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 →

Guarding the desk's input and output

An input guardrail is a check that runs before the model and stops the run when its tripwire fires, so a message with a password never reaches the desk.

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

The desk from The desk agent and its tools answers whatever it is asked. A guardrail, from Input guardrails and the tripwire, sits in front of it and refuses input you do not want the model to see.

The pieces, and where each came from

PieceFrom lesson
The desk with its lookup toolThe desk agent and its tools
@input_guardrail returning GuardrailFunctionOutputInput guardrails and the tripwire
InputGuardrailTripwireTriggered on a blockInput guardrails and the tripwire

The password check

A guardrail is a function with @input_guardrail. It returns a GuardrailFunctionOutput; setting tripwire_triggered=True stops the run.

python
@input_guardrail
async def no_passwords(ctx, agent, user_input) -> GuardrailFunctionOutput:
    text = user_input if isinstance(user_input, str) else str(user_input)
    tripped = "password" in text.lower()   # True blocks the run
    return GuardrailFunctionOutput(output_info={"blocked": tripped},
                                   tripwire_triggered=tripped)

The guarded desk

The check goes in the desk's input_guardrails list, so it runs before the model on each run.

python
desk = Agent(
    name="Shop desk",
    instructions="Help shoppers with their orders.",
    tools=[lookup_order],
    input_guardrails=[no_passwords],
    model=ShopModel(),
)

A safe run and a blocked run

A safe message answers as before; a message with a password raises InputGuardrailTripwireTriggered, which you catch.

python
print("SAFE:", Runner.run_sync(desk, "Where is my order A17?").final_output)
try:
    Runner.run_sync(desk, "My password is hunter2, refund me now")
except InputGuardrailTripwireTriggered:
    print("BLOCKED: the input guardrail tripped, the model never ran")

The desk refusing a password

One safe run and one blocked run, side by side.

Example
from agents import (Agent, Runner, function_tool, set_tracing_disabled,
    input_guardrail, GuardrailFunctionOutput, InputGuardrailTripwireTriggered,
    RunContextWrapper)
from shop_model import ShopModel
set_tracing_disabled(True)

@function_tool
def lookup_order(order_id: str) -> str:
    "Look up an order by its id."
    return f"Order {order_id}: shipped on 3 March, arriving 7 March."

@input_guardrail
async def no_passwords(ctx: RunContextWrapper, agent: Agent, user_input) -> GuardrailFunctionOutput:
    text = user_input if isinstance(user_input, str) else str(user_input)
    tripped = "password" in text.lower()
    return GuardrailFunctionOutput(output_info={"blocked": tripped}, tripwire_triggered=tripped)

desk = Agent(
    name="Shop desk",
    instructions="Help shoppers with their orders.",
    tools=[lookup_order],
    input_guardrails=[no_passwords],
    model=ShopModel(),
)

print("SAFE:", Runner.run_sync(desk, "Where is my order A17?").final_output)
try:
    Runner.run_sync(desk, "My password is hunter2, refund me now")
except InputGuardrailTripwireTriggered:
    print("BLOCKED: the input guardrail tripped, the model never ran")

What the guardrail did

  • The safe message passed the check, so the run reached the model and the tool answered normally.
  • The password message tripped the wire, so the SDK raised InputGuardrailTripwireTriggered before the model saw a single word.
  • Catching the exception is how your code turns a trip into a polite refusal instead of a crash.

Input guardrail vs output guardrail

GuardrailWhen it runs, and on what
Input guardrailBefore the model, on the run's first agent, checking the incoming message
Output guardrailAfter the model, on the final answer, checking what the agent produced

When to guard the desk

  • Refuse secrets or unsafe requests before the model reads them, so they never enter a prompt or a log.
  • Check the final answer with an output guardrail when a reply must never leak a price, a policy, or a rule.
Watch out. An input guardrail runs only on the first agent of a run, per the guardrails docs. After a handoff the specialist is not re-checked, so put the guard on the agent the run starts with.
Try it yourself
  • Change the banned word from password to your own and watch a new message get blocked.
  • Remove the try/except and read the traceback the tripwire raises.
  • Return tripwire_triggered=False always and confirm the password message now reaches the model.

You understood something today that you didn't yesterday.