Add untrusted external messages to the Python SDK (#44086)

## Why

Applications need to deliver content from other agents, tools, or services with tool-level authority, without treating it as user input or granting authorization.

## What changed

- Export `ExternalMessage` for sync and async `run(...)` and `turn(...)`, accepting text or structured content with a tool name and optional namespace. Send it through `toolOutput` and require CLI 0.151.0 or newer.
- Support starting a turn or joining an active regular turn while preserving external content as function output in history. Keep external messages separate from user-input lists and `steer(...)`.
- Give turn handles independent subscriptions, replaying completed items and latest usage to joining handles. Release consumed transient events and clean up subscriptions on closure, failure, or cancellation.
- Document the authority boundary and add sync and async examples.

## Testing

Add coverage for wire representations, input validation, runtime compatibility, tool authority across resume, active-turn joins, and tool-output truncation. Add subscription tests for replay, concurrent consumers, early completion, cancellation, and cleanup.

GitOrigin-RevId: 6106327085fd9c4bd11b71e20b3d8e74738b8bb5
This commit is contained in:
Ahmed Ibrahim
2026-09-09 06:46:01 +00:00
committed by copyberry
parent 8afccec87a
commit 1a4096e273
19 changed files with 1031 additions and 87 deletions

View File

@@ -70,6 +70,11 @@ with Codex() as codex:
Use `Thread.turn(...)` when you need a `TurnHandle` for streaming, steering,
or interrupting an active turn.
For **untrusted content** from another agent, tool, or application, pass an
[`ExternalMessage`](api-reference.md#externalmessage). It retains tool-level
authority and does not establish user authorization or approval. Plain strings
and `TextInput` represent user input.
## 4. Choose Sandbox Access
Use one enum for the initial thread and later turn overrides: