1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
37 small wins to finish your pathNext lesson →
RailOutcome
RailOutcome is the object a rail's action returns to tell NeMo what to do with a message: allow it, block it, or transform it.
Last updated: 30 Sep, 2026 · NeMo Guardrails 0.24.1
The Custom input rail used two of the three decisions. This lesson looks at the object itself and at the older style it replaced.
Syntax:
RailOutcome.allow()
RailOutcome.block(reason="...")
RailOutcome.transform([(TransformTarget.BOT_MESSAGE, "new text")])The three decisions
from nemoguardrails.actions.rail_outcome import RailOutcome, TransformTarget
print(RailOutcome.allow().decision, RailOutcome.allow().is_blocked)
print(RailOutcome.block(reason="found ssn").decision, RailOutcome.block().is_blocked)
rewrite = RailOutcome.transform([(TransformTarget.BOT_MESSAGE, "redacted")])
print(rewrite.decision, rewrite.transforms[0].text)Output
RailDecision.ALLOW False RailDecision.BLOCK True RailDecision.TRANSFORM redacted
- allow lets the content through unchanged.
- block stops it; the outcome carries no refusal wording, the flow says that.
- transform replaces a value: the user message, the bot message or retrieved chunks.
What it replaced
from nemoguardrails.actions import action
try:
@action(output_mapping=lambda value: not value)
async def old_style():
return True
except TypeError as error:
print("TypeError:", error)Output
TypeError: action() got an unexpected keyword argument 'output_mapping'
Older releases let an action return a plain value and told the runtime how to read it with output_mapping. That argument is gone and passing it raises. Tutorials from before release 0.22 still show it.
Allow, block or transform
| Your action is | Return |
|---|---|
Read by an if in your own flow | Anything: a list, a bool, a string |
| Standing in for a library rail | RailOutcome |
| Rewriting instead of refusing | RailOutcome.transform, or assign in the flow |
Where you meet it
- Every library rail's action returns one, which is why the library flows read
$response.is_blocked. - Your own rails, when you want them to behave like the library's.
Watch out. The documentation says
metadata must not be load-bearing. Code that decides what to do reads decision or is_blocked, never a key in metadata.Related
- Previous: Custom input rail
- Next: Output rails
- Reference: Rail outcomes
Try it yourself
- Call
RailOutcome.transform([])and read the error. - Build
RailOutcome.block(metadata={"score": 0.91})and print it.
Little by little, you're building something great.