OpenAI Agents SDK Guardrails
Guardrails are the safety and reliability layer of the OpenAI Agents SDK. They allow you to validate inputs before an agent acts and verify outputs before they reach the user, all without cluttering your agent logic. This article is a practical, implementation‑focused guide: you’ll learn how to define input and output guardrails, enforce policies, protect tool execution, and build a robust safety net around your production agents.
What Are Guardrails in the OpenAI Agents SDK
Guardrails are declarative validation functions that the SDK runs automatically at the boundaries of an agent’s execution. They act as circuit breakers:
- Input guardrails run before the agent processes a user message. They can block the request entirely if it’s invalid, dangerous, or out of policy.
- Output guardrails run after the agent produces a final answer. They can verify the response meets format, content, or quality standards, and can even rewrite it before returning it to the user.
- Runtime checks – while not a separate built‑in type – can be implemented inside tools and event handlers to monitor execution in‑flight.
Guardrails are defined as asynchronous Python functions and attached directly to agents. The Runner invokes them at the correct moment, so you don’t need to write wrapping logic.
A simple example: rejecting empty input.
from agents import input_guardrail, GuardrailResult
@input_guardrail
async def reject_empty_input(context, agent, input):
if not input or not input.strip():
return GuardrailResult(blocked=True, message="Input cannot be empty.")
return GuardrailResult(blocked=False)
Attach it to an agent:
agent = Agent(
name="Assistant",
instructions="Be helpful.",
input_guardrails=[reject_empty_input],
...
)
Now, if a user sends an empty string, the agent will never run. Instead, the Runner returns the guardrail’s error message.
Why Guardrails Matter
Unchecked inputs and outputs are the root cause of many agent failures. Guardrails directly address:
- Prevent invalid execution – stop malformed or malicious requests before they reach the LLM.
- Improve reliability – enforce response schemas and formats, so downstream code always gets well‑shaped data.
- Reduce hallucinations – catch responses that lack required citations or contain disallowed content.
- Enforce business rules – ensure that an agent never gives legal advice, shares confidential information, or exceeds its mandate.
- Protect downstream systems – validate tool calls and their arguments, preventing harmful actions.
- Improve production safety – act as a safety net that catches errors the model itself might miss.
In short, guardrails convert implicit trust into explicit, auditable checks.
How Guardrails Work
The Runner integrates guardrails into the execution loop:
- Input Guardrail – the SDK calls all input guardrail functions sequentially. If any returns
blocked=True, the run terminates immediately, returning the guardrail’s message. The agent is never invoked. - Agent Execution – if all input guardrails pass, the agent reasons, calls tools, and eventually produces a final answer.
- Output Guardrail – after the agent finishes, the SDK runs output guardrails on the final text. If a guardrail blocks, the output can be discarded or replaced. The guardrail can also return a modified version of the output.
Guardrails are non‑blocking in the sense that they don’t interfere with each other; each is called independently. However, the first input guardrail to block stops the run.
Core Guardrail Concepts
| Concept | Role |
|---|---|
| Input Validation | Verify the user’s message before the agent processes it. |
| Output Validation | Verify the agent’s final response before sending it to the user. |
| Runtime Checks | Monitor and validate actions during execution (tool arguments, resource usage). |
| Policy Enforcement | Apply business or safety rules that the agent must follow. |
| Failure Handling | Define what happens when a guardrail blocks—return an error, rewrite the output, or escalate. |
These concepts are implemented via the input_guardrail, output_guardrail, and by placing validation logic inside tool functions.
Input Guardrails
What Are Input Guardrails
Input guardrails are async functions decorated with @input_guardrail. They receive:
context– theRunContext(contains session info, metadata).agent– the current agent being run.input– the user’s message as a string.
They return a GuardrailResult with:
blocked(bool) – whether to stop the run.message(str) – an error message to return if blocked.- (Optionally)
output_data– to pass additional information.
Example: blocking forbidden words.
@input_guardrail
async def block_profanity(context, agent, input):
forbidden = ["offensive1", "offensive2"]
if any(word in input.lower() for word in forbidden):
return GuardrailResult(blocked=True, message="Inappropriate language detected.")
return GuardrailResult(blocked=False)
Attaching multiple guardrails: agents accept a list. All are evaluated; the first to block stops the run.
agent = Agent(
input_guardrails=[reject_empty_input, block_profanity],
...
)
Common Validation Rules
- Length checks – reject empty or overly long inputs.
- Content checks – block sensitive words, PII patterns (emails, credit cards).
- Schema validation – when input is expected to be JSON, validate with Pydantic.
- Authentication – verify that a user token is present in the context.
Output Guardrails
What Are Output Guardrails
Output guardrails validate the agent’s final answer. They are async functions decorated with @output_guardrail. They receive context, agent, and output (the final text).
A guardrail can:
- Block the output and return an error (similar to input guardrails).
- Rewrite the output: return a
GuardrailResult(blocked=False, output_data=new_output_string). - Pass through unchanged.
Example: ensure a response ends with a citation.
@output_guardrail
async def require_citation(context, agent, output):
if "Source:" not in output:
return GuardrailResult(blocked=True, message="Response must include a Source citation.")
return GuardrailResult(blocked=False)
Rewriting output – to append a disclaimer:
@output_guardrail
async def add_disclaimer(context, agent, output):
disclaimer = "\n\n*This response was generated by AI. Verify critical information.*"
return GuardrailResult(blocked=False, output_data=output + disclaimer)
Structured Output Validation
When you use the output_type parameter on an agent, the SDK enforces a JSON schema automatically. However, you can add extra semantic checks via guardrails. For example, if the output must contain a specific field, validate it.
class SupportResponse(BaseModel):
sentiment: str
resolution: str
@output_guardrail
async def validate_response_fields(context, agent, output):
try:
data = json.loads(output)
SupportResponse(**data)
return GuardrailResult(blocked=False)
except:
return GuardrailResult(blocked=True, message="Output not in required format.")
Runtime Guardrails
While not a separate SDK feature, runtime checks are a critical third dimension of agent safety. They are implemented inside tool functions and event handlers.
- Tool usage restrictions – validate tool arguments before executing the external action. For example, ensure a
send_emailtool is called only for internal addresses. - Tool argument validation – use Pydantic models inside the tool to reject malformed calls; return an error string that the model can self‑correct.
- Resource limits – track and enforce token budgets, maximum tool calls, or conversation length from inside the tool or via a custom
RunContextfield. - Timeout enforcement – set
asyncio.wait_foraround tool execution to prevent hanging. - Cost limits – inside a tool that calls an expensive API, check cumulative cost and return a “budget exceeded” message.
Example: a tool that rejects large transfers.
@function_tool
def transfer_funds(amount: float, recipient: str) -> str:
if amount > 10000:
return "Error: transfers above $10,000 require manual approval."
# proceed with transfer...
By embedding runtime checks directly into tools, you add a layer of defense that the model cannot bypass.
Policy Enforcement
Guardrails are the enforcement arm of your agent’s operational policies. Policies might include:
- Allowed actions – only certain tools or APIs may be called for certain user tiers. Use input guardrails to check
context.user_tierand block unsupported requests early. - Restricted topics – an agent must refuse to answer questions about illegal activities. Input guardrails detect topic keywords; output guardrails double‑check the final response.
- Data access rules – before the agent queries a database, an input guardrail verifies that the user has permission (by checking
context.user_id). - Approval requirements – use a combination of an output guardrail that sends the response for human review and a custom
output_datato pause the flow.
Policies are business‑level rules. Guardrails translate them into executable code that runs on every interaction.
Guardrails and Tool Calling
Guardrails protect tool execution in two ways:
- Before tool calls – Input guardrails can indirectly prevent dangerous tool calls by blocking requests that would lead to them (e.g., a request containing “delete all records”). However, they don’t inspect the tool call arguments directly. For that, validate arguments inside the tool function itself.
- After tool calls – The model may generate text that includes tool results. Output guardrails can verify that the final response doesn’t leak sensitive data from a tool call (e.g., full credit card numbers).
Thus, a layered approach is best:
- Input guardrails for top‑level content filtering.
- Tool‑internal validation for argument safety.
- Output guardrails for final content quality and data leakage.
Guardrails and Handoffs
Handoffs transfer conversation responsibility. Guardrails can be used to enforce safety at each step:
- The source agent’s input guardrails run before the handoff decision; if the original request is unsafe, the handoff never occurs.
- The target agent may have its own input guardrails, but they do not run again on the existing conversation (the user’s message is not re‑evaluated). However, you can attach a guardrail to the source agent that validates the handoff before it happens, by using a custom output guardrail that inspects the source agent’s final message (which could be a handoff call). This is advanced but possible.
- More commonly, you rely on the target agent’s output guardrails to ensure the final answer meets quality standards.
A practical pattern: the triage agent (source) has input guardrails to block harmful requests. The specialist agent (target) has output guardrails to ensure its answer contains required disclaimers. This way, safety is maintained across the entire flow.
Guardrail Lifecycle
The lifecycle from request to response, with guardrails inserted:
- Request received – the user message enters the system.
- Input validation – all input guardrails run; if any block, the process ends with an error message.
- Agent execution – the agent processes the input, using tools, possibly handing off.
- Output generated – the agent produces a final text output.
- Output validation – output guardrails inspect the text. They can block, rewrite, or pass.
- Response delivery – the final (possibly rewritten) output is returned to the user.
Each guardrail has access to the RunContext, so you can log failures and track guardrail metrics.
Common Guardrail Patterns
| Pattern | Description | Example |
|---|---|---|
| Input Validation | Reject malformed or unsafe requests. | Empty input, SQL injection attempts, hate speech. |
| Output Validation | Ensure response meets format/content rules. | Must contain JSON, must be under 2000 characters, no PII. |
| Approval Pattern | Pause and wait for human sign‑off on the output. | Use an output guardrail to send the response to a review queue and return a “pending approval” message. |
| Safety Filter | Remove or replace prohibited content. | Mask credit card numbers, remove toxic language. |
| Budget Control | Enforce per‑session or per‑request cost limits. | An input guardrail checks remaining budget; a tool guardrail counts against it. |
These patterns can be mixed and matched per agent.
Failure Handling
When a guardrail blocks, the outcome depends on where it fires.
- Input guardrail blocks –
Runner.run()returns aRunResultwherefinal_outputis the guardrail’s error message. You can inspectresult.last_agentandresult.input_guardrail_resultsto see which guardrail failed. - Output guardrail blocks – the final output is replaced by the guardrail’s error message, unless the guardrail rewrites it. The original agent’s output is discarded.
- Policy violations – should be logged immediately (use
context.add_eventor logging). You can also raise a custom exception inside the guardrail to trigger retries.
Recovery strategies:
- If an output guardrail fails, you might re‑run the agent with an additional instruction based on the guardrail’s feedback.
- For critical failures, escalate to a human operator via an incident ticket.
Security Considerations
Guardrails are a frontline defense. Implement them with security in mind:
- Sensitive data protection – Use input guardrails to detect and reject PII early. Use output guardrails to redact any PII that slipped through.
- Prompt injection defense – Input guardrails can look for patterns like “ignore previous instructions” and block them.
- Tool abuse prevention – While guardrails don’t directly inspect tool calls, a strong input guardrail that restricts the types of requests can limit the agent’s ability to call dangerous tools.
- Unauthorized actions – Use runtime checks inside tools to verify permissions based on
context.user_id. - Data leakage prevention – Output guardrails can scan for internal URLs, secret keys, or confidential project names and mask them.
Performance Considerations
Guardrails are async functions that run in the request path. Keep them fast to avoid adding latency.
- Validation overhead – simple string checks are negligible; heavy API calls (e.g., external content moderation) should be used judiciously or moved to an asynchronous pipeline that doesn’t block the user response.
- Schema complexity – validating large Pydantic models is cheap; validating against a large list of forbidden words is also fast. The primary cost is any I/O inside the guardrail.
- Optimization strategies – cache results of expensive checks (e.g., user permission lookups) across turns using the session store.
Common Beginner Mistakes
- No output validation – trusting the model’s raw output leads to formatting errors and compliance issues.
- Excessive guardrails – too many checks slow down every request and may cause false positives that frustrate users.
- Weak validation rules – guardrails that are too lenient give a false sense of security.
- Ignoring runtime controls – thinking input/output guardrails are enough, while tool misuse can still occur.
- Missing fallback paths – when a guardrail blocks, the user gets a generic error with no way to recover.
- Not logging guardrail events – without logs, you can’t know why requests are being blocked.
Best Practices
- Validate all external inputs – even if the input seems safe, run basic sanity checks.
- Enforce structured outputs – combine
output_typewith output guardrails for maximum consistency. - Restrict tool permissions – never expose raw system capabilities; always validate arguments inside the tool.
- Use layered validation – input guardrails for broad safety, tool checks for fine‑grained control, output guardrails for final polish.
- Log all violations – record blocked requests, guardrail name, timestamp, and user context.
- Monitor guardrail effectiveness – track false positive rates and adjust rules accordingly.
- Keep guardrails simple and deterministic – avoid using the LLM inside a guardrail if possible; it adds cost and latency.
- Test guardrails – write unit tests for each guardrail function, injecting both passing and blocking inputs.
Practical Example: Customer Support Agent with Guardrails
We’ll build a support agent that:
- Rejects empty or profane inputs.
- Ensures responses contain a required disclaimer.
- Validates tool arguments during execution (runtime guardrail).
1. Define guardrails
from agents import input_guardrail, output_guardrail, GuardrailResult
@input_guardrail
async def block_empty_and_profanity(context, agent, input):
if not input.strip():
return GuardrailResult(blocked=True, message="Input cannot be empty.")
if "badword" in input.lower():
return GuardrailResult(blocked=True, message="Inappropriate language.")
return GuardrailResult(blocked=False)
@output_guardrail
async def require_disclaimer(context, agent, output):
disclaimer = "Please verify details on our website."
if disclaimer not in output:
new_output = output + f"\n\n{disclaimer}"
return GuardrailResult(blocked=False, output_data=new_output)
return GuardrailResult(blocked=False)
2. Define a tool with runtime checks
@function_tool
def look_up_order(order_id: str) -> str:
# Runtime validation: only allow numeric order IDs
if not order_id.isdigit():
return "Error: Invalid order ID format. Please provide a numeric ID."
# Simulated DB lookup
return f"Order {order_id}: shipped"
3. Create the agent
support_agent = Agent(
name="Support Agent",
instructions="Help with order inquiries. Use the look_up_order tool.",
model="gpt-4o",
tools=[look_up_order],
input_guardrails=[block_empty_and_profanity],
output_guardrails=[require_disclaimer],
)
4. Run the agent
async def main():
result = await Runner.run(support_agent, "Check order 12345")
print(result.final_output)
# Output includes the disclaimer automatically.
Flow:
- The input guardrail passes (non‑empty, no profanity).
- The agent decides to call
look_up_order. The tool validates theorder_id, passes. - The agent generates a response.
- The output guardrail checks for the disclaimer; if missing, it appends it.
- The final output is returned with the disclaimer.
If the user sends an empty input, the input guardrail blocks, and the user sees “Input cannot be empty.”
Guardrails in Production Systems
In production, guardrails are your continuous safety net.
- Reliability improvements – fewer malformed responses reach users, reducing support escalations.
- Compliance requirements – output guardrails enforce legal disclaimers, data masking, and content guidelines, helping meet regulatory standards.
- Cost control – input guardrails can reject overly broad requests that would burn tokens, and runtime checks prevent expensive tool loops.
- Observability integration – all guardrail actions (pass/block) are captured in traces, providing an audit trail.
- Incident reduction – catching prompt injections and harmful outputs before they are sent to users drastically reduces the risk profile of your agent.
Integrate guardrails into your CI/CD: test them with simulated attacks, and monitor their logs for trends.
Guardrails and Other SDK Concepts
Guardrails are a cross‑cutting concern that enhances the entire SDK experience.
- Core Concepts – Agents and Runner are the foundation; guardrails hook into the Runner’s lifecycle.
- Tool Calling – Guardrails can’t directly block tool calls, but input guardrails prevent malicious requests, and tool‑level validation completes the safety picture.
- Handoffs – Each agent can have its own guardrails. Input guardrails on the triage agent stop unsafe requests before any specialist is involved.
- Observability – Guardrail results (block/pass, messages) are recorded in traces, giving you full visibility into why a run was rejected.
- MCP – Tools from MCP servers can be secured with runtime checks; guardrails provide the outer policy layer.
For comparison with other frameworks’ safety features, see the LangGraph Human‑in‑the‑Loop guide and CrewAI Tools & Delegation. The framework comparison highlights how each framework handles validation.
FAQ
1. What are Guardrails in the OpenAI Agents SDK?
Guardrails are async validation functions that run before and after agent execution to enforce safety, policy, and quality rules.
2. How do Guardrails work?
Input guardrails run before the agent processes the user message; output guardrails run after the agent produces a final answer. The SDK invokes them automatically.
3. What is input validation?
It’s the process of checking the user’s input (e.g., for emptiness, profanity, or malicious patterns) and blocking the run if it fails.
4. What is output validation?
It’s the process of verifying the agent’s final response (e.g., for required format, content safety, or completeness) and optionally rewriting it.
5. Can Guardrails stop tool execution?
Not directly. You should put validation logic inside the tool function itself to reject unsafe calls. Input guardrails help prevent requests that would lead to dangerous tool usage.
6. How do Guardrails improve reliability?
By catching malformed inputs and outputs early, they prevent downstream errors and ensure consistent response quality.
7. Are Guardrails production‑ready?
Yes. They are lightweight, run asynchronously, and are designed for high‑volume use. Tracing captures every guardrail action.
8. How many guardrails can an agent have?
You can attach multiple input and output guardrails. The Runner executes them in order; the first input guardrail that blocks stops the run.
9. Can I use guardrails to implement human‑in‑the‑loop?
Yes, the approval pattern uses an output guardrail to pause the flow and require a human decision. However, you’ll need a separate mechanism (like a queue) to manage the review.
10. What happens when an output guardrail rewrites the output?
The rewritten output replaces the original and is returned to the user. The original output is still captured in traces.
11. Can guardrails access the conversation history?
They receive the RunContext, which includes the session state. You can access previous messages or custom metadata.
12. How do I test guardrails?
Write unit tests that call the guardrail function directly with sample inputs and verify the GuardrailResult.
13. Do guardrails add latency?
Minimal overhead for simple checks (a few milliseconds). Avoid heavy I/O inside guardrails; offload to background tasks if needed.
14. Can I use guardrails with MCP tools?
Yes. Guardrails protect the agent’s input/output; runtime checks inside the MCP tool (or its wrapper) provide additional safety.
15. Is there a way to bypass guardrails?
No, if an agent has guardrails configured, the Runner always runs them. This is by design for safety.
Conclusion
Guardrails in the OpenAI Agents SDK provide a clean, declarative way to enforce safety, compliance, and quality in your AI agents. By validating inputs before execution and outputs after, you can build systems that are more reliable, more secure, and easier to maintain. Combined with runtime checks in tools, they form a comprehensive defense‑in‑depth strategy.
Key takeaways:
- Input guardrails block invalid or dangerous requests early.
- Output guardrails ensure responses meet your standards.
- Runtime checks inside tools add a final layer of protection.
- Guardrails are asynchronous, tracable, and production‑ready.
Now, deepen your expertise:
- Tool Calling in the OpenAI Agents SDK – secure and optimize your tool usage.
- Handoffs & Multi‑Agent Patterns – manage agent delegation safely.
- Observability & Tracing – monitor guardrail effectiveness in production.
- OpenAI Agents SDK Core Concepts – revisit the foundational abstractions.
For cross‑framework safety comparisons, see the LangGraph Human‑in‑the‑Loop guide, CrewAI Tools & Delegation, and the full framework comparison. To standardize tool safety, visit the MCP Guide.
Now, build agents that not only think, but think safely.