Implementation:Openai Openai agents python Tool Input Guardrail Decorator
Overview
The tool input guardrail decorator and associated classes provide the API for defining pre-execution validation on tool call inputs. The @tool_input_guardrail decorator transforms a function into a ToolInputGuardrail instance, while ToolInputGuardrailData provides the data context and ToolGuardrailFunctionOutput provides the result signaling mechanism.
Decorator Signature
def tool_input_guardrail(
func: _ToolInputFuncSync | _ToolInputFuncAsync | None = None,
*,
name: str | None = None,
) -> ToolInputGuardrail[Any] | Callable[..., ToolInputGuardrail[Any]]:
The decorator can be used with or without arguments:
# Without arguments -- uses function name as guardrail name
@tool_input_guardrail
def my_guardrail(data):
...
# With arguments -- custom name
@tool_input_guardrail(name="custom_name")
def my_guardrail(data):
...
Source: src/agents/tool_guardrails.py lines 228-243
Class: ToolInputGuardrail
@dataclass
class ToolInputGuardrail(Generic[TContext_co]):
guardrail_function: Callable[
[ToolInputGuardrailData],
MaybeAwaitable[ToolGuardrailFunctionOutput],
]
name: str | None = None
The ToolInputGuardrail dataclass wraps a guardrail function and an optional name. The guardrail_function is a callable that receives ToolInputGuardrailData and returns a ToolGuardrailFunctionOutput. The function can be either synchronous or asynchronous (indicated by MaybeAwaitable).
Source: src/agents/tool_guardrails.py lines 152-177
Class: ToolInputGuardrailData
@dataclass
class ToolInputGuardrailData:
context: ToolContext[Any]
agent: Agent[Any]
This dataclass is passed to the guardrail function and provides:
context-- AToolContextinstance containing the tool call arguments viacontext.tool_input, the tool name, and other invocation metadata.agent-- TheAgentinstance that triggered the tool call.
Class: ToolGuardrailFunctionOutput
The ToolGuardrailFunctionOutput class provides three class methods for signaling the guardrail's decision:
.allow(output_info=None)-- Indicates the tool call is safe. Execution proceeds to the tool function..reject_content(message, output_info=None)-- Indicates the tool call is unsafe. The tool function is not executed, and themessagestring is sent to the LLM as the tool result instead..raise_exception(output_info=None)-- Indicates the tool call is dangerous enough to halt the run. AToolInputGuardrailTripwireTriggeredexception is raised.
The optional output_info parameter on all three methods allows attaching arbitrary metadata to the guardrail result for logging or debugging purposes.
Import
from agents import tool_input_guardrail, ToolGuardrailFunctionOutput
Example: SQL Injection Detection
from agents import tool_input_guardrail, ToolGuardrailFunctionOutput
@tool_input_guardrail
def no_sql_injection(data):
"""Reject tool inputs containing SQL injection patterns."""
input_str = str(data.context.tool_input)
if "DROP TABLE" in input_str.upper() or ";" in input_str:
return ToolGuardrailFunctionOutput.reject_content("SQL injection detected")
return ToolGuardrailFunctionOutput.allow()
This guardrail inspects the stringified tool input for common SQL injection patterns. If a dangerous pattern is found, the tool call is rejected with an error message that the LLM receives instead of a tool result. The LLM can then decide to reformulate its approach.
Example: Async Guardrail
from agents import tool_input_guardrail, ToolGuardrailFunctionOutput
@tool_input_guardrail
async def validate_url(data):
"""Check that URL inputs point to allowed domains."""
import urllib.parse
input_str = str(data.context.tool_input)
parsed = urllib.parse.urlparse(input_str)
allowed_domains = ["example.com", "api.example.com"]
if parsed.hostname and parsed.hostname not in allowed_domains:
return ToolGuardrailFunctionOutput.reject_content(
f"Domain {parsed.hostname} is not in the allowed list"
)
return ToolGuardrailFunctionOutput.allow()
Example: Attaching to a Tool
from agents import function_tool, tool_input_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()
@function_tool(tool_input_guardrails=[no_sql_injection])
def query_database(sql: str) -> str:
"""Execute a database query."""
# The guardrail ensures this only runs with safe input
return execute_query(sql)
See Also
- Tool Input Guardrail Definition -- The principle behind tool input guardrails
- Tool Output Guardrail Decorator -- The corresponding output guardrail implementation
- Guardrail Attachment Pattern -- How to wire guardrails to tools and agents