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

A function as on_fail

Lessons 9 to 11 picked from a fixed list. When none of them fits, on_fail takes a function, and the function decides what the Guard hands back.

Example
def to_store_credit(value, fail_result):
    return value.replace("refund", "store credit")


desk = Guard().use(NoRefunds(on_fail=to_store_credit))
outcome = desk.validate("We can refund order 8821 in full.")

print(outcome.validation_passed)
print(outcome.validated_output)

The signature is fixed: the value that failed, then the FailResult the validator returned. Whatever the function returns becomes validated_output. The validator itself did not change and still has no fix_value; the repair moved out to the place that knows what this particular desk wants.

Reading the failure

The second argument is the object from lesson 7, so the function can use anything the validator recorded.

Example
def explain(value, fail_result):
    return f"[held back: {fail_result.error_message}]"


desk = Guard().use(NoRefunds(on_fail=explain))

print(desk.validate("We can refund order 8821 in full.").validated_output)
print(desk.validate("Order 8821 ships today.").validated_output)

It counts as resolved

A custom handler and a noop both hand a value back, and the Guard treats them completely differently.

Example
quiet = Guard().use(NoRefunds(on_fail="noop"))
handled = Guard().use(NoRefunds(on_fail=explain))
text = "We can refund order 8821 in full."

print("noop    ", quiet.validate(text).validation_passed, quiet.history.last.status)
print("function", handled.validate(text).validation_passed, handled.history.last.status)

noop leaves the failure unresolved, so the call stays a failure and validation_passed is False. A function is treated as a repair, like fix, so the call passes. The validator failed in both runs, and history.last.validator_logs says so in both runs.

Inside Guardrails the function shows up as the action named custom, which is the entry in lesson 9's enum you never set by hand.

Try it yourself
  • Return None from the function and see what validated_output becomes.
  • Raise an exception inside the function instead of returning. That is a third way to get exception behaviour, with your own message.
  • Use fail_result.error_spans in the function to cut only the offending characters out of the reply.

You understood something today that you didn't yesterday.