Skip to content

Commit f355af6

Browse files
authored
docs: document v0.22.1 behavior updates (#4577)
1 parent f0b884a commit f355af6

16 files changed

Lines changed: 217 additions & 18 deletions

File tree

docs/config.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ set_default_openai_client(custom_client)
5353

5454
When you pass an explicit client to [`OpenAIProvider`][agents.models.openai_provider.OpenAIProvider], that client owns its connection and account settings. Do not also pass `api_key`, `base_url`, `websocket_base_url`, `organization`, or `project` to `OpenAIProvider`; combining `openai_client` with any of those arguments raises [`UserError`][agents.exceptions.UserError] instead of silently ignoring the duplicate value. Set the intended values when constructing `AsyncOpenAI`.
5555

56+
When `openai_client` is omitted, `OpenAIProvider` reuses the SDK-wide default client only if `api_key`, `base_url`, `websocket_base_url`, `organization`, and `project` are all `None`. Passing any of those options, including an empty string, makes the provider create its own client and gives the provider option precedence over the SDK-wide default client. Leave every provider option as `None` when the provider should inherit the client installed by `set_default_openai_client()`.
57+
58+
[`OpenAIVoiceModelProvider`][agents.voice.models.openai_model_provider.OpenAIVoiceModelProvider] uses the same ownership and precedence rules for `api_key`, `base_url`, `organization`, and `project`. Its explicit `openai_client` cannot be combined with any of those four options.
59+
5660
### Custom HTTP clients with `openai` v3
5761

5862
Version 0.21.0 requires `openai>=3.0.0,<4`. The default OpenAI provider uses HTTPX2, so most applications do not need to configure an HTTP client directly. If your application passes `http_client=` to `AsyncOpenAI`, use HTTPX2 types for the custom client and its transport-facing options:

docs/guardrails.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Guardrails are attached to agents and tools, but they do not all run at the same
1313

1414
- **Input guardrails** run only for the first agent in the chain.
1515
- **Output guardrails** run only for the agent that produces the final output.
16-
- **Tool guardrails** run on every custom function-tool invocation, with input guardrails before execution and output guardrails after execution.
16+
- **Tool guardrails** run on every guarded function-tool invocation, including local MCP tools when their server configures guardrails, with input guardrails before execution and output guardrails after execution.
1717

1818
If you need checks before and/or after each custom function-tool call in a workflow that includes managers, handoffs, or delegated specialists, use tool guardrails instead of relying only on agent-level input/output guardrails.
1919

@@ -53,7 +53,20 @@ Output guardrails run in 3 steps:
5353

5454
An output tripwire and an exception raised by the guardrail function have different session behavior. A tripwire rejects the candidate final output. When a tripwire fires, the runner asks the configured session to persist already-completed tool call and tool output items, together with any reasoning context required to replay those calls, while excluding the rejected candidate final output. The runner applies this tripwire rule to both streaming and non-streaming runs. When the guardrail function raises an exception instead of returning a tripwire result, the runner treats the verdict as unknown and asks the configured session to persist the completed final-turn items before surfacing the guardrail exception. If that session write also fails, the session write error takes precedence. Streaming runs use the same persistence ordering as non-streaming runs and raise the terminal exception from `stream_events()`. An immediate [`RunResultStreaming.cancel()`][agents.result.RunResultStreaming.cancel] call while the output guardrail is running cancels the in-flight guardrail and does not start a final-turn session write.
5555

56-
Terminal function-tool output needs additional handling because the tool has already run before the agent-level output guardrail checks the value. When [`Agent.tool_use_behavior`][agents.agent.Agent.tool_use_behavior] makes that tool result the final output and an output tripwire rejects it, the SDK retains a replay-valid function call/output pair only when it can rebuild the pair from validated fields. The retained `function_call_output` payload is replaced with the fixed text `"Output withheld by an output guardrail."`; the original tool-output payload is not retained in the session, `RunState`, streamed result state, or sandbox memory input. The SDK does retain validated function-call metadata required for replay, including the function arguments, so that metadata can contain data that also appeared in the rejected output. Current-response [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] objects also replace `agent_output` with the fixed text and clear `output_info`. Current-response [`ToolOutputGuardrailResult`][agents.tool_guardrails.ToolOutputGuardrailResult] objects preserve the allow/reject behavior type but replace payload-bearing `output_info` and rejection messages with the same text. Earlier accepted turns and guardrail results remain unchanged. If the response contains reasoning or another shape that the SDK cannot sanitize safely, the SDK discards the complete current-response suffix instead of retaining the rejected output payload. A guardrail function that raises an exception has not returned a rejection verdict, so the completed terminal-tool turn follows the exception persistence behavior described above.
56+
Terminal function-tool output needs additional handling because the tool has already run before the agent-level output guardrail checks the value. When [`Agent.tool_use_behavior`][agents.agent.Agent.tool_use_behavior] makes that tool result the final output and an output tripwire rejects it, the SDK retains a replay-valid function call/output pair only when it can rebuild the pair from validated fields. The retained `function_call_output` payload is replaced with the default text `"Output withheld by an output guardrail."`; the original tool-output payload is not retained in the session, `RunState`, streamed result state, or sandbox memory input. The SDK does retain validated function-call metadata required for replay, including the function arguments, so that metadata can contain data that also appeared in the rejected output. Current-response [`OutputGuardrailResult`][agents.guardrail.OutputGuardrailResult] objects also replace `agent_output` with the resolved placeholder and clear `output_info`. Current-response [`ToolOutputGuardrailResult`][agents.tool_guardrails.ToolOutputGuardrailResult] objects preserve the allow/reject behavior type but replace payload-bearing `output_info` and rejection messages with the same placeholder. Earlier accepted turns and guardrail results remain unchanged. If the response contains reasoning or another shape that the SDK cannot sanitize safely, the SDK discards the complete current-response suffix instead of retaining the rejected output payload. A guardrail function that raises an exception has not returned a rejection verdict, so the completed terminal-tool turn follows the exception persistence behavior described above.
57+
58+
Set [`RunConfig.output_guardrail_blocked_message`][agents.run.RunConfig.output_guardrail_blocked_message] to a non-empty string or a synchronous formatter when your application needs a different data-free placeholder. The formatter receives [`OutputGuardrailBlockedMessageArgs`][agents.run.OutputGuardrailBlockedMessageArgs] with the SDK default, the guardrail name, the agent, and the active run context. It never receives the rejected tool output or guardrail `output_info`. The returned text is persisted and replayed wherever the SDK retains the sanitized terminal-tool turn, so keep it free of sensitive data and do not copy secrets from the run context. If the formatter raises, returns `None`, returns an empty or non-string value, or produces an awaitable, the SDK uses the default placeholder. Async formatter functions are rejected when `RunConfig` is constructed.
59+
60+
```python
61+
from agents import OutputGuardrailBlockedMessageArgs, RunConfig
62+
63+
64+
def blocked_message(args: OutputGuardrailBlockedMessageArgs[dict[str, str]]) -> str:
65+
return f"Output blocked by policy: {args.guardrail_name}."
66+
67+
68+
run_config = RunConfig(output_guardrail_blocked_message=blocked_message)
69+
```
5770

5871
## Tool guardrails
5972

@@ -62,7 +75,7 @@ Tool guardrails wrap **`FunctionTool` instances** and let you validate or block
6275
- Input tool guardrails run before the tool executes and can skip the call, replace the output with a message, or raise a tripwire.
6376
- Output tool guardrails run after the tool executes and can replace the output or raise a tripwire.
6477
- 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.
65-
- 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.
78+
- Tool guardrails use the `FunctionTool` execution pipeline. You can attach them directly to a custom tool created with `tool` or [`function_tool`][agents.tool.function_tool]. You can also set `tool_input_guardrails` and `tool_output_guardrails` on a local MCP server; the SDK attaches those lists to every tool exposed by that server. Handoffs run through the SDK's handoff pipeline rather than the 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`) do not use this guardrail pipeline, and [`Agent.as_tool()`][agents.agent.Agent.as_tool] does not currently expose tool-guardrail options directly. See [MCP server tool guardrails](mcp.md#tool-guardrails) for the local MCP configuration.
6679

6780
See the code snippet below for details.
6881

docs/human_in_the_loop.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This page focuses on the manual approval flow via `interruptions`. If your app c
1212

1313
Set `needs_approval` to `True` to always require approval or provide an async function that decides per call. The callable receives the run context, parsed tool parameters, and the tool call ID.
1414

15-
Callable approval rules fail closed when the SDK cannot safely inspect the arguments. If the arguments are malformed JSON, are valid JSON but not an object (for example, `null` or a list), or contain non-standard constants such as `NaN`, `Infinity`, or `-Infinity`, the callable is not invoked and the call requires manual approval. This behavior is the same for Runner and Realtime tool calls.
15+
Callable approval rules fail closed when the SDK cannot safely inspect the arguments. If the arguments are missing, empty, contain only whitespace, are malformed JSON, are valid JSON but not an object (for example, `null` or a list), or contain non-standard constants such as `NaN`, `Infinity`, or `-Infinity`, the callable is not invoked and the call requires manual approval. This behavior is the same for Runner and Realtime tool calls.
1616

1717
```python
1818
from agents import Agent

docs/mcp.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ async with MCPServerManager(servers) as manager:
388388
Key behaviors:
389389

390390
- `active_servers` includes only successfully connected servers when `drop_failed_servers=True` (the default).
391+
- If the input iterable repeats the same server object, the manager owns that server once: `all_servers` and `active_servers` contain one entry, and connection and cleanup run once for that server.
391392
- Failures are tracked in `failed_servers` and `errors`.
392393
- Set `strict=True` to raise on the first connection failure.
393394
- Call `reconnect(failed_only=True)` to retry failed servers, or `reconnect(failed_only=False)` to restart all servers.
@@ -452,6 +453,39 @@ async with MCPServerStdio(
452453

453454
The filter context exposes the active `run_context`, the `agent` requesting the tools, and the `server_name`.
454455

456+
## Tool guardrails
457+
458+
Local MCP server classes accept `tool_input_guardrails` and `tool_output_guardrails`. The SDK attaches these server-wide guardrails to every MCP tool that remains after filtering. Input guardrails can prevent the MCP server call and supply replacement content, while output guardrails inspect the converted MCP result before the SDK sends that result back to the model. These guardrails use the same function-tool execution pipeline, approval ordering, result tracking, and tripwire exceptions described in [Tool guardrails](guardrails.md#tool-guardrails).
459+
460+
```python
461+
import json
462+
463+
from agents import ToolGuardrailFunctionOutput
464+
from agents.decorators import tool_input_guardrail
465+
from agents.mcp import MCPServerStdio
466+
467+
468+
@tool_input_guardrail
469+
def block_secret_arguments(data):
470+
arguments = json.loads(data.context.tool_arguments or "{}")
471+
if "secret" in arguments:
472+
return ToolGuardrailFunctionOutput.reject_content(
473+
"Remove secrets before calling this MCP tool."
474+
)
475+
return ToolGuardrailFunctionOutput.allow()
476+
477+
478+
filesystem_server = MCPServerStdio(
479+
params={
480+
"command": "npx",
481+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
482+
},
483+
tool_input_guardrails=[block_secret_arguments],
484+
)
485+
```
486+
487+
This configuration applies only to tools exposed by local MCP server objects such as `MCPServerStdio`, `MCPServerSse`, and `MCPServerStreamableHttp`. It does not add client-side tool guardrails to [`HostedMCPTool`][agents.tool.HostedMCPTool], which the Responses API executes as a hosted tool.
488+
455489
## Prompts
456490

457491
MCP servers can also provide prompts that dynamically generate agent instructions. Servers that support prompts expose two
@@ -486,6 +520,8 @@ Resources remain explicitly paginated. Pass the `nextCursor` from `list_resource
486520

487521
Every agent run calls `list_tools()` on each MCP server. Remote servers can introduce noticeable latency, so all of the MCP server classes expose a `cache_tools_list` option. Set it to `True` only if you are confident that the tool definitions do not change frequently. To force a fresh list later, call `invalidate_tools_cache()` on the server instance.
488522

523+
When caching is enabled, each `list_tools()` result contains detached copies of the cached tool definitions, including nested input schemas. Dynamic tool-filter callbacks also inspect detached copies. Mutating a returned tool or a tool received by a filter therefore does not change the server's cached schema or later `list_tools()` results.
524+
489525
## Tracing
490526

491527
[Tracing](./tracing.md) automatically captures MCP activity, including:

0 commit comments

Comments
 (0)