Implementation:Openai Openai agents python Tool Output Guardrail Decorator
Overview
The tool output guardrail decorator and associated classes provide the API for defining post-execution validation on tool return values. The @tool_output_guardrail decorator transforms a function into a ToolOutputGuardrail instance, while ToolOutputGuardrailData provides access to both the tool's input context and its output value.
Decorator Signature
def tool_output_guardrail(
func: _ToolOutputFuncSync | _ToolOutputFuncAsync | None = None,
*,
name: str | None = None,
) -> ToolOutputGuardrail[Any] | Callable[..., ToolOutputGuardrail[Any]]:
The decorator can be used with or without arguments:
# Without arguments -- uses function name as guardrail name
@tool_output_guardrail
def my_guardrail(data):
...
# With arguments -- custom name
@tool_output_guardrail(name="pii_filter")
def my_guardrail(data):
...
Source: src/agents/tool_guardrails.py lines 264-279
Class: ToolOutputGuardrail
@dataclass
class ToolOutputGuardrail(Generic[TContext_co]):
guardrail_function: Callable[
[ToolOutputGuardrailData],
MaybeAwaitable[ToolGuardrailFunctionOutput],
]
name: str | None = None
The ToolOutputGuardrail dataclass wraps a guardrail function and an optional name. The guardrail_function receives ToolOutputGuardrailData and returns a ToolGuardrailFunctionOutput. The function can be synchronous or asynchronous.
Source: src/agents/tool_guardrails.py lines 181-206
Class: ToolOutputGuardrailData
@dataclass
class ToolOutputGuardrailData(ToolInputGuardrailData):
output: Any # The tool's return value
This dataclass extends ToolInputGuardrailData and provides:
context-- AToolContextinstance containing the tool call arguments and invocation metadata (inherited fromToolInputGuardrailData).agent-- TheAgentinstance that triggered the tool call (inherited fromToolInputGuardrailData).output-- The actual return value produced by the tool function. This is the primary value being validated.
The inheritance from ToolInputGuardrailData means output guardrails have access to both the tool's input arguments and its output, enabling contextual validation that considers the relationship between what was requested and what was returned.
Class: ToolGuardrailFunctionOutput
The ToolGuardrailFunctionOutput class provides three class methods for signaling the guardrail's decision (shared with tool input guardrails):
.allow(output_info=None)-- The tool output is safe and should be sent to the LLM as-is..reject_content(message, output_info=None)-- The tool output is problematic. Themessagestring replaces the actual tool output in what the LLM receives. The original output is never seen by the model..raise_exception(output_info=None)-- The tool output is dangerous enough to halt the run. AToolOutputGuardrailTripwireTriggeredexception is raised.
Import
from agents import tool_output_guardrail, ToolGuardrailFunctionOutput
Example: PII Detection
from agents import tool_output_guardrail, ToolGuardrailFunctionOutput
@tool_output_guardrail
def no_pii_in_output(data):
"""Reject tool outputs containing PII patterns."""
import re
output_str = str(data.output)
if re.search(r'\b\d{3}-\d{2}-\d{4}\b', output_str): # SSN pattern
return ToolGuardrailFunctionOutput.reject_content("Output contained PII")
return ToolGuardrailFunctionOutput.allow()
This guardrail scans the tool's output for Social Security Number patterns. If a match is found, the actual output is replaced with an error message so the LLM never receives the sensitive data.
Example: Output Size Validation
from agents import tool_output_guardrail, ToolGuardrailFunctionOutput
@tool_output_guardrail
def limit_output_size(data):
"""Reject tool outputs that exceed a maximum size."""
output_str = str(data.output)
max_chars = 50000
if len(output_str) > max_chars:
return ToolGuardrailFunctionOutput.reject_content(
f"Tool output exceeded {max_chars} characters. Please refine your query."
)
return ToolGuardrailFunctionOutput.allow()
Example: Contextual Validation
from agents import tool_output_guardrail, ToolGuardrailFunctionOutput
@tool_output_guardrail
def verify_output_matches_request(data):
"""Ensure tool output is consistent with the requested scope."""
requested_user = data.context.tool_input.get("user_id", "")
output_str = str(data.output)
# Check that the output only contains data for the requested user
if "all_users" in output_str and requested_user:
return ToolGuardrailFunctionOutput.reject_content(
"Tool returned data beyond the requested user scope"
)
return ToolGuardrailFunctionOutput.allow()
This example demonstrates using both the input context and the output to validate that the tool did not return more data than was requested.
Example: Attaching to a Tool
from agents import function_tool, tool_output_guardrail, ToolGuardrailFunctionOutput
@tool_output_guardrail
def no_pii_in_output(data):
import re
output_str = str(data.output)
if re.search(r'\b\d{3}-\d{2}-\d{4}\b', output_str):
return ToolGuardrailFunctionOutput.reject_content("Output contained PII")
return ToolGuardrailFunctionOutput.allow()
@function_tool(tool_output_guardrails=[no_pii_in_output])
def lookup_customer(customer_id: str) -> str:
"""Look up customer information."""
return get_customer_record(customer_id)
See Also
- Tool Output Guardrail Definition -- The principle behind tool output guardrails
- Tool Input Guardrail Decorator -- The corresponding input guardrail implementation
- Guardrail Attachment Pattern -- How to wire guardrails to tools and agents