Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Openai Openai agents python Guardrail Attachment Pattern

From Leeroopedia

Overview

The guardrail attachment pattern describes how to wire guardrail instances to the tools and agents they protect. This is a configuration pattern -- guardrails are specified as list fields on FunctionTool and Agent at construction time.

Tool-Level Attachment

Via the @function_tool Decorator

The most concise way to attach guardrails to a tool is through the @function_tool decorator:

from agents import (
    function_tool,
    tool_input_guardrail,
    tool_output_guardrail,
    ToolGuardrailFunctionOutput,
)

@tool_input_guardrail
def input_guard(data):
    """Validate tool input."""
    if "dangerous" in str(data.context.tool_input):
        return ToolGuardrailFunctionOutput.reject_content("Dangerous input rejected")
    return ToolGuardrailFunctionOutput.allow()

@tool_output_guardrail
def output_guard(data):
    """Validate tool output."""
    if "secret" in str(data.output):
        return ToolGuardrailFunctionOutput.reject_content("Secret data filtered")
    return ToolGuardrailFunctionOutput.allow()

@function_tool(
    tool_input_guardrails=[input_guard],
    tool_output_guardrails=[output_guard],
)
def my_func(x: str) -> str:
    """A guarded tool function."""
    return process(x)

Via the function_tool Function

When creating tools programmatically rather than with decorators, use the function_tool function:

from agents import function_tool

def my_func(x: str) -> str:
    return process(x)

my_tool = function_tool(
    my_func,
    tool_input_guardrails=[input_guard],
    tool_output_guardrails=[output_guard],
)

FunctionTool Fields

The underlying FunctionTool dataclass defines two guardrail list fields:

# From src/agents/tool.py lines 247-251
@dataclass
class FunctionTool:
    # ... other fields ...
    tool_input_guardrails: list[ToolInputGuardrail[Any]]
    tool_output_guardrails: list[ToolOutputGuardrail[Any]]

Source: src/agents/tool.py lines 247-251

Agent-Level Attachment

Direct Construction

Agent-level guardrails are attached via the input_guardrails and output_guardrails fields on the Agent class:

from agents import (
    Agent,
    InputGuardrail,
    OutputGuardrail,
    GuardrailFunctionOutput,
)

def check_input(ctx, agent, input):
    if "blocked" in str(input).lower():
        return GuardrailFunctionOutput(
            output_info="Blocked content",
            tripwire_triggered=True,
        )
    return GuardrailFunctionOutput(output_info="OK")

def check_output(ctx, agent, output):
    if len(str(output)) > 10000:
        return GuardrailFunctionOutput(
            output_info="Too long",
            tripwire_triggered=True,
        )
    return GuardrailFunctionOutput(output_info="OK")

agent = Agent(
    name="safe_agent",
    instructions="Be helpful and safe.",
    input_guardrails=[
        InputGuardrail(guardrail_function=check_input),
    ],
    output_guardrails=[
        OutputGuardrail(guardrail_function=check_output),
    ],
)

Using Decorator-Created Guardrails

Guardrails created with the @input_guardrail and @output_guardrail decorators can be passed directly into the agent's lists:

from agents import Agent, input_guardrail, output_guardrail, GuardrailFunctionOutput

@input_guardrail
def topic_filter(ctx, agent, input):
    if "off_topic" in str(input).lower():
        return GuardrailFunctionOutput(
            output_info="Off topic",
            tripwire_triggered=True,
        )
    return GuardrailFunctionOutput(output_info="OK")

@output_guardrail
def quality_check(ctx, agent, output):
    if len(str(output)) < 10:
        return GuardrailFunctionOutput(
            output_info="Response too short",
            tripwire_triggered=True,
        )
    return GuardrailFunctionOutput(output_info="OK")

agent = Agent(
    name="quality_agent",
    instructions="Provide thorough responses.",
    input_guardrails=[topic_filter],
    output_guardrails=[quality_check],
)

Agent Guardrail Fields

The underlying Agent dataclass defines two guardrail list fields:

# From src/agents/agent.py lines 269-277
@dataclass
class Agent:
    # ... other fields ...
    input_guardrails: list[InputGuardrail[TContext]]
    output_guardrails: list[OutputGuardrail[TContext]]

Source: src/agents/agent.py lines 269-277

Stacking Multiple Guardrails

Both tool-level and agent-level guardrail fields accept lists, enabling multiple guardrails to be stacked:

from agents import (
    function_tool,
    tool_input_guardrail,
    tool_output_guardrail,
    ToolGuardrailFunctionOutput,
)

@tool_input_guardrail
def no_sql_injection(data):
    input_str = str(data.context.tool_input)
    if "DROP TABLE" in input_str.upper():
        return ToolGuardrailFunctionOutput.reject_content("SQL injection detected")
    return ToolGuardrailFunctionOutput.allow()

@tool_input_guardrail
def validate_length(data):
    input_str = str(data.context.tool_input)
    if len(input_str) > 10000:
        return ToolGuardrailFunctionOutput.reject_content("Input too long")
    return ToolGuardrailFunctionOutput.allow()

@tool_output_guardrail
def no_pii(data):
    import re
    if re.search(r'\b\d{3}-\d{2}-\d{4}\b', str(data.output)):
        return ToolGuardrailFunctionOutput.reject_content("PII detected")
    return ToolGuardrailFunctionOutput.allow()

@function_tool(
    tool_input_guardrails=[no_sql_injection, validate_length],
    tool_output_guardrails=[no_pii],
)
def query_database(sql: str) -> str:
    """Execute a database query with multiple guardrails."""
    return execute_query(sql)

All guardrails in the list are evaluated. If any one rejects or triggers a tripwire, the operation is blocked.

See Also

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment