Guardrails AIguardrails-ai 0.11.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
27 small wins to finish your pathNext lesson

refrain and filter

Lesson 10's fix assumes a wrong answer can be made right. Sometimes the right move is to send nothing, and Guardrails has two actions for that.

Example
from guardrails import Guard
from guardrails_ai.valid_length import ValidLength

for action in ["noop", "refrain", "filter"]:
    desk = Guard().use(ValidLength(min=1, max=20, on_fail=action))
    outcome = desk.validate("Order 8821 is running late and arrives Friday.")
    print(action, "->", repr(outcome.validated_output))

refrain means the answer is not safe to show, so no answer is shown. On a plain string filter does the same thing, which the documentation warns about: filtering is meant for structured output, where it removes only the field that failed. Lesson 18 has an object with fields and picks that up.

Why it is None and not an empty string

The value Guardrails kept internally is not None.

Example
desk = Guard().use(ValidLength(min=1, max=20, on_fail="refrain"))
outcome = desk.validate("Order 8821 is running late and arrives Friday.")

print(repr(outcome.validated_output))
print(repr(desk.history.last.iterations.last.guarded_output))
print(desk.history.last.status)

The iteration holds an empty string, which is what refraining produces for a text output. The outcome holds None, because Call.guarded_output returns a value only when the Guard passed or every failure was a noop, and this one was neither.

That rule is worth keeping in mind for the rest of the course. validated_output being None does not tell you what happened; it tells you the Guard is not willing to vouch for anything. The history says which of the reasons applied.

Which one to reach for

  • refrain when showing a wrong answer is worse than showing none. A refund promise, a made-up delivery date, a leaked address.
  • filter when the answer has parts and only one part is bad. That needs structured output, so it waits for lesson 18.
  • exception when your own code should decide. Refraining returns a quiet None that is easy to pass along by accident.
Try it yourself
  • Swap refrain for exception and decide which one your support desk should use. Write down why.
  • Run the loop again with a value that passes and print validated_output for all three actions.
  • Print outcome.error after a refrain. It is None, because refusing to answer is not an error.

Little by little, you're building something great.