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 →

Output guardrails on the final answer

An output guardrail is a check that runs on the agent's final answer after the model produces it, and it can trip a tripwire that blocks that answer.

Last updated: 28 Sep, 2026 · openai-agents 0.22.3

An output guardrail runs on the final output of the last agent in a run. It reads the finished text and decides whether the caller is allowed to see it. This is where you catch an answer that leaked something it should not.

The @output_guardrail decorator

python
from agents import output_guardrail, GuardrailFunctionOutput

@output_guardrail
async def guard(ctx, agent, answer):             # runs after the model
    bad = "card" in answer.lower()
    return GuardrailFunctionOutput(
        output_info={"leaked_card": bad},
        tripwire_triggered=bad,                  # True blocks the answer
    )

A tool that returns sensitive text

To give the guardrail something to catch, a tool returns an order line that includes a card detail. The model will hand this text back as the final answer.

python
from agents import function_tool

@function_tool
def lookup_order(order_id: str) -> str:
    "Look up an order by id."
    return f"Order {order_id}: shipped, card ending 4242."

The output guardrail

The function takes the context, the agent, and the final answer string. It trips the tripwire when the answer mentions a card.

python
@output_guardrail
async def no_card_numbers(ctx, agent, answer):
    leaked = "card" in answer.lower()
    return GuardrailFunctionOutput(
        output_info={"leaked_card": leaked},
        tripwire_triggered=leaked,
    )

Attaching it and catching the tripwire

Pass the guardrail in output_guardrails. When it trips, the run raises OutputGuardrailTripwireTriggered, which carries the same result object.

python
from agents import Agent, Runner, OutputGuardrailTripwireTriggered
from shop_model import ShopModel

agent = Agent(name="Shop", instructions="Help with orders.", tools=[lookup_order],
              model=ShopModel(), output_guardrails=[no_card_numbers])

A leaked card number, blocked

The same pieces in one file. A greeting passes; an order lookup returns the card line and is blocked.

Example
from agents import (Agent, Runner, function_tool, set_tracing_disabled,
    output_guardrail, GuardrailFunctionOutput, OutputGuardrailTripwireTriggered)
from shop_model import ShopModel
set_tracing_disabled(True)

@function_tool
def lookup_order(order_id: str) -> str:
    "Look up an order by id."
    return f"Order {order_id}: shipped, card ending 4242."

@output_guardrail
async def no_card_numbers(ctx, agent, answer):
    leaked = "card" in answer.lower()
    return GuardrailFunctionOutput(
        output_info={"leaked_card": leaked},
        tripwire_triggered=leaked,
    )

agent = Agent(name="Shop", instructions="Help with orders.", tools=[lookup_order],
              model=ShopModel(), output_guardrails=[no_card_numbers])

for question in ["hello there", "where is my order?"]:
    try:
        result = Runner.run_sync(agent, question)
        print("OK:", result.final_output)
    except OutputGuardrailTripwireTriggered as e:
        print("BLOCKED:", e.guardrail_result.output.output_info)

Why the order lookup was blocked

  • The greeting returns a generic reply with no card in it, so the guardrail passes and you see the text.
  • The order question makes the model call lookup_order, whose result mentions a card. That text becomes the final answer.
  • The output guardrail reads that final answer, finds card, and trips the tripwire, so the run raises OutputGuardrailTripwireTriggered instead of returning the text.

Input guardrail vs output guardrail

GuardrailRuns onWhen it runs
input_guardrailsThe user's input to the first agentBefore the model is called
output_guardrailsThe final answer of the last agentAfter the model produces the answer

When to guard the output

  • Catching a reply that includes card numbers, tokens, or another person's details.
  • Rejecting an answer whose format is wrong before it reaches the user.
  • Adding a policy check that only the finished text can be judged against.
Watch out. An output guardrail runs on the final output of the last agent only. A message produced by an earlier agent that then hands off is not the final output, so it is not checked here.
Try it yourself
  • Change the banned token from card to shipped and rerun the greeting.
  • Make lookup_order return a line with no card and confirm the order question now passes.
  • Add a second output guardrail and see which one's exception is raised first.

This is what real progress feels like.