NeMo Guardrailsnemoguardrails 0.24.1 · Python 3.10+
Dashboard
0%
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:

python
RailOutcome.allow()
RailOutcome.block(reason="...")
RailOutcome.transform([(TransformTarget.BOT_MESSAGE, "new text")])

The three decisions

Example
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)
  • 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

Example
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)

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 isReturn
Read by an if in your own flowAnything: a list, a bool, a string
Standing in for a library railRailOutcome
Rewriting instead of refusingRailOutcome.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.
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.