Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/guardrails.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ Terminal function-tool output needs additional handling because the tool has alr

## Tool guardrails

Tool guardrails wrap **`FunctionTool` instances** and let you validate or block calls to those tools before and after execution. They are configured on the tool itself and run every time that tool is invoked.
Tool guardrails wrap **`FunctionTool` instances** and let you validate or block calls to those tools before and after execution. They are configured on the tool itself — or, for locally executed MCP tools, on the MCP server — and run every time that tool is invoked.

- Input tool guardrails run before the tool executes and can skip the call, replace the output with a message, or raise a tripwire.
- Output tool guardrails run after the tool executes and can replace the output or raise a tripwire.
- If a function tool requires approval, input tool guardrails normally run after approval and immediately before execution. Set [`RunConfig.tool_execution`][agents.run.RunConfig.tool_execution] to [`ToolExecutionConfig(pre_approval_tool_input_guardrails=True)`][agents.run.ToolExecutionConfig] when you want those input checks to run before the pending approval interruption is emitted. Calls that pass this pre-approval check are still checked again after approval before the tool executes.
- Tool guardrails apply only to function tools created with [`function_tool`][agents.tool.function_tool]. Handoffs run through the SDK's handoff pipeline rather than the normal function-tool pipeline, so tool guardrails do not apply to the handoff call itself. Hosted tools (`WebSearchTool`, `FileSearchTool`, `HostedMCPTool`, `CodeInterpreterTool`, `ImageGenerationTool`) and built-in execution tools (`ComputerTool`, `ShellTool`, `ApplyPatchTool`, `LocalShellTool`) also do not use this guardrail pipeline, and [`Agent.as_tool()`][agents.agent.Agent.as_tool] does not currently expose tool-guardrail options directly.
- Locally executed MCP server tools can opt in by passing `tool_input_guardrails` / `tool_output_guardrails` to the MCP server (for example [`MCPServerStdio`][agents.mcp.server.MCPServerStdio] or [`MCPServerStreamableHttp`][agents.mcp.server.MCPServerStreamableHttp]). Those guardrails are attached to every tool the server exposes when the SDK converts MCP tools into `FunctionTool`s, so they run on the same pipeline and with the same approval ordering, tripwire behavior, and `tool_input_guardrail_results` / `tool_output_guardrail_results` reporting described here. Guardrails receive the normal [`ToolContext`][agents.tool_context.ToolContext], so branch on `context.tool_name` when a policy should apply to only some of a server's tools. `HostedMCPTool` is not covered, because the Python process does not own that round trip.
- Otherwise, tool guardrails apply only to function tools created with [`function_tool`][agents.tool.function_tool]. Handoffs run through the SDK's handoff pipeline rather than the normal function-tool pipeline, so tool guardrails do not apply to the handoff call itself. Hosted tools (`WebSearchTool`, `FileSearchTool`, `HostedMCPTool`, `CodeInterpreterTool`, `ImageGenerationTool`) and built-in execution tools (`ComputerTool`, `ShellTool`, `ApplyPatchTool`, `LocalShellTool`) also do not use this guardrail pipeline, and [`Agent.as_tool()`][agents.agent.Agent.as_tool] does not currently expose tool-guardrail options directly.

See the code snippet below for details.

Expand Down
29 changes: 29 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,35 @@ server = MCPServerStreamableHttp(

If your run context is a Pydantic model, dataclass, or custom class, read the tenant ID with attribute access instead.

### Tool guardrails for local MCP servers

Locally executed MCP tools are converted into `FunctionTool`s by the SDK, so they can opt into the same [tool guardrails](guardrails.md#tool-guardrails) used by function tools. Guardrails passed to the server apply to every tool it exposes: input guardrails run immediately before `call_tool()`, and output guardrails run on the result before it becomes model-visible.

```python
from agents.mcp import MCPServerStreamableHttp
from agents.tool_guardrails import (
ToolGuardrailFunctionOutput,
ToolInputGuardrailData,
tool_input_guardrail,
Comment on lines +306 to +309

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import the decorator from the canonical module

This runnable snippet imports tool_input_guardrail from agents.tool_guardrails, teaching readers a noncanonical decorator import path. Import the decorator from agents.decorators while keeping ToolGuardrailFunctionOutput and ToolInputGuardrailData on their existing public path.

AGENTS.md reference: AGENTS.md:L126-L126

Useful? React with 👍 / 👎.

)


@tool_input_guardrail
def block_pii(data: ToolInputGuardrailData) -> ToolGuardrailFunctionOutput:
if "ssn" in data.context.tool_arguments.lower():
return ToolGuardrailFunctionOutput.reject_content(message="Blocked: argument contains PII")
return ToolGuardrailFunctionOutput.allow()


server = MCPServerStreamableHttp(
name="Billing",
params={"url": "http://localhost:8000/mcp"},
tool_input_guardrails=[block_pii],
)
```

Guardrails receive the normal `ToolContext`, so branch on `data.context.tool_name` to apply a policy to only some of the server's tools. These checks are client-side and complement, rather than replace, authorization in the MCP server itself. `HostedMCPTool` is not covered, since the Python process does not own that round trip.

### MCP tool outputs: text, images, and other content

When an MCP result uses its content blocks, the SDK forwards text content as text output and maps image content to image-type entries in the tool output. For other MCP content block types, including audio and resource blocks, the SDK forwards a text output whose value is the block's valid JSON serialization. Responses that contain multiple content blocks are forwarded as a list of output items. If `use_structured_content=True` selects a non-empty, non-error `structuredContent` payload, that structured payload takes precedence over these content blocks. Missing or empty structured content falls back to the content blocks.
Expand Down