OpenAI Agents SDKopenai-agents 0.22 · Python 3.10+
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
25 small wins to finish your pathNext lesson

Guarding what comes out

The other half. An input guardrail decides what the agent is allowed to hear; an output guardrail decides what the customer is allowed to see.

python
@output_guardrail
async def no_promises(context, agent, agent_output):
    """Never let the agent promise a delivery date."""
    promised = "guarantee" in str(agent_output).lower()
    return GuardrailFunctionOutput(
        output_info={"promised": promised},
        tripwire_triggered=promised,
    )

Same shape as lesson 16, with one difference in the arguments: this one is handed the agent's answer instead of the user's question.

Example
for agent in (careful, reckless):
    try:
        result = await Runner.run(agent, "when will it arrive?")
        print(f"{agent.name:<9} -> {result.final_output}")
    except OutputGuardrailTripwireTriggered:
        print(f"{agent.name:<9} -> blocked, the customer never saw it")

The reckless agent produced its answer, the guardrail read it, and the run raised OutputGuardrailTripwireTriggered before anything reached the customer.

Only on the last agent

The mirror of lesson 16, and the docs are equally explicit: an agent's output guardrails only run if that agent is the last one, the one that actually produced the final answer.

In a handoff chain that is the agent the work ended up with, not the one you started. If Triage hands to Billing, Billing's output guardrails run and Triage's do not.

Which means a rule you want applied to everything the customer ever sees has to go on every agent that can finish a run. There is no single place to put it.

The awkward part

The model call already happened. You paid for it, and the answer exists. An output guardrail cannot save you money, only save you from sending something.

So the two are for different jobs. Input guardrails are cheap and catch whole categories of request. Output guardrails are the last line, for the things you cannot describe in advance and can only recognise when you see them.

Input guardrailOutput guardrail
Runsbefore the modelafter the model
Costsnothingthe model call you are about to discard
Catchesquestions you will not answeranswers you will not send
Typical useoff topic, prompt injection, abusepromises, private data, wrong tone
What to do when it fires
When one fires, you still have to answer the customer somehow. Catch the exception and reply with something fixed, or run a second, more careful agent. Letting the exception reach the user is not a plan.
Try it yourself
  • Ban a second word and try an answer containing it.
  • Catch the exception and print a fixed apology instead.
  • Read output_info off the exception and log which rule fired.

You understood something today that you didn't yesterday.