OpenAI Agents SDK Guardrails in Practice: Blocking Dangerous Inputs and Outputs

OpenAI Agents SDK Guardrails provide three decorator-based security layers to intercept unsafe inputs, outputs, and tool calls in production AI Agents.
This article covers the Guardrails mechanism in the OpenAI Agents SDK, which splits AI Agent security into three layers: Input Guardrails block non-compliant input before the model runs, Output Guardrails filter dangerous responses after generation, and Tool Guardrails intervene after arguments are known but before side effects occur. All three are implemented via Python decorators returning standard output objects with a `tripwire_triggered` field. The `run_in_parallel` parameter also lets you choose between parallel or serial execution, directly affecting latency and token cost tradeoffs.
What Are Guardrails: Three Layers of Agent Security
When building production-grade AI Agents, one unavoidable challenge is: how do you prevent certain inputs from reaching the model, and how do you intercept outputs that shouldn't be returned to users? The Guardrails mechanism in the OpenAI Agents SDK is designed exactly for this purpose.
As explained in this YouTube tutorial, Guardrails are essentially "checks that run around an agent," organized into three layers:
- Input Guardrail: Inspects user input before the model runs
- Output Guardrail: Checks the response after the model generates an answer
- Tool Guardrail: Intercepts tool calls before they execute
The video uses a vivid analogy — "the hidden village cannot allow the Agent to teach forbidden jutsu." Whether a user is trying to coerce the model into revealing sensitive information, or the model itself attempts to perform dangerous operations through tool calls, all of these can be blocked layer by layer through these three guardrails.
Input Guardrail: Blocking Before the Model Runs
The Input Guardrail is a decorator that runs before the model is invoked. To implement it, you need to import several core objects from the SDK: Agent, GuardrailFunctionOutput, RunContextWrapper, and input_guardrail.
GuardrailFunctionOutput determines what the guardrail function returns, while RunContextWrapper is used to pass and hold context values during execution and hand them off to callbacks.
In practice, you define a function (e.g., block_input) that accepts three parameters — context, agent, and user input (typed as string or list) — and apply the @input_guardrail decorator to transform it into a guardrail. The function's return type must be GuardrailFunctionOutput.

Since the input may be a list, the logic first normalizes it into text: use it directly if it's a string, otherwise convert it. It then returns a GuardrailFunctionOutput with two key parameters:
output_info: Additional metadata (such as a reason or score); the example passesNonetripwire_triggered: The trigger condition — set to triggered when the text contains "forbidden jutsu"
Once the tripwire fires, the SDK raises an InputGuardrailTripwireTriggered exception, preventing the request from reaching the model.
A decorator is Python syntactic sugar — essentially a higher-order function that takes a function and returns a new one, applied using the @decorator_name syntax above a function definition. In the OpenAI Agents SDK, the @input_guardrail decorator "registers" an ordinary Python function as a guardrail checker, allowing the SDK to invoke it automatically at the right moment. Developers don't need to manually embed check logic into the call chain — the SDK manages guardrail triggering and exception throwing internally. The name tripwire is also worth understanding: it borrows from the concept of a physical trip wire that triggers an alarm. Once tripwire_triggered=True, the SDK immediately halts the current flow and raises the corresponding exception — rather than waiting for the entire pipeline to finish. This "fail early" design pushes security concerns to the earliest possible interception point.
Output Guardrail: Checking After the Answer Is Ready
The structure of the Output Guardrail is nearly identical to the Input Guardrail — the only difference is when it runs. It executes after the model has generated an answer (run after the answer is ready), whereas the Input Guardrail runs before the model is called.

To implement it, import output_guardrail instead of input_guardrail. The function still accepts context, agent, and output as parameters and returns a GuardrailFunctionOutput. The guardrail triggers when the output contains "forbidden jutsu."
The video uses a ScriptedModel to construct two dummy responses for verification: one query mentions forbidden jutsu in the input, the other in the output. Running the tests clearly shows — the first triggers InputGuardrailTripwireTriggered, and the second triggers OutputGuardrailTripwireTriggered, with each layer handling its own responsibility.
Tool Guardrail: The Final Line of Defense Before Tool Execution
The third layer targets tool calls. Using the @tool_input_guardrail decorator, it intervenes right before the tool runs.

The tool guardrail's return object is ToolGuardrailFunctionOutput, which supports three actions: allow, reject, or raise error.
The example logic checks whether data.context.tool_arguments (lowercased) contains the forbidden string:
- If it does, call
ToolGuardrailFunctionOutput.reject_contentand return a rejection message like "That jutsu is forbidden by the hidden village" - If it doesn't, return
allowto proceed normally
A regular function (e.g., use_jutsu) is then converted into a tool using @function_tool, with the tool_input_guardrail list attached to it. In testing, "forbidden ceiling jutsu" is blocked and returns the forbidden jutsu message, while "fireball jutsu" executes normally — confirming precise, argument-level interception.
Understanding this requires knowing how the @function_tool decorator works: it's how the OpenAI Agents SDK exposes an ordinary Python function as a tool available for model invocation (function calling). The model doesn't execute code directly during inference — it outputs a structured "tool call intent" (containing the tool name and arguments), and the SDK parses that intent before actually invoking the corresponding function. The Tool Guardrail intervenes in the gap between "SDK parses the intent" and "function actually executes" — at a point where tool arguments are already determined but side effects haven't occurred yet. This makes Tool Guardrails especially effective against prompt injection attacks: an attacker might craft malicious user input to coax the model into generating tool calls with harmful parameters, and the Tool Guardrail can intercept these before they ever reach external systems like databases or APIs.
run_in_parallel: Balancing Performance and Cost
One detail worth exploring from the video is the run_in_parallel parameter on Input Guardrails, which directly affects how guardrails and model calls execute relative to each other.

run_in_parallel=True: The guardrail and the first model call start simultaneously. If the guardrail trips, the SDK cancels the in-progress model call. Responses are faster, but you may have already initiated one model call.run_in_parallel=False: The guardrail check runs first; the model is only invoked after passing. This is slower but avoids unnecessary model calls (i.e., saves token costs).
This is a classic latency-vs-cost tradeoff. If response speed matters most, choose parallel; if you want to strictly minimize API call costs, choose serial. The right choice depends on your business requirements.
Understanding this tradeoff requires knowing how LLM APIs are billed: typically by the number of input and output tokens, and every request sent incurs a charge regardless of whether the result is used. When run_in_parallel=True, both the guardrail check and model inference start simultaneously — even if the guardrail eventually triggers and cancels the model call, the tokens consumed by that already-dispatched request still appear on the bill. For scenarios with high trigger rates (e.g., high-traffic applications with many malicious or non-compliant inputs), parallel mode can generate significant additional costs. Conversely, run_in_parallel=False increases end-to-end latency (due to waiting serially for the guardrail to pass) but achieves zero wasted calls. When designing your system, estimate the cost difference between the two modes based on your expected violation rate, then weigh that against how sensitive your users are to response latency.
End-to-End Validation with a Real LLM
The tutorial wraps up by stringing all three guardrail layers together using real LLM calls (requires an OpenAI API Key). A count_model_calls callback function tracks how many model calls actually occur, making it easy to observe the difference between parallel and serial modes.
The combined test results show:
- Input contains forbidden jutsu → triggers
InputGuardrailTripwireTriggered - Output contains forbidden jutsu → triggers
OutputGuardrailTripwireTriggered - Calling the "forbidden ceiling jutsu" tool → intercepted by the tool guardrail, returns forbidden jutsu message
- Calling the "fireball jutsu" tool → executes normally and returns a result
One additional note: inside @function_tool, you can use name_override to map a function's real name to the tool name used during model invocation, giving you more flexibility in naming your tools.
Summary
Guardrails are a critical step in taking an AI Agent from a "toy demo" to a production-ready system. The OpenAI Agents SDK abstracts security checks into three layers of decorators — input, output, and tool — so developers only need to focus on returning GuardrailFunctionOutput / ToolGuardrailFunctionOutput and setting tripwire conditions. Combined with run_in_parallel for fine-tuning the performance-vs-cost balance, you can design flexible protection strategies for different scenarios. For any Agent application serving real users, this mechanism deserves a place in your architecture from day one.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.