You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guardrails.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -51,6 +51,8 @@ Output guardrails run in 3 steps:
51
51
52
52
Output guardrails always run after the agent completes, so they don't support the `run_in_parallel` parameter.
53
53
54
+
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.
55
+
54
56
## Tool guardrails
55
57
56
58
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.
Copy file name to clipboardExpand all lines: docs/human_in_the_loop.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,13 +45,15 @@ agent = Agent(
45
45
## How the approval flow works
46
46
47
47
1. When the model emits a tool call, the runner evaluates its approval rule (`needs_approval`, `require_approval`, or the hosted MCP equivalent).
48
-
2. If an approval decision for that tool call is already stored in the [`RunContextWrapper`][agents.run_context.RunContextWrapper], the runner proceeds without prompting. Per-call approvals are scoped to the specific call ID; pass `always_approve=True` or `always_reject=True` to persist the same decision for future calls to that tool during the rest of the run.
48
+
2. If an approval decision for that tool call is already stored in the [`RunContextWrapper`][agents.run_context.RunContextWrapper], the runner proceeds without prompting. Per-call approvals are scoped to the specific call ID; pass `always_approve=True` or `always_reject=True` to persist the same decision for future calls to the same tool identity during the rest of the run.
49
49
3. If the approval rule requires approval and no decision for that tool call is stored, execution pauses, and `RunResult.interruptions` (or `RunResultStreaming.interruptions`) contains [`ToolApprovalItem`][agents.items.ToolApprovalItem] entries with details such as `agent.name`, `tool_name`, and `arguments`. This includes approvals raised after a handoff or inside nested `Agent.as_tool()` executions.
50
50
4. Convert the result to a `RunState` with `result.to_state()`, call `state.approve(...)` or `state.reject(...)`, and then resume with `Runner.run(agent, state)` or `Runner.run_streamed(agent, state)`, where `agent` is the original top-level agent for the run.
51
51
5. The resumed run continues where it left off and will re-enter this flow if new approvals are needed.
52
52
53
53
Sticky decisions created with `always_approve=True` or `always_reject=True` are stored in the run state, so they survive `state.to_string()` / `RunState.from_string(...)` and `state.to_json()` / `RunState.from_json(...)` when you resume the same paused run later.
54
54
55
+
For approval requests from [`HostedMCPTool`][agents.tool.HostedMCPTool], the Agents SDK identifies a sticky tool decision by the combination of `server_label` and tool name. An always-approve decision for `lookup_account` on one hosted MCP server does not approve a tool with the same name on another server. The Agents SDK persists an always-approve or always-reject decision only when the hosted MCP approval request includes both non-empty identity fields.
56
+
55
57
You do not need to resolve every pending approval in the same pass. `interruptions` can contain a mix of regular function tools, hosted MCP approvals, and nested `Agent.as_tool()` approvals. If you rerun after approving or rejecting only some items, those resolved calls can continue while unresolved ones remain in `interruptions` and pause the run again.
Copy file name to clipboardExpand all lines: docs/mcp.md
+32-3Lines changed: 32 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -26,6 +26,34 @@ Before wiring an MCP server into an agent decide where the tool calls should exe
26
26
27
27
The sections below walk through each option, how to configure it, and when to prefer one transport over another.
28
28
29
+
## MCP Python SDK v1 and v2
30
+
31
+
The Agents SDK supports both major versions of the `mcp` Python package through the dependency range `mcp>=1.19.0,<3`. The installed `mcp` package version is separate from the MCP protocol version negotiated with a server. The Agents SDK detects the installed package major version and adapts stdio, SSE, and Streamable HTTP connections automatically, so ordinary server configuration does not need a version switch.
32
+
33
+
When MCP Python SDK v2 is installed, the Agents SDK creates the v2 `mcp.Client` with `mode="auto"` around the configured local transport. The client first sends a `server/discover` probe at the newest protocol version supported by the installed MCP SDK. A modern server answers the probe, and the client adopts the result. If an older server does not support `server/discover`, the client falls back to the legacy `initialize` handshake and uses the protocol version negotiated there. Installing MCP Python SDK v2 therefore does not force every connection to use the newest MCP protocol version. See the MCP Python SDK's [protocol version negotiation guide](https://py.sdk.modelcontextprotocol.io/protocol-versions/).
34
+
35
+
Most applications should let their dependency resolver select a compatible version. If your application must stay on one major version, add an explicit constraint alongside `openai-agents`:
36
+
37
+
```bash
38
+
# MCP Python SDK v1
39
+
pip install "mcp>=1.19.0,<2"
40
+
41
+
# MCP Python SDK v2
42
+
pip install "mcp>=2,<3"
43
+
```
44
+
45
+
HTTP transport customization must use the HTTP stack owned by the installed MCP package:
|`params["httpx_client_factory"]` return value |`httpx.AsyncClient`|`httpx2.AsyncClient`|
51
+
|`MCPServerStreamableHttp``params["ignore_initialized_notification_failure"] = True`| Supported | Not supported; rejected before connecting |
52
+
53
+
Use an `Authorization` header when possible, as shown in the Streamable HTTP example below; an `Authorization` header works unchanged with both package versions. When an application supplies `params["auth"]` or `params["httpx_client_factory"]`, those values must use the HTTP types for the installed `mcp` package major version. When an application sets `MCPServerStreamableHttp`'s `params["ignore_initialized_notification_failure"] = True`, the application must keep `mcp<2` or disable the option before upgrading.
54
+
55
+
These local `mcp` dependency requirements do not apply to [`HostedMCPTool`][agents.tool.HostedMCPTool] because the OpenAI Responses API owns the remote MCP connection.
56
+
29
57
## Agent-level MCP configuration
30
58
31
59
In addition to choosing a transport, you can tune how MCP tools are prepared by setting `Agent.mcp_config`.
@@ -269,9 +297,9 @@ server = MCPServerStreamableHttp(
269
297
270
298
If your run context is a Pydantic model, dataclass, or custom class, read the tenant ID with attribute access instead.
271
299
272
-
### MCP tool outputs: textand images
300
+
### MCP tool outputs: text, images, and other content
273
301
274
-
When an MCP tool returns image content, the SDK automatically maps it to image-type entries in the tool output. Mixed text/image responses are forwarded as a list of output items, so agents can consume MCP image results the same way they consume image output from regular function tools.
302
+
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.
275
303
276
304
## 3. HTTP with SSE MCP servers
277
305
@@ -363,7 +391,8 @@ Key behaviors:
363
391
- Failures are tracked in `failed_servers` and `errors`.
364
392
- Set `strict=True` to raise on the first connection failure.
365
393
- Call `reconnect(failed_only=True)` to retry failed servers, or `reconnect(failed_only=False)` to restart all servers.
366
-
- Set `connect_timeout_seconds`, `cleanup_timeout_seconds`, and `connect_in_parallel` to tune lifecycle behavior. Lifecycle timeouts accept positive finite seconds, or `None` to disable them, and are validated both during construction and assignment; zero is rejected because it would create an immediate deadline.
394
+
- Calls to `connect_all()`, `reconnect()`, and `cleanup_all()` are serialized. If one lifecycle operation is already running, another lifecycle operation waits for it to finish instead of connecting or cleaning up the same servers concurrently.
395
+
- Set `connect_timeout_seconds`, `cleanup_timeout_seconds`, and `connect_in_parallel` to tune lifecycle behavior. Both lifecycle timeouts default to 10 seconds. They accept positive finite seconds, or `None` to disable them, and are validated both during construction and assignment; zero is rejected because it would create an immediate deadline.
Copy file name to clipboardExpand all lines: docs/models/index.md
+10-5Lines changed: 10 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ Start with the simplest path that fits your setup:
23
23
24
24
For most OpenAI-only apps, the recommended path is to use string model names with the default OpenAI provider and stay on the Responses model path.
25
25
26
-
When you don't specify a model when initializing an `Agent`, the default model will be used. The default is currently [`gpt-5.4-mini`](https://developers.openai.com/api/docs/models/gpt-5.4-mini) with `reasoning.effort="none"` and `verbosity="low"` for low-latency agent workflows. If you have access, we recommend setting your agents to `gpt-5.6-sol` for higher quality while keeping explicit `model_settings`.
26
+
When an [`Agent`][agents.agent.Agent] does not specify a model, the Agents SDK uses [`gpt-5.6-luna`](https://developers.openai.com/api/docs/models/gpt-5.6-luna) with `reasoning.effort="none"` and `verbosity="low"`by default for cost-sensitive, high-volume agent workflows. Applications that need frontier capability can explicitly set `model="gpt-5.6-sol"` and choose `model_settings` that are appropriate for the workload.
27
27
28
28
If you want to switch to other models like `gpt-5.6-sol`, there are two ways to configure your agents.
29
29
@@ -545,11 +545,12 @@ A retry policy receives a [`RetryPolicyContext`][agents.retry.RetryPolicyContext
545
545
-`error` for raw inspection.
546
546
-`normalized` facts such as `status_code`, `retry_after`, `error_code`, `is_network_error`, `is_timeout`, and `is_abort`.
547
547
-`provider_advice` when the underlying model adapter can supply retry guidance.
548
+
-`response_started`, `replay_safety`, and `stateful_request` as stable replay-safety facts captured before the policy runs. `replay_safety` is `"safe"`, `"unsafe"`, or `"unknown"`; `stateful_request` is true when the request uses `previous_response_id` or `conversation_id`.
548
549
549
550
The policy can return either:
550
551
551
552
-`True` / `False` for a simple retry decision.
552
-
- A [`RetryDecision`][agents.retry.RetryDecision] when you want to override the delay or attach a diagnostic reason.
553
+
- A [`RetryDecision`][agents.retry.RetryDecision] when you want to override the delay, attach a diagnostic reason, or explicitly approve a narrowly scoped unsafe replay.
553
554
554
555
The SDK exports ready-made helpers on `retry_policies`:
555
556
@@ -567,13 +568,15 @@ When you compose policies, `provider_suggested()` is the safest first building b
567
568
568
569
##### Safety boundaries
569
570
570
-
Some failures are never retried automatically:
571
+
Some failures are never retried:
571
572
572
573
- Abort errors.
573
-
- Requests where provider advice marks replay as unsafe.
574
574
- Streamed runs after output has already started in a way that would make replay unsafe.
575
+
- Requests with a separate local-side-effect replay veto, including Programmatic Tool Calling requests, unless the provider has independently marked the replay safe.
575
576
576
-
Stateful follow-up requests using `previous_response_id` or `conversation_id` are also treated more conservatively. For those requests, non-provider predicates such as `network_error()` or `http_status([500])` are not enough by themselves. The retry policy should include a replay-safe approval from the provider, typically via `retry_policies.provider_suggested()`.
577
+
Provider-marked unsafe failures are also blocked by default. For a non-streaming request without a separate local-side-effect veto, an application can accept the provider-side replay risk by returning `RetryDecision(retry=True, approve_unsafe_replay=True)`. Check `context.response_started`, `context.replay_safety`, and `context.stateful_request` before granting this approval, and grant it only when repeating provider-side work is acceptable. An ordinary `RetryDecision(retry=True)` never bypasses replay protection, and `approve_unsafe_replay=True` cannot authorize streamed retries or local side effects.
578
+
579
+
Stateful follow-up requests using `previous_response_id` or `conversation_id` fail closed when replay safety is unknown. For those requests, non-provider predicates such as `network_error()` or `http_status([500])` are not enough by themselves. Include a replay-safe approval from the provider, typically via `retry_policies.provider_suggested()`, or explicitly approve a non-streaming failure that the provider marked unsafe as described above.
577
580
578
581
##### Runner and agent merge behavior
579
582
@@ -624,6 +627,8 @@ result = await Runner.run(
624
627
625
628
If you use [`MultiProvider`][agents.MultiProvider], pass `openai_strict_feature_validation=True` instead.
626
629
630
+
The OpenAI Chat Completions API can return audio output, but [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel] does not currently convert audio output into Agents SDK run items. If a non-streaming message or streaming delta contains audio output, the adapter raises `AgentsException("Audio is not currently supported")` instead of returning a partial or empty result. Use [Realtime agents](../realtime/guide.md) or [Voice agents](../voice/quickstart.md) for SDK-managed audio workflows.
631
+
627
632
Some OpenAI-compatible Chat Completions providers stream tool-call deltas in chunks that are not reliable enough for incremental SDK processing. In that case, enable streamed tool-call buffering so the SDK emits tool calls only after the provider stream finishes:
Copy file name to clipboardExpand all lines: docs/realtime/guide.md
+54Lines changed: 54 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -85,6 +85,60 @@ Useful run-level settings on `RealtimeRunner(config=...)` include:
85
85
86
86
See [`RealtimeRunConfig`][agents.realtime.config.RealtimeRunConfig] and [`RealtimeSessionModelSettings`][agents.realtime.config.RealtimeSessionModelSettings] for the full typed surface.
87
87
88
+
### Input transcription settings
89
+
90
+
Configure input transcription under `audio.input.transcription`. Use `gpt-live-transcribe` for low-latency incremental transcripts, or use `gpt-transcribe` over WebSocket when transcription should begin after an audio turn is committed or when your application needs detected-language output. The Agents SDK forwards the model-specific GA transcription settings in the nested session configuration:
91
+
92
+
```python
93
+
runner = RealtimeRunner(
94
+
starting_agent=agent,
95
+
config={
96
+
"model_settings": {
97
+
"audio": {
98
+
"input": {
99
+
"transcription": {
100
+
"model": "gpt-live-transcribe",
101
+
"prompt": "A support call about the OpenAI Agents SDK.",
102
+
"keywords": ["RunState", "MCPServerManager"],
103
+
"languages": ["en", "ja"],
104
+
},
105
+
"turn_detection": None,
106
+
}
107
+
}
108
+
}
109
+
},
110
+
)
111
+
```
112
+
113
+
For `gpt-live-transcribe`, `prompt` provides free-form recording context, `keywords` lists literal terms that may occur in the audio, and `languages` lists expected input languages. This model uses plural `languages` instead of singular `language`; do not send both fields.
114
+
115
+
The OpenAI client version pinned by this SDK supports `delay` only with `gpt-realtime-whisper`. Configure that model's latency and accuracy tradeoff as follows:
116
+
117
+
```python
118
+
runner = RealtimeRunner(
119
+
starting_agent=agent,
120
+
config={
121
+
"model_settings": {
122
+
"audio": {
123
+
"input": {
124
+
"transcription": {
125
+
"model": "gpt-realtime-whisper",
126
+
"delay": "low",
127
+
},
128
+
"turn_detection": None,
129
+
}
130
+
}
131
+
}
132
+
},
133
+
)
134
+
```
135
+
136
+
The `delay` setting accepts `minimal`, `low`, `medium`, `high`, or `xhigh`. Lower values can produce earlier partial text, while higher values give the transcription model more audio context and can improve recognition accuracy. Benchmark representative audio instead of assuming fixed timing for any level.
137
+
138
+
Use `gpt-transcribe` in a Realtime session over WebSocket only when transcription should begin after a committed audio turn or the application needs detected-language output. The model automatically uses earlier transcribed turns as context. The `gpt-transcribe` completion event reports detected languages in its `languages` output field. This output field is different from the `gpt-live-transcribe` expected-language input shown above.
139
+
140
+
Setting `audio.input.turn_detection` to `None` disables automatic turn detection. The application must then commit audio turns and control response creation as described in [Manual response control](#manual-response-control). See the OpenAI API [Realtime transcription guide](https://developers.openai.com/api/docs/guides/realtime-transcription) for model behavior, validation rules, and latency guidance.
0 commit comments