Part 4: Tripwire handling

The input guardrail is attached, but a blocked request currently raises an exception in the notebook. In this step we catch the tripwire exception and return a normal blocked message.

Catch one blocked call

Run the guarded agent inside a try block:

try:
    result = await Runner.run(guarded_faq_agent, "How do I cook pizza?")
    print(result.final_output)
except InputGuardrailTripwireTriggered as e:
    print(f"[BLOCKED] {e.guardrail_result.output.output_info}")

Expected output:

[BLOCKED] The question is about cooking, not data engineering.

The guardrail result is nested because the SDK preserves the full guardrail run. For a notebook or app, you usually want the short output_info string.

This is the shape you want in a product. If a UI has already started showing output, replace it with the guardrail response. If you call through an API, this is the same kind of flow as a refusal: the user gets a controlled blocked message instead of the agent's attempted answer.

Extract a helper

Wrap the pattern in one function:

async def run_with_input_guardrail(agent, user_input):
    """Run an agent with input guardrail handling."""
    try:
        result = await Runner.run(agent, user_input)
        return result.final_output
    except InputGuardrailTripwireTriggered as e:
        return f"[BLOCKED] {e.guardrail_result.output.output_info}"

This helper keeps SDK exception details out of the rest of the notebook. That is the same shape you would want in an app endpoint: callers ask for an answer and receive either the answer or a blocked message.

Test allowed and blocked prompts

Run a relevant course question:

response = await run_with_input_guardrail(
    guarded_faq_agent,
    "How do I submit homework?"
)
print(f"Q: How do I submit homework?\n{response}\n")

The FAQ assistant should run normally because the topic check passes.

Now run the pizza prompt:

response = await run_with_input_guardrail(
    guarded_faq_agent,
    "What's the best pizza recipe?"
)
print(f"Q: What's the best pizza recipe?\n{response}")

A typical blocked response looks like this:

Q: What's the best pizza recipe?
[BLOCKED] About cooking, not course

The exact reasoning text can vary because the guardrail is an LLM call. The stable contract is the prefix and the fact that the FAQ assistant does not answer the cooking question.

Input guardrail behavior

Now the workshop has an enforced input boundary:

  • Related questions proceed to faq_agent.
  • Unrelated questions raise InputGuardrailTripwireTriggered.
  • The helper catches the exception and returns a blocked response.

This is stronger than asking the FAQ assistant to stay on topic. The off-topic message is blocked before the assistant has a chance to answer.

Continue with Part 5: Output guardrail to check the assistant response before returning it to the user.

Questions & Answers (0)

Sign in to ask questions