One read of Claude Developer Platformapi-20261014T120710Z
59 pages moved out of 763 read.
Pages moved
59
significant first
Pages read
763
in this capture
Captured
12:07 UTC
Corpus hash
0e0ee442771d
corpus-hash
What this read moved
26-50 of 59, page 2 of 3This capture is too large to show at once. Changes 26-50 of 59 are below, significant first; the rest are on the following screens.
managed-agents/self-hosted-sandboxes-operations Changed · +16 / -16 lines
from line 18
1818
1919## Read queue depth
2020
21`GET /v1/environments/{environment_id}/work/stats` (curl; python, typescript, ruby: `client.beta.environments.work.stats()`; go, csharp: `client.Beta.Environments.Work.Stats()`; java: `client.beta().environments().work().stats()`; php: `$client->beta->environments->work->stats()`; cli: `ant beta:environments:work stats`) returns the queue state for an environment:
21`GET /v1/environments/{environment_id}/work/stats` (python, typescript, ruby: `client.beta.environments.work.stats()`; go, csharp: `client.Beta.Environments.Work.Stats()`; java: `client.beta().environments().work().stats()`; php: `$client->beta->environments->work->stats()`; cli: `ant beta:environments:work stats`) returns the queue state for an environment:
2222
23| Field | Meaning | Use it to |
24| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
25| `depth` (java, php; csharp, go: `Depth`) | Items waiting to be claimed. | Scale your worker fleet or alert on backlog. |
26| `pending` (java, php; csharp, go: `Pending`) | Items claimed by a worker but not yet acknowledged. The worker helpers acknowledge each item before processing it, so this stays near zero in normal operation. | Detect a worker that stalled between claiming and acknowledging: alert on a sustained non-zero value. |
27| `oldest_queued_at` (java, php: `oldestQueuedAt`; csharp, go: `OldestQueuedAt`) | Timestamp of the oldest item still in the queue, either waiting to be claimed or claimed but not yet acknowledged. `null` when there is none. | See how long the oldest item has waited. |
28| `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`) | Workers that have polled in the last 30 seconds. | Alert on liveness. |
23| Field | Meaning | Use it to |
24| ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
25| `depth` (csharp, go: `Depth`) | Items waiting to be claimed. | Scale your worker fleet or alert on backlog. |
26| `pending` (csharp, go: `Pending`) | Items claimed by a worker but not yet acknowledged. The worker helpers acknowledge each item before processing it, so this stays near zero in normal operation. | Detect a worker that stalled between claiming and acknowledging: alert on a sustained non-zero value. |
27| `oldest_queued_at` (java, php: `oldestQueuedAt`; csharp, go: `OldestQueuedAt`) | Timestamp of the oldest item still in the queue, either waiting to be claimed or claimed but not yet acknowledged. `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) when there is no such item. | See how long the oldest item has waited. |
28| `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`) | Workers that have polled in the last 30 seconds. | Alert on liveness. |
2929
3030<CodeGroup>
3131 ```bash cURL
from line 152
152152
153153## Stop a session gracefully
154154
155Use `POST /v1/environments/{environment_id}/work/{work_id}/stop` (curl; python, typescript, ruby: `client.beta.environments.work.stop()`; go, csharp: `client.Beta.Environments.Work.Stop()`; java: `client.beta().environments().work().stop()`; php: `$client->beta->environments->work->stop()`; cli: `ant beta:environments:work stop`) to ask the worker handling a specific session to shut it down.
155Use `POST /v1/environments/{environment_id}/work/{work_id}/stop` (python, typescript, ruby: `client.beta.environments.work.stop()`; go, csharp: `client.Beta.Environments.Work.Stop()`; java: `client.beta().environments().work().stop()`; php: `$client->beta->environments->work->stop()`; cli: `ant beta:environments:work stop`) to ask the worker handling a specific session to shut it down.
156156
157157By default the work item moves to `stopping`. The worker notices on its next lease heartbeat, cancels the session's in-flight tool call, and confirms the shutdown. The work item then becomes `stopped`.
158158
from line 323
323323
324324### A session stays queued
325325
326No worker is claiming work. A queued session waits rather than failing. Check `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`) and `depth` (java, php; csharp, go: `Depth`) in [Read queue depth](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#read-queue-depth).
326No worker is claiming work. A queued session waits rather than failing. Check `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`) and `depth` (csharp, go: `Depth`) in [Read queue depth](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#read-queue-depth).
327327
328328### Memory stores fail to mount
329329
from line 331
331331
332332If the worker cannot mount a memory store when it claims a session, it fails the work item. The session emits no error event and stays idle.
333333
334| Symptom | Cause | Fix |
335| --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
336| The worker log contains `the work item carried no sessions token` (in Go, the `ErrSessionMemoryNoToken` error) and the work item fails. | The work item's per-session `secret` (java, php; csharp, go: `Secret`) did not reach the worker. Either your code did not forward it, or memory stores on self-hosted sandboxes are not enabled for your organization. | [Forward the work item's secret](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret). If the worker polls and runs sessions in one process and still logs this, contact support. |
337| The worker log contains `something already exists at the memory store's path`. | A directory left over from a previous session, usually one whose worker was killed before its teardown ran. | Remove the leftover directory that the log line names. Edits in it that had not synced are lost. |
338| The worker log contains `cannot create the memory store's folder` and `the worker host must make this mount path writable`. | The user the worker runs as cannot create directories under `/mnt/memory`. | Create `/mnt/memory` and `chown` it to that user. See [Prepare the host](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#prepare-the-host). |
339| The session sits `idle` with a `requires_action` stop reason and no error event shortly after a worker claimed it. | The worker failed the work item because it could not mount a memory store, for one of the preceding reasons. | Fix the cause on the host, then send a [`user.interrupt`](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) event. The session's work is queued again, and the next worker that claims it retries the mount. |
334| Symptom | Cause | Fix |
335| --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
336| The worker log contains `the work item carried no sessions token` (in Go, the `ErrSessionMemoryNoToken` error) and the work item fails. | The work item's per-session `secret` (csharp, go: `Secret`) did not reach the worker. Either your code did not forward it, or memory stores on self-hosted sandboxes are not enabled for your organization. | [Forward the work item's secret](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret). If the worker polls and runs sessions in one process and still logs this, contact support. |
337| The worker log contains `something already exists at the memory store's path`. | A directory left over from a previous session, usually one whose worker was killed before its teardown ran. | Remove the leftover directory that the log line names. Edits in it that had not synced are lost. |
338| The worker log contains `cannot create the memory store's folder` and `the worker host must make this mount path writable`. | The user the worker runs as cannot create directories under `/mnt/memory`. | Create `/mnt/memory` and `chown` it to that user. See [Prepare the host](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#prepare-the-host). |
339| The session sits `idle` with a `requires_action` stop reason and no error event shortly after a worker claimed it. | The worker failed the work item because it could not mount a memory store, for one of the preceding reasons. | Fix the cause on the host, then send a [`user.interrupt`](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) event. The session's work is queued again, and the next worker that claims it retries the mount. |
340340
341341### A custom tool call never returns
342342
managed-agents/session-operations Changed · +6 / -6 lines
from line 25
2525
2626## Updating the agent configuration
2727
28You can update a session's `agent.tools` (java, php; csharp, go: `Agent.Tools`) and `agent.mcp_servers` (java, php: `agent.mcpServers`; csharp: `Agent.McpServers`; go: `Agent.MCPServers`), including permission policies and per-tool web settings such as [domain filters](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#change-the-lists-mid-session), mid-session without creating a new agent version. Updates are session-local and do not propagate back to the underlying agent. Updated `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) apply to the rest of the session.
28You can update a session's `agent.tools` (csharp, go: `Agent.Tools`) and `agent.mcp_servers` (java, php: `agent.mcpServers`; csharp: `Agent.McpServers`; go: `Agent.MCPServers`), including permission policies and per-tool web settings such as [domain filters](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#change-the-lists-mid-session), mid-session without creating a new agent version. Updates are session-local and do not propagate back to the underlying agent. Updated `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) apply to the rest of the session.
2929
30Only the agent's `tools` (java, php; csharp, go: `Tools`) and `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) can change after a session is created. To run a session with `model` (java, php; csharp, go: `Model`), `system` (java, php; csharp, go: `System`; ruby: `system_`), or `skills` (java, php; csharp, go: `Skills`) values other than the agent's, use [agent configuration overrides](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session) when you create the session. The agent's model configuration, including its [`inference_geo`](https://platform.claude.com/docs/en/manage-claude/data-residency) pin, also can't change mid-session: set the pin when you save the agent, or set or clear it for a single session with a `model` (java, php; csharp, go: `Model`) override when you create it. The agent's configured `system` (java, php; csharp, go: `System`; ruby: `system_`) field is fixed for the session's lifetime. On models that support it, you can still append system-level guidance mid-session by sending a [`system.message` event](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#send-system-messages).
30Only the agent's `tools` (csharp, go: `Tools`) and `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) can change after a session is created. To run a session with `model` (csharp, go: `Model`), `system` (csharp, go: `System`; ruby: `system_`), or `skills` (csharp, go: `Skills`) values other than the agent's, use [agent configuration overrides](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session) when you create the session. The agent's model configuration, including its [`inference_geo`](https://platform.claude.com/docs/en/manage-claude/data-residency) pin, also can't change mid-session: set the pin when you save the agent, or set or clear it for a single session with a `model` (csharp, go: `Model`) override when you create it. The agent's configured `system` (csharp, go: `System`; ruby: `system_`) field is fixed for the session's lifetime. On models that support it, you can still append system-level guidance mid-session by sending a [`system.message` event](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#send-system-messages).
3131
32The semantics of a `tools` (java, php; csharp, go: `Tools`) or `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) update are full replacement: the provided array is the new value. To preserve existing entries, `GET` the session, modify the array, and `POST` it back.
32The semantics of a `tools` (csharp, go: `Tools`) or `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) update are full replacement: the provided array is the new value. To preserve existing entries, `GET` the session, modify the array, and `POST` it back.
3333
3434The session must be `idle` to update the agent. To update the agent while the session is running, send a [`user.interrupt` event](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) by itself and wait for the session to become `idle`. If a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#while-a-run-is-open) is open, whether it's running or paused, the update returns a 400 error, even when the session is `idle`. An interrupt doesn't end a run, so the update still fails after you interrupt the session. Send a `user.message` that [asks the agent to stop its runs](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open), or wait until every run has ended.
3535
from line 215
215215
216216## Updating the session budget
217217
218A session [created with a budget](https://platform.claude.com/docs/en/managed-agents/sessions#set-a-session-budget) accepts two kinds of budget update: replacing the cap with a new `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`), and removing it by passing `"budget": null` (python: `budget=None`; typescript: `budget: null`; ruby: `budget: nil`; go: `Budget: param.NullStruct[anthropic.BetaManagedAgentsBudgetLimitParam]()`; java: `.budget(Optional.empty())`; csharp: `Budget = null`; php: `requestOptions: ['extraBodyParams' => ['budget' => null]]`; cli: `--budget null`). Both automatically resume work that paused when the session reached its cap. A replacement cap can be higher or lower than the current one, but it must be strictly greater than the session's consumed list cost, and removal is one-way: a non-null `budget` (java, php; csharp, go: `Budget`) is accepted only on a session that currently has one, so you can't re-add a removed budget or add one to a session created without it. See [Session budgets](https://platform.claude.com/docs/en/managed-agents/budgets#resume-a-session-at-its-budget) for request examples, the error behaviors, and what counts toward list cost.
218A session [created with a budget](https://platform.claude.com/docs/en/managed-agents/sessions#set-a-session-budget) accepts two kinds of budget update: replacing the cap with a new `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`), and removing it by passing `"budget": null` (python: `budget=None`; typescript: `budget: null`; ruby: `budget: nil`; go: `Budget: param.NullStruct[anthropic.BetaManagedAgentsBudgetLimitParam]()`; java: `.budget(Optional.empty())`; csharp: `Budget = null`; php: `requestOptions: ['extraBodyParams' => ['budget' => null]]`; cli: `--budget null`). Both automatically resume work that paused when the session reached its cap. A replacement cap can be higher or lower than the current one, but it must be strictly greater than the session's consumed list cost, and removal is one-way: a non-null `budget` (csharp, go: `Budget`) is accepted only on a session that currently has one, so you can't re-add a removed budget or add one to a session created without it. See [Session budgets](https://platform.claude.com/docs/en/managed-agents/budgets#resume-a-session-at-its-budget) for request examples, the error behaviors, and what counts toward list cost.
219219
220220## Retrieving a session
221221
managed-agents/session-threads Changed · +16 / -15 lines
from line 18
1818
1919**Session threads** are where you drill into a specific agent's activity.
2020
21The session `status` (java, php; csharp, go: `Status`) is an aggregation of all agent activity; if at least one thread is `running`, then the overall session status is `running` as well. A [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs) that's running can keep the session `running` too, even while none of its threads is working. When no thread is working and a thread waits on your client, the session is `idle`; see [Know when the work is done](https://platform.claude.com/docs/en/managed-agents/workflow-runs#know-when-the-work-is-done).
21The session `status` (csharp, go: `Status`) is an aggregation of all agent activity; if at least one thread is `running`, then the overall session status is `running` as well. A [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs) that's running can keep the session `running` too, even while none of its threads is working. When no thread is working and a thread waits on your client, the session is `idle`; see [Know when the work is done](https://platform.claude.com/docs/en/managed-agents/workflow-runs#know-when-the-work-is-done).
2222
2323A [session budget](https://platform.claude.com/docs/en/managed-agents/budgets) is a single shared cap across all of a session's threads. As the cap is reached, threads pause independently, and each thread's cost is priced at the thread's own served model.
2424
from line 102
102102 ```
103103</CodeGroup>
104104
105The full list includes the primary thread. `parent_thread_id` (java: `parentThreadId`; php: `parentThreadID`; csharp, go: `ParentThreadID`) is `null` for the primary thread. Every other thread is a child thread. `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null` except on [a run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads).
105The full list includes the primary thread. `parent_thread_id` (java: `parentThreadId`; php: `parentThreadID`; csharp, go: `ParentThreadID`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) for the primary thread. Every other thread is a child thread. `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) except on [a run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads).
106106
107107To list only threads that have certain statuses, add `statuses[]` to the request, and repeat it to give more than one status, as in `?statuses[]=running&statuses[]=idle`. Leave it out to return threads of every status.
108108
from line 386
386386
387387These events surface multiagent activity on the primary thread at `/v1/sessions/{session_id}/events/stream`. Message-direction events are named relative to the thread whose stream they appear on: `agent.thread_message_received` means a message arrived on this thread from another thread, and `agent.thread_message_sent` means this thread sent one. The task that the primary thread's agent delegates, for example, arrives on the child's own stream as an `agent.thread_message_received` event.
388388
389| Type | Description |
390| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
391| `session.thread_created` | A thread was created. Includes `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) and `agent_name` (java, php: `agentName`; csharp, go: `AgentName`). |
392| `session.thread_status_running` | A thread started activity. |
393| `session.thread_status_idle` | The agent associated with the thread is awaiting input. Includes a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) indicating why the agent stopped. |
394| `session.thread_status_terminated` | A thread terminated and accepts no further input, for example because it was archived or encountered an unrecoverable error. An advisor thread also terminates when its consultation ends. |
395| `agent.thread_message_received` | On the primary thread, a subagent sent the primary thread's agent a report or question. Includes `from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`), `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`), and `content` (java, php; csharp, go: `Content`). |
396| `agent.thread_message_sent` | On the primary thread, the primary thread's agent sent a subagent a task or follow-up message. Includes `to_session_thread_id` (java: `toSessionThreadId`; php: `toSessionThreadID`; csharp, go: `ToSessionThreadID`), `to_agent_name` (java, php: `toAgentName`; csharp, go: `ToAgentName`), and `content` (java, php; csharp, go: `Content`). |
389| Type | Description |
390| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
391| `session.thread_created` | A thread was created. Includes `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) and `agent_name` (java, php: `agentName`; csharp, go: `AgentName`). |
392| `session.thread_status_running` | A thread started activity. |
393| `session.thread_status_idle` | The agent associated with the thread is awaiting input. Includes a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) indicating why the agent stopped. |
394| `session.thread_status_terminated` | A thread terminated and accepts no further input, for example because it was archived or encountered an unrecoverable error. An advisor thread also terminates when its consultation ends. |
395| `agent.thread_message_received` | On the primary thread, a subagent sent the primary thread's agent a report or question. Includes `from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`), `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`), and `content` (csharp, go: `Content`). |
396| `agent.thread_message_sent` | On the primary thread, the primary thread's agent sent a subagent a task or follow-up message. Includes `to_session_thread_id` (java: `toSessionThreadId`; php: `toSessionThreadID`; csharp, go: `ToSessionThreadID`), `to_agent_name` (java, php: `toAgentName`; csharp, go: `ToAgentName`), and `content` (csharp, go: `Content`). |
397397
398398Advisor consultations emit these same thread events under the reserved name `anthropic.advisor` (as `agent_name` (java, php: `agentName`; csharp, go: `AgentName`) on the thread lifecycle events and `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`) on the advice delivery); see [Give the session an advisor](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#give-the-session-an-advisor) for the sequence.
399399
from line 410
410410
411411Each session thread has its own event stream at `/v1/sessions/{session_id}/threads/{thread_id}/stream`, and it accepts the same `event_deltas[]` parameter as the session-level stream, so you can preview a subagent's text as the model generates it. A connection previews only the thread it's reading: a child thread's previews never appear on the session-level stream, so to watch a subagent live, open its own thread stream. See [Preview session thread events](https://platform.claude.com/docs/en/managed-agents/event-deltas#preview-session-thread-events) for opting in, accumulating, and reconciling previews.
412412
413In a workflow run, the server runs a workflow: a program that the primary thread's agent writes. On each of the run's threads, the first `agent.thread_message_received` is the prompt that the workflow wrote. Its `from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`) is the primary thread's ID, and it has no `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`). The API doesn't guarantee the prompt's text, so don't parse it. The thread's `session.thread_status_terminated` event, on the primary thread's stream, tells you the thread is done. No event records the result it returned to the workflow.
413In a workflow run, the server runs a workflow: a program that the primary thread's agent writes. On each of the run's threads, the first `agent.thread_message_received` is the prompt that the workflow wrote. Its `from_session_thread_id` (java: `fromSessionThreadId`; php: `fromSessionThreadID`; csharp, go: `FromSessionThreadID`) is the primary thread's ID, and the API doesn't set its `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`). The API doesn't guarantee the prompt's text, so don't parse it. The thread's `session.thread_status_terminated` event, on the primary thread's stream, tells you the thread is done. No event records the result it returned to the workflow.
414414
415A thread's stream doesn't replay earlier events. Right after `session.thread_created`, the event list of a run's thread can be empty, because the server writes the thread's first event after it. So open the thread's stream first, then list the thread's events, and skip each streamed event whose `id` (java, php; csharp, go: `ID`) the list returned.
415A thread's stream doesn't replay earlier events. Right after `session.thread_created`, the event list of a run's thread can be empty, because the server writes the thread's first event after it. So open the thread's stream first, then list the thread's events, and skip each streamed event whose `id` (csharp, go: `ID`) the list returned.
416416
417417<Tabs>
418418 <Tab title="Stream session thread events">
from line 687
687687}
688688```
689689
690Post `user.tool_confirmation` (with `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`)) or `user.custom_tool_result` (with `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`)); the server routes the response to the correct thread automatically. The response can appear on the primary thread and on the subagent's thread with different `id` (java, php; csharp, go: `ID`) values. To match the two copies, compare `type` (java, php; csharp, go: `Type`) and `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) (or `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`)), not `id` (java, php; csharp, go: `ID`).
690Post `user.tool_confirmation` (with `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`)) or `user.custom_tool_result` (with `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`)); the server routes the response to the correct thread automatically. The response can appear on the primary thread and on the subagent's thread with different `id` (csharp, go: `ID`) values. To match the two copies, compare `type` (csharp, go: `Type`) and `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) (or `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`)), not `id` (csharp, go: `ID`).
691691
692692The session goes `idle` only when no thread is `running`, so `session.status_idle` can arrive long after a subagent's call. You don't have to wait for it: send the `user.custom_tool_result` as soon as the cross-posted `agent.custom_tool_use` event arrives.
693693
694694Under `auto`, your `user.message` events can lead the server to allow a call it would otherwise deny. Nothing in a subagent's thread counts as your intent. Your client posts no messages there, and the messages that the primary thread's agent sends the subagent don't count. When the server denies a call under `auto`, nothing is cross-posted: the event and the error tool result appear only on the subagent's own [thread stream](https://platform.claude.com/docs/en/managed-agents/session-threads#session-thread-events), and the subagent keeps running.
695695
696The following example goes inside the event loop of the [tool confirmation handler](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#tool-confirmation). For each ID in `stop_reason.event_ids`, it sends a `user.tool_confirmation` that allows the call. The same pattern applies to `user.custom_tool_result`.
696The following example goes inside the event loop of the [tool confirmation handler](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#tool-confirmation). For each ID in `stop_reason.event_ids`, it sends a `user.tool_confirmation` that allows the call. The same pattern applies to `user.custom_tool_result`, which you can also send as soon as its `agent.custom_tool_use` event arrives.
697697
698698<CodeGroup>
699699 ```bash cURL
from line 781
781781 session.id(),
782782 EventSendParams.builder()
783783 .addEvent(BetaManagedAgentsUserToolConfirmationEventParams.builder()
784 .type(BetaManagedAgentsUserToolConfirmationEventParams.Type.USER_TOOL_CONFIRMATION)
784785 .toolUseId(eventId)
785786 .result(BetaManagedAgentsUserToolConfirmationEventParams.Result.ALLOW)
786787 .build())
managed-agents/sessions Changed · +12 / -12 lines
from line 14
1414
1515## Creating a session
1616
17A session requires an `agent` ID and an `environment` ID. Agents are versioned resources; passing in the `agent` (java, php; csharp, go: `Agent`) ID as a string creates the session with the latest agent version.
17A session requires an `agent` ID and an `environment` ID. Agents are versioned resources; passing in the `agent` (csharp, go: `Agent`) ID as a string creates the session with the latest agent version.
1818
1919<CodeGroup>
2020 ```bash cURL
from line 458
458458
459459### Override agent configuration for a session
460460
461You can pass `agent` (java, php; csharp, go: `Agent`) in three forms: an agent ID string, a pinned-version object (`type: "agent"`), or an overrides object. The overrides form changes parts of the agent's configuration for a single session. Use it to try a different model or grant an extra tool in one session without versioning the agent. For the overrides form, set `type` to `agent_with_overrides` and pass the agent's `id` (java, php; csharp, go: `ID`) and optionally a `version` (java, php; csharp, go: `Version`) (omit `version` (java, php; csharp, go: `Version`) to use the agent's latest version). Then include any of `model` (java, php; csharp, go: `Model`), `system` (java, php; csharp, go: `System`; ruby: `system_`), `tools` (java, php; csharp, go: `Tools`), `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`), or `skills` (java, php; csharp, go: `Skills`) with the values the session should use.
461You can pass `agent` (csharp, go: `Agent`) in three forms: an agent ID string, a pinned-version object (`type: "agent"`), or an overrides object. The overrides form changes parts of the agent's configuration for a single session. Use it to try a different model or grant an extra tool in one session without versioning the agent. For the overrides form, set `type` to `agent_with_overrides` and pass the agent's `id` (csharp, go: `ID`) and optionally a `version` (csharp, go: `Version`) (omit `version` (csharp, go: `Version`) to use the agent's latest version). Then include any of `model` (csharp, go: `Model`), `system` (csharp, go: `System`; ruby: `system_`), `tools` (csharp, go: `Tools`), `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`), or `skills` (csharp, go: `Skills`) with the values the session should use.
462462
463463Each overridable field follows the same three rules:
464464
465465* **Omit the field:** The session inherits the value from the agent version it references.
466466
467* **Set the field to `null`, or to an empty array for list fields:** The session runs with that field cleared. This rule applies in full to `system` (java, php; csharp, go: `System`; ruby: `system_`) and `skills` (java, php; csharp, go: `Skills`). There are three exceptions:
467* **Set the field to `null`, or to an empty array for list fields:** The session runs with that field cleared. This rule applies in full to `system` (csharp, go: `System`; ruby: `system_`) and `skills` (csharp, go: `Skills`). There are three exceptions:
468468
469469 * `model` is never clearable. A session always needs a model, so `model: null` returns a 400 `agent_model_required` error.
470 * Clearing `tools` returns a 400 error when the session's effective `skills` (java, php; csharp, go: `Skills`) is non-empty, because skills require the `read` tool. Otherwise, `tools: null` and `tools: []` clear the field.
471 * Clearing `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) returns a 400 error when the session's effective `tools` (java, php; csharp, go: `Tools`) still contains an `mcp_toolset` that references one of the agent's servers. Override `tools` (java, php; csharp, go: `Tools`) in the same request to remove those `mcp_toolset` entries, then clear `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`).
470 * Clearing `tools` returns a 400 error when the session's effective `skills` (csharp, go: `Skills`) is non-empty, because skills require the `read` tool. Otherwise, `tools: null` and `tools: []` clear the field.
471 * Clearing `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) returns a 400 error when the session's effective `tools` (csharp, go: `Tools`) still contains an `mcp_toolset` that references one of the agent's servers. Override `tools` (csharp, go: `Tools`) in the same request to remove those `mcp_toolset` entries, then clear `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`).
472472
473* **Set the field to a value:** The value replaces the agent's value in full. Overrides never merge with the agent's configuration, so a `tools` (java, php; csharp, go: `Tools`) override must list every tool the session should have. Likewise, a `model` (java, php; csharp, go: `Model`) override replaces the agent's `model` (java, php; csharp, go: `Model`) object in full, so the agent's own `effort` (java, php; csharp, go: `Effort`) isn't carried over. To run the session at a specific effort level, set `effort` (java, php; csharp, go: `Effort`) inside the override's `model` (java, php; csharp, go: `Model`) object. A level the model doesn't support returns a 400 error, and a `model` (java, php; csharp, go: `Model`) override without `effort` (java, php; csharp, go: `Effort`) runs at that model's default effort level.
473* **Set the field to a value:** The value replaces the agent's value in full. Overrides never merge with the agent's configuration, so a `tools` (csharp, go: `Tools`) override must list every tool the session should have. Likewise, a `model` (csharp, go: `Model`) override replaces the agent's `model` (csharp, go: `Model`) object in full, so the agent's own `effort` (csharp, go: `Effort`) isn't carried over. To run the session at a specific effort level, set `effort` (csharp, go: `Effort`) inside the override's `model` (csharp, go: `Model`) object. A level the model doesn't support returns a 400 error, and a `model` (csharp, go: `Model`) override without `effort` (csharp, go: `Effort`) runs at that model's default effort level.
474474
475475Overrides apply only to the session you create. They do not modify the agent resource or create a new agent version, so other sessions that reference the same agent are unaffected.
476476
477In the response, the `agent` (java, php; csharp, go: `Agent`) object reflects the configuration the session runs with after the overrides are applied. Its `id` (java, php; csharp, go: `ID`) and `version` (java, php; csharp, go: `Version`) still identify the agent and version the overrides are applied to. This lets you trace a session back to its base agent.
477In the response, the `agent` (csharp, go: `Agent`) object reflects the configuration the session runs with after the overrides are applied. Its `id` (csharp, go: `ID`) and `version` (csharp, go: `Version`) still identify the agent and version the overrides are applied to. This lets you trace a session back to its base agent.
478478
479479The following example starts a session that overrides the model and clears the system prompt:
480480
from line 641
641641
642642#### Pin the inference geo for a session
643643
644Because a `model` (java, php; csharp, go: `Model`) override replaces the agent's `model` (java, php; csharp, go: `Model`) object in full, it also sets or clears the model's [inference geo](https://platform.claude.com/docs/en/manage-claude/data-residency) pin for the session: an override that includes `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) pins the geography that serves the session's model requests, and one that omits it clears the agent's pin so the session follows the workspace's `default_inference_geo`. The overridden value is validated against the workspace's `allowed_inference_geos` when the session is created.
644Because a `model` (csharp, go: `Model`) override replaces the agent's `model` (csharp, go: `Model`) object in full, it also sets or clears the model's [inference geo](https://platform.claude.com/docs/en/manage-claude/data-residency) pin for the session: an override that includes `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) pins the geography that serves the session's model requests, and one that omits it clears the agent's pin so the session follows the workspace's `default_inference_geo`. The overridden value is validated against the workspace's `allowed_inference_geos` when the session is created.
645645
646The following example starts a session from an agent whose model has no geo pin, pins the session's model requests to US inference by including `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) in the `model` (java, php; csharp, go: `Model`) override, and prints the value echoed in the response's `agent.model` (java, php; csharp, go: `Agent.Model`):
646The following example starts a session from an agent whose model has no geo pin, pins the session's model requests to US inference by including `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) in the `model` (csharp, go: `Model`) override, and prints the value echoed in the response's `agent.model` (csharp, go: `Agent.Model`):
647647
648648<CodeGroup>
649649 ```bash cURL
from line 800
800800
801801### Set a session budget
802802
803To cap what a session can spend, pass the optional `budget` (java, php; csharp, go: `Budget`) object when you create it. A budget is a hard ceiling on the session's list cost: the platform prices everything the session consumes at public list rates, and the session stops issuing new model requests once that running total reaches `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`). Set `type` (java, php; csharp, go: `Type`) to `limit` and give `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`) an `amount` (java, php; csharp, go: `Amount`) and a `currency` (java, php; csharp, go: `Currency`). `amount` (java, php; csharp, go: `Amount`) is a whole number of US cents written as a string, such as `"125"` for $1.25. The API takes a string rather than a number so no floating-point rounding is ever applied. `USD` is the only currency currently supported. When the session reaches the cap, it pauses and goes idle with the stop reason `budget_reached`. The cap is enforced between model requests, so the request that crosses it finishes first and the session's final list cost can land [a fraction past the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget). A budget can only be attached at creation: you can [change or remove](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-session-budget) it later, but you can't add one to a session created without it.
803To cap what a session can spend, pass the optional `budget` (csharp, go: `Budget`) object when you create it. A budget is a hard ceiling on the session's list cost: the platform prices everything the session consumes at public list rates, and the session stops issuing new model requests once that running total reaches `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`). Set `type` (csharp, go: `Type`) to `limit` and give `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`) an `amount` (csharp, go: `Amount`) and a `currency` (csharp, go: `Currency`). `amount` (csharp, go: `Amount`) is a whole number of US cents written as a string, such as `"125"` for $1.25. The API takes a string rather than a number so no floating-point rounding is ever applied. `USD` is the only currency currently supported. When the session reaches the cap, it pauses and goes idle with the stop reason `budget_reached`. The cap is enforced between model requests, so the request that crosses it finishes first and the session's final list cost can land [a fraction past the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget). A budget can only be attached at creation: you can [change or remove](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-session-budget) it later, but you can't add one to a session created without it.
804804
805805The following example creates a session with a $1.25 budget:
806806
managed-agents/skills Changed · +8 / -8 lines
from line 12
1212
1313Skills are reusable, filesystem-based resources that give your agent domain-specific expertise: workflows, context, and best practices that turn a general-purpose agent into a specialist. Each skill you add incurs a modest cost on the session's context window, adding instructions and metadata that help the model use the skill. Learn more in the [Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) overview.
1414
15Skills reach your agent in two ways: attach them through the agent's `skills` (java, php; csharp, go: `Skills`) array, or [load them from a GitHub repository](https://platform.claude.com/docs/en/managed-agents/skills#load-skills-from-a-github-repository) mounted on the session. Attached skills come in two types. All skills work the same way: your agent invokes them automatically when they are relevant to the task.
15Skills reach your agent in two ways: attach them through the agent's `skills` (csharp, go: `Skills`) array, or [load them from a GitHub repository](https://platform.claude.com/docs/en/managed-agents/skills#load-skills-from-a-github-repository) mounted on the session. Attached skills come in two types. All skills work the same way: your agent invokes them automatically when they are relevant to the task.
1616
1717* **Pre-built Anthropic skills:** Common document tasks such as PowerPoint, Excel, Word, and PDF handling (`pptx`, `xlsx`, `docx`, `pdf`).
1818* **Custom skills:** Skills you author and upload to your workspace.
from line 208
208208 Mounting more skills increases the time it takes for the session's sandbox to start. Attach only the skills each agent needs for its task.
209209</Note>
210210
211Each entry in the `skills` (java, php; csharp, go: `Skills`) array uses the following fields:
211Each entry in the `skills` (csharp, go: `Skills`) array uses the following fields:
212212
213213| Field | Description |
214214| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
215| `type` (java, php; csharp, go: `Type`) | Either `anthropic` for pre-built skills or `custom` for workspace-authored skills. |
215| `type` (csharp, go: `Type`) | Either `anthropic` for pre-built skills or `custom` for workspace-authored skills. |
216216| `skill_id` (java: `skillId`; php: `skillID`; csharp, go: `SkillID`) | The skill identifier. For Anthropic skills, use the short name (for example, `xlsx`). For custom skills, use the `skill_*` ID returned at creation (see [Create a custom skill](https://platform.claude.com/docs/en/managed-agents/skills#create-a-custom-skill)). |
217| `version` (java, php; csharp, go: `Version`) | Pin to a specific version or use `latest`. Optional. Defaults to `latest` when omitted. Applies to both Anthropic and custom skills. |
217| `version` (csharp, go: `Version`) | Pin to a specific version or use `latest`. Optional. Defaults to `latest` when omitted. Applies to both Anthropic and custom skills. |
218218
219219<CodeGroup defaultLanguage="CLI">
220220 ```bash cURL
from line 390
390390
391391## Load skills from a GitHub repository
392392
393Skills can also live in your codebase. When a session mounts a repository through the [`github_repository` resource](https://platform.claude.com/docs/en/managed-agents/github), the repository's root `.claude/skills` directory is scanned at session start, and each skill found there becomes available to the agent. No upload and no entry in the agent's `skills` (java, php; csharp, go: `Skills`) array are required. The agent sees each discovered skill's name, description, and path in the sandbox, and reads the skill's `SKILL.md` when a task matches, including any scripts and resources the skill ships. Discovery relies on the agent's `read` tool from the [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools), which is enabled by default; an agent with `read` disabled doesn't load repository skills.
393Skills can also live in your codebase. When a session mounts a repository through the [`github_repository` resource](https://platform.claude.com/docs/en/managed-agents/github), the repository's root `.claude/skills` directory is scanned at session start, and each skill found there becomes available to the agent. No upload and no entry in the agent's `skills` (csharp, go: `Skills`) array are required. The agent sees each discovered skill's name, description, and path in the sandbox, and reads the skill's `SKILL.md` when a task matches, including any scripts and resources the skill ships. Discovery relies on the agent's `read` tool from the [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools), which is enabled by default; an agent with `read` disabled doesn't load repository skills.
394394
395395<Warning>
396396 Repository skills are agent instructions, so a mounted repository is part of your agent's trust boundary. Anyone who can commit to the repository (a merged external pull request, a compromised dependency, a contributor) can add or change a skill, the platform loads it at session start without a review step, and session tools such as `bash` and `web_fetch` give those instructions real reach. Mount only repositories you trust, and review `.claude/skills` before mounting a repository that accepts outside contributions.
from line 583
583583
584584For private repositories, the resource's `authorization_token` (java, php: `authorizationToken`; csharp, go: `AuthorizationToken`) must have access to the repository. This is the same personal access token flow used for any repository mount; see [Accessing GitHub](https://platform.claude.com/docs/en/managed-agents/github#token-permissions).
585585
586Discovered skills follow the checked-out state of the repository: the `checkout` (java, php; csharp, go: `Checkout`) branch or commit when the resource sets one, otherwise the repository's default branch. The scan runs once, when the session starts. Commits pushed mid-session are not picked up; to load updated skills, start a new session.
586Discovered skills follow the checked-out state of the repository: the `checkout` (csharp, go: `Checkout`) branch or commit when the resource sets one, otherwise the repository's default branch. The scan runs once, when the session starts. Commits pushed mid-session are not picked up; to load updated skills, start a new session.
587587
588Repository skills work alongside skills attached through the agent's `skills` (java, php; csharp, go: `Skills`) array. If a repository skill shares a name with an attached skill, or with a skill from another mounted repository, both are available; each is announced with its own path.
588Repository skills work alongside skills attached through the agent's `skills` (csharp, go: `Skills`) array. If a repository skill shares a name with an attached skill, or with a skill from another mounted repository, both are available; each is announced with its own path.
589589
590590## Next steps
591591
managed-agents/tools Changed · +7 / -7 lines
from line 33
3333
3434## Configuring the toolset
3535
36Enable the full toolset with `agent_toolset_20260401` when creating an agent. Use the `configs` (java, php; csharp, go: `Configs`) array to disable specific tools or override their settings. Each entry is identified by its `name` (java, php; csharp, go: `Name`), which takes a value from the Name column in [Available tools](https://platform.claude.com/docs/en/managed-agents/tools#available-tools). An entry also accepts an optional `type` (java, php; csharp, go: `Type`) field with the same value.
36Enable the full toolset with `agent_toolset_20260401` when creating an agent. Use the `configs` (csharp, go: `Configs`) array to disable specific tools or override their settings. Each entry is identified by its `name` (csharp, go: `Name`), which takes a value from the Name column in [Available tools](https://platform.claude.com/docs/en/managed-agents/tools#available-tools). An entry also accepts an optional `type` (csharp, go: `Type`) field with the same value.
3737
3838Each config entry can also set a `permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`). The policy controls whether the tool's calls run without confirmation, require confirmation, or are evaluated individually by the server. See [Permission policies](https://platform.claude.com/docs/en/managed-agents/permission-policies) for the available policy types.
3939
from line 240
240240
241241### Config entry types in the SDKs
242242
243The Python, TypeScript, Go, Java, C#, Ruby, and PHP SDKs type each `configs` (java, php; csharp, go: `Configs`) entry per tool. The type is a union with one member per built-in tool, discriminated by `type` (java, php; csharp, go: `Type`).
243The Python, TypeScript, Go, Java, C#, Ruby, and PHP SDKs type each `configs` (csharp, go: `Configs`) entry per tool. The type is a union with one member per built-in tool, discriminated by `type` (csharp, go: `Type`).
244244
245In Go, Java, C#, and PHP, you construct entries from typed values rather than plain dictionaries or hashes. In those SDKs, the element type of `configs` (java, php; csharp, go: `Configs`) is the union itself, so build each entry from its per-tool member type.
245In Go, Java, C#, and PHP, you construct entries from typed values rather than plain dictionaries or hashes. In those SDKs, the element type of `configs` (csharp, go: `Configs`) is the union itself, so build each entry from its per-tool member type.
246246
247You can omit `type` (java, php; csharp, go: `Type`) when you construct an entry, because the server infers it from `name` (java, php; csharp, go: `Name`). Responses always include it. This typing does not change the JSON that an entry serializes to. A request whose entries set only `name`, `enabled`, and `permission_policy` is valid with or without `type`.
247You can omit `type` (csharp, go: `Type`) when you construct an entry, because the server infers it from `name` (csharp, go: `Name`). Responses always include it. This typing does not change the JSON that an entry serializes to. A request whose entries set only `name`, `enabled`, and `permission_policy` is valid with or without `type`.
248248
249249## Custom tools
250250
from line 498
498498 ```
499499</CodeGroup>
500500
501A custom tool's name can't start with `mcp__` or `ant__`, or match the name of a built-in agent tool. A request that breaks this rule returns a 400 error. An agent that already has a custom tool whose name starts with `ant__` accepts an update only if the update sends `tools` (java, php; csharp, go: `Tools`) without that name, so rename or remove the tool in your next update. A new session is refused with a 400 error if such a tool is on its agent (after any [overrides](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session)), on an agent in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`), or on an agent in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`). Sessions that already exist aren't affected.
501A custom tool's name can't start with `mcp__` or `ant__`, or match the name of a built-in agent tool. A request that breaks this rule returns a 400 error. An agent that already has a custom tool whose name starts with `ant__` accepts an update only if the update sends `tools` (csharp, go: `Tools`) without that name, so rename or remove the tool in your next update. A new session is refused with a 400 error if such a tool is on its agent (after any [overrides](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session)), on an agent in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (csharp, go: `Subagents`), or on an agent in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (csharp, go: `Workflows`). Sessions that already exist aren't affected.
502502
503503The agent calls its custom tools during a session. To receive the calls and return results, see [Session event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#handling-custom-tool-calls).
504504
managed-agents/tools-web-restrictions Changed · +8 / -8 lines
from line 10
1010 betaHeader: managed-agents-2026-04-01
1111---
1212
13To control which sites the agent's web tools can reach, set a domain list on the `web_search` and `web_fetch` entries of the [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools#configuring-the-toolset). Each of these `configs` (java, php; csharp, go: `Configs`) entries takes one of two lists:
13To control which sites the agent's web tools can reach, set a domain list on the `web_search` and `web_fetch` entries of the [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools#configuring-the-toolset). Each of these `configs` (csharp, go: `Configs`) entries takes one of two lists:
1414
1515* **`allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`):** The tool can reach only these hosts.
1616* **`blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`):** The tool can never reach these hosts.
from line 23
2323
2424## Set domain lists on an agent
2525
26The following example creates an agent that limits `web_search` to two sites and blocks one host for `web_fetch`. It also sets `user_location` (java, php: `userLocation`; csharp, go: `UserLocation`) and `max_content_tokens` (java, php: `maxContentTokens`; csharp, go: `MaxContentTokens`), which [Settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) describes. The example then prints the `configs` (java, php; csharp, go: `Configs`) array from the response.
26The following example creates an agent that limits `web_search` to two sites and blocks one host for `web_fetch`. It also sets `user_location` (java, php: `userLocation`; csharp, go: `UserLocation`) and `max_content_tokens` (java, php: `maxContentTokens`; csharp, go: `MaxContentTokens`), which [Settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) describes. The example then prints the `configs` (csharp, go: `Configs`) array from the response.
2727
2828<CodeGroup defaultLanguage="CLI">
2929 ```bash cURL
from line 376
376376
377377## Settings
378378
379In addition to `enabled` (java, php; csharp, go: `Enabled`) and `permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`), the web tool entries accept the following settings:
379In addition to `enabled` (csharp, go: `Enabled`) and `permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`), the web tool entries accept the following settings:
380380
381381| Setting | Applies to | Description |
382382| ------------------------------------------------------------------------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
from line 433
433433
434434## Validation errors
435435
436The API validates these settings when you [create an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#create-an-agent) or [update an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent). It also validates them when you create or update a session that supplies `tools` (java, php; csharp, go: `Tools`).
436The API validates these settings when you [create an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#create-an-agent) or [update an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent). It also validates them when you create or update a session that supplies `tools` (csharp, go: `Tools`).
437437
438438Format and limit violations are rejected with a 400 `invalid_request_error`:
439439
from line 463
463463
464464## Multiagent and outcome-driven sessions
465465
466In a [multiagent session](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), every domain list that applies to a thread is enforced at the same time. An agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) is bound by three sets of lists:
466In a [multiagent session](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), every domain list that applies to a thread is enforced at the same time. An agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (csharp, go: `Subagents`) is bound by three sets of lists:
467467
468468* Its own `allowed_domains` and `blocked_domains`
469469* Those of any agent that called it
from line 482
482482* A listed agent that sets `blocked_domains` keeps the `allowed_domains` of the session's agent and blocks those hosts within it.
483483* A listed agent that sets its own `allowed_domains` can reach only the hosts that both its list and the list of the session's agent cover.
484484
485A `{"type": "self"}` entry in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) has no web settings of its own and follows the current settings of the session's agent.
485A `{"type": "self"}` entry in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (csharp, go: `Subagents`) has no web settings of its own and follows the current settings of the session's agent.
486486
487487If the combined `allowed_domains` lists have no domain in common, the tool stays available to that agent but every call fails. Each call returns a `url_not_allowed` error stating that no domain is permitted. The tool description tells the model the same. To avoid this, keep each listed agent's `allowed_domains` inside the `allowed_domains` of the session's agent.
488488
from line 492
492492
493493You can change the lists on an idle session by [updating its tools](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-agent-configuration). The new lists apply to the rest of the session.
494494
495In a multiagent session, every thread applies the new lists from its next turn. For an agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`), the update does not change the agent's own lists. Those stay as the agent's definition set them when the session was created.
495In a multiagent session, every thread applies the new lists from its next turn. For an agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (csharp, go: `Subagents`), the update does not change the agent's own lists. Those stay as the agent's definition set them when the session was created.
496496
497497## Differences from the Messages API tools
498498
from line 501
501501* Each list is [capped at 64 domains](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules).
502502* Domains listed for `web_fetch` [cannot include a path](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-format).
503503* Domains [must be ASCII](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-format). The Messages API accepts Unicode entries, though it recommends against them.
504* `max_uses` (java, php: `maxUses`; csharp, go: `MaxUses`), `citations` (java, php; csharp, go: `Citations`), and `cache_control` (java, php: `cacheControl`; csharp, go: `CacheControl`) are not available on the toolset.
504* `max_uses` (java, php: `maxUses`; csharp, go: `MaxUses`), `citations` (csharp, go: `Citations`), and `cache_control` (java, php: `cacheControl`; csharp, go: `CacheControl`) are not available on the toolset.
505505
506506## Next steps
507507
managed-agents/vaults Changed · +10 / -10 lines
from line 20
2020 Vaults and credentials are workspace-scoped, meaning any API key with workspace access can reference them when creating a session. To revoke access, delete the vault or credential.
2121</Warning>
2222
23A vault is the collection of `credentials` associated with an end user. Give it a `display_name` (java, php: `displayName`; csharp, go: `DisplayName`) and optionally tag it with `metadata` (java, php; csharp, go: `Metadata`) so you can map it back to your own user records.
23A vault is the collection of `credentials` associated with an end user. Give it a `display_name` (java, php: `displayName`; csharp, go: `DisplayName`) and optionally tag it with `metadata` (csharp, go: `Metadata`) so you can map it back to your own user records.
2424
2525<CodeGroup>
2626 ```bash cURL
from line 136
136136* **MCP credentials** (`mcp_oauth`, `static_bearer`): each credential is keyed by an `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`). When the agent connects to a server at that URL at session runtime, the token is injected automatically.
137137* **Environment variables** (`environment_variable`): each credential is keyed by a `secret_name` (java, php: `secretName`; csharp, go: `SecretName`) (the environment variable name) and stored in the sandbox as an opaque placeholder. When the agent initiates an outbound request, the opaque placeholder is substituted with the real secret at egress. The agent never sees the secret value. Use this for any service that authenticates through an environment variable, such as CLIs, SDKs, or direct API calls.
138138
139The actual credential values you supply (`token` (java, php; csharp, go: `Token`), `access_token` (java, php: `accessToken`; csharp, go: `AccessToken`), `refresh_token` (java, php: `refreshToken`; csharp, go: `RefreshToken`), `client_secret` (java, php: `clientSecret`; csharp, go: `ClientSecret`), `secret_value` (java, php: `secretValue`; csharp, go: `SecretValue`)) are treated as sensitive, write-only fields and never returned in API responses.
139The actual credential values you supply (`token` (csharp, go: `Token`), `access_token` (java, php: `accessToken`; csharp, go: `AccessToken`), `refresh_token` (java, php: `refreshToken`; csharp, go: `RefreshToken`), `client_secret` (java, php: `clientSecret`; csharp, go: `ClientSecret`), `secret_value` (java, php: `secretValue`; csharp, go: `SecretValue`)) are treated as sensitive, write-only fields and never returned in API responses.
140140
141141<Note>
142142 Environment variable credentials (`environment_variable`) are not yet supported with [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes).
from line 144
144144
145145<Tabs>
146146 <Tab title="MCP OAuth">
147 Use `mcp_oauth` when the MCP server uses OAuth 2.0. If you supply a `refresh` (java, php; csharp, go: `Refresh`) block, Anthropic refreshes the access token on your behalf when it expires.
147 Use `mcp_oauth` when the MCP server uses OAuth 2.0. If you supply a `refresh` (csharp, go: `Refresh`) block, Anthropic refreshes the access token on your behalf when it expires.
148148
149149 The `refresh.token_endpoint_auth.type` field indicates how to authenticate the refresh call:
150150
from line 492
492492 <Tab title="Environment variable">
493493 Use `environment_variable` to authenticate to external services through an environment variable, such as CLIs, SDKs, or direct API calls. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, so check the client eligibility criteria in this tab before configuring one.
494494
495 The `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) array in `networking` (java, php; csharp, go: `Networking`) controls which outbound hosts the secret can be substituted for. Use `"type": "limited"` with a specific list, or `"type": "unrestricted"` if the caller reaches domains you can't enumerate in advance.
495 The `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) array in `networking` (csharp, go: `Networking`) controls which outbound hosts the secret can be substituted for. Use `"type": "limited"` with a specific list, or `"type": "unrestricted"` if the caller reaches domains you can't enumerate in advance.
496496
497497 Limiting domains is strongly recommended for security purposes, and prevents your key from ever being shared with unauthorized hosts.
498498
499499 <Note>
500 `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (java, php; csharp, go: `Networking`) on a vault credential controls which requests use the secret, not which requests are allowed. For the agent to actually reach a domain, it must also be allowed at the [environment level](https://platform.claude.com/docs/en/managed-agents/environments). Both levels must include the domain (either through `unrestricted` networking or by explicitly listing the domain in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`)) for a secret-substituted request to succeed.
500 `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (csharp, go: `Networking`) on a vault credential controls which requests use the secret, not which requests are allowed. For the agent to actually reach a domain, it must also be allowed at the [environment level](https://platform.claude.com/docs/en/managed-agents/environments). Both levels must include the domain (either through `unrestricted` networking or by explicitly listing the domain in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`)) for a secret-substituted request to succeed.
501501 </Note>
502502
503503 The optional `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) field scopes where the secret is substituted; the full semantics follow the example.
from line 697
697697 ```
698698 </CodeGroup>
699699
700 Request payloads are often assembled from content the agent is working with, so the request body is the broader exposure surface. Most services read an API key from a request header, so enabling only `header` (java, php; csharp, go: `Header`) is the narrower configuration. It scopes substitution to request header values for that credential.
700 Request payloads are often assembled from content the agent is working with, so the request body is the broader exposure surface. Most services read an API key from a request header, so enabling only `header` (csharp, go: `Header`) is the narrower configuration. It scopes substitution to request header values for that credential.
701701
702 The credential's `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) controls which parts of an outbound request the secret is substituted into. It is an optional object, a sibling of `networking` (java, php; csharp, go: `Networking`), with two Boolean fields: `header` (java, php; csharp, go: `Header`) (request headers) and `body` (java, php; csharp, go: `Body`) (request body). `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) is independent of `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (java, php; csharp, go: `Networking`): `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) scopes which hosts the secret is substituted for, and `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) scopes which parts of the request it is substituted into.
702 The credential's `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) controls which parts of an outbound request the secret is substituted into. It is an optional object, a sibling of `networking` (csharp, go: `Networking`), with two Boolean fields: `header` (csharp, go: `Header`) (request headers) and `body` (csharp, go: `Body`) (request body). `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) is independent of `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (csharp, go: `Networking`): `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) scopes which hosts the secret is substituted for, and `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) scopes which parts of the request it is substituted into.
703703
704704 `injection_location` behaves differently on create and on update:
705705
from line 710
710710
711711 A credential must have at least one location enabled, so a create or update that would disable both locations returns a 400 error. Passing an explicit `null` for the `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) object or for either field also returns a 400 error ("omit the field instead"). The response always returns both fields with their resolved values.
712712
713 A placeholder in a disabled location is neither substituted nor stripped. The request is sent to the third party with the literal opaque placeholder string in that location. If a request arrives at the third party containing the literal placeholder string, either that location is disabled for the credential or the destination host is not covered by the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in the credential's `networking` (java, php; csharp, go: `Networking`).
713 A placeholder in a disabled location is neither substituted nor stripped. The request is sent to the third party with the literal opaque placeholder string in that location. If a request arrives at the third party containing the literal placeholder string, either that location is disabled for the credential or the destination host is not covered by the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in the credential's `networking` (csharp, go: `Networking`).
714714
715715 <Note>
716716 Credentials created in the Console enable header injection only. If your client sends the secret in the request body, such as a form-encoded token request, the placeholder passes through literally and the service rejects it with its own authentication error. Enable body injection in the Console form when you create the credential, or update the credential with `{"injection_location": {"body": true}}`.
from line 1002
10021002
10031003To diagnose why a refresh failed, call `POST /v1/vaults/{vault_id}/credentials/{credential_id}/mcp_oauth_validate` (or `client.beta.vaults.credentials.mcp_oauth_validate(...)` (typescript: `client.beta.vaults.credentials.mcpOAuthValidate(...)`; csharp: `client.Beta.Vaults.Credentials.McpOAuthValidate(...)`; go: `client.Beta.Vaults.Credentials.MCPOAuthValidate(...)`; java: `client.beta().vaults().credentials().mcpOAuthValidate(...)`; php: `$client->beta->vaults->credentials->mcpOAuthValidate(...)`) in the SDK). This lets you decide how to handle the failure; the right action depends on the error type.
10041004
1005The top-level `status` (java, php; csharp, go: `Status`) tells you what to do next:
1005The top-level `status` (csharp, go: `Status`) tells you what to do next:
10061006
10071007* `valid`: the token works; no action needed.
10081008* `invalid`: the grant is gone or the OAuth server rejected the refresh with a 4xx. Prompt the end user to re-authorize.
managed-agents/workflow-runs Changed · +47 / -43 lines
## Cost and budgets ## Limits ## Budgets and limits
from line 1
11---
22title: Workflow runs
33url: https://platform.claude.com/docs/en/managed-agents/workflow-runs
4description: "Follow an agent's workflow runs: their states and events, when the work is done, what a run blocks, budgets, and limits."
4description: "Follow an agent's workflow runs: their states and events, when the work is done, requests while a run is open, budgets, and limits."
55featureMetadata:
66 topic:
77 title: Managed Agents
from line 10
1010 betaHeader: managed-agents-2026-04-01
1111---
1212
13A **workflow** is a program that an agent writes to run many agents and combine what they return. A **workflow run** is the execution of one workflow. **[Dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#dynamic-workflows)** is the feature that lets an agent write workflows and start runs. You turn it on or off with the `workflows` (java, php; csharp, go: `Workflows`) setting in the agent's `multiagent` (java, php; csharp, go: `Multiagent`) block.
13A **workflow** is a program that an agent writes to run many agents and combine what they return. A **workflow run** is the execution of one workflow. **[Dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#dynamic-workflows)** is the feature that lets an agent write workflows and start runs. You turn it on or off with the `workflows` (csharp, go: `Workflows`) setting in the agent's `multiagent` (csharp, go: `Multiagent`) block.
1414
15The server runs a workflow in the background. Its agents work in [session threads](https://platform.claude.com/docs/en/managed-agents/session-threads) that the server creates as the workflow needs them. You follow runs on the session's [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming). Only the agent starts a run. No event you send ends one; archiving the session can.
15The server runs a workflow in the background. Its agents work in [session threads](https://platform.claude.com/docs/en/managed-agents/session-threads) that the server creates as the workflow needs them. You follow runs on the session's [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming). To stop a run, ask the agent to stop it (see [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)).
1616
1717## How dynamic workflows work
1818
from line 26
2626
2727* **Workflow run:** The server runs the workflow in the background, as one workflow run. A session can have several runs open at the same time.
2828* **Phases:** A workflow can divide its work into phases. A phase is a named stage of the run, such as "Read the contracts". You follow a run's progress by its phase events.
29* **Agent threads:** In a phase, the program runs agents. Each agent works in its own [session thread](https://platform.claude.com/docs/en/managed-agents/session-threads), on a prompt that the program wrote. An agent in a run can be an inline agent, which the program defines itself, or a predefined agent, which you list in the [`predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`)](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents). For what each thread shows, see [A run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads).
29* **Agent threads:** In a phase, the program runs agents. Each agent works in its own [session thread](https://platform.claude.com/docs/en/managed-agents/session-threads), on a prompt that the program wrote. An agent in a run can be an inline agent, which the program defines itself, or a predefined agent, which you list in the [`predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (csharp, go: `Workflows`)](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents). For what each thread shows, see [A run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads).
3030
3131The program can do the following:
3232
from line 48
4848
4949A run starts as running or as idle. Reaching the budget, for example, pauses a running run, which makes it idle; raising or removing the budget then makes it run again, unless an interrupt paused it too. A running run ends when its workflow finishes, the agent stops it, it fails, its lifetime passes, or the session is archived. An idle run can end too, for example when the agent stops it or the session is archived.
5050
51A run is **open** from its `workflow_run.created` event until its `workflow_run.status_ended` event, whether it's running or idle. A run is idle while it's paused, for example at the session's budget. A run's lifetime is 24 hours by default. The agent can set a shorter lifetime when it starts the run. Time that a run spends waiting on your client counts toward that lifetime. A pause doesn't stop a run's lifetime from passing, so a run that stays paused can end with `timeout_error`. The following events report a run's start, its phases, and its end. A pause at the budget sends one too. A pause after an interrupt might send none. Every `workflow_run.*` event includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), which is `null` only on a `workflow_run.error` when no run was created.
51A run is **open** from its `workflow_run.created` event until its `workflow_run.status_ended` event, whether it's running or idle. A run is idle while it's paused, for example at the session's budget. A run has a [lifetime](https://platform.claude.com/docs/en/managed-agents/workflow-runs#limits), which the agent can set when it starts the run. Time that a run spends waiting on your client counts toward that lifetime. A pause doesn't stop a run's lifetime from passing, so a run that stays paused can end with `timeout_error`. The following events report a run's start, its phases, and its end. A pause at the budget sends one too. A pause after an interrupt might send none. Every `workflow_run.*` event includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), which is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) only on a `workflow_run.error` when no run was created.
5252
5353## Run events
5454
5555Run events arrive on the session's event stream, which is the primary thread's stream, and listing the session's events returns them too. Run events don't trigger [webhooks](https://platform.claude.com/docs/en/managed-agents/webhooks). Status events from the run's threads arrive on the same stream. Each names its thread in `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`), and a run's threads are the ones whose `session.thread_created` event had the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`).
5656
57| Event | When it arrives | What to do |
58| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59| `workflow_run.created` | The agent started a run. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) (`wrun_…`), the run's `name` (java, php; csharp, go: `Name`) and `description` (java, php; csharp, go: `Description`), and `phases` (java, php; csharp, go: `Phases`), the phases the workflow declares, each with an `id` (java, php; csharp, go: `ID`), a `name` (java, php; csharp, go: `Name`), and a `description` (java, php; csharp, go: `Description`). A `description` (java, php; csharp, go: `Description`) is `null` when the workflow gives none. `phases` (java, php; csharp, go: `Phases`) is always present and can be empty. The run's and phases' `name` (java, php; csharp, go: `Name`) and `description` (java, php; csharp, go: `Description`) are text the model wrote, so they can repeat words from your request. A run's `name` (java, php; csharp, go: `Name`) can also be one the server assigned. | Track the run as open. Show its `name` (java, php; csharp, go: `Name`), and progress against `phases` (java, php; csharp, go: `Phases`). |
60| `workflow_run.status_running` | When the run starts to execute, which can be a while after `created`, and each time it resumes after a pause at the budget. A resume after an interrupt might not send it. A run that starts idle might get `workflow_run.status_idle` first. | Show the run as running. |
61| `workflow_run.status_idle` | The run was paused, for example at the session's budget. The event doesn't say why. A pause after an interrupt might not send it. | To continue, see [Budgets and limits](https://platform.claude.com/docs/en/managed-agents/workflow-runs#budgets-and-limits) or [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open). |
62| `workflow_run.phase_started`, `workflow_run.phase_ended` | The workflow entered or left a phase, or the run's end closed a phase that was still open. The end event doesn't say whether the phase's work finished. Both include `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`). The end also has `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`), the `id` (java, php; csharp, go: `ID`) of the start event it closes. Neither has the phase's name: look it up by `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`) in the `phases` (java, php; csharp, go: `Phases`) of `workflow_run.created`. | Update progress. Phases run one at a time, in the order of `phases` (java, php; csharp, go: `Phases`), each at most once, but the API doesn't guarantee it. Match a phase's end to its start by `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`). Handle more than one open phase, a phase that isn't in `phases` (java, php; csharp, go: `Phases`), and a listed phase that never starts, even in a run that completes. Every phase that starts also ends, before the run's `workflow_run.status_ended`. |
63| `workflow_run.status_ended` | The run ended. Always the last of the run's `workflow_run.*` events. Includes `result` (java, php; csharp, go: `Result`). | Read `result` (java, php; csharp, go: `Result`) (next table). The agent then gets a turn to read how the run ended. At the budget, or while the primary thread waits on your client, that turn comes later. After an interrupt, that turn might not come: send a `user.message`, or read `result` (java, php; csharp, go: `Result`) yourself. After an archive or termination, it doesn't come. |
64| `workflow_run.error` | The server reports an error of a run, or a start that it refused. A run that ends in `error` gets this event, with the same error, before its `workflow_run.status_ended`. Includes `error` (java, php; csharp, go: `Error`): a `type` (java, php; csharp, go: `Type`) and a `message` (java, php; csharp, go: `Message`) that is safe to log. `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null` when no run was created. | Log it, and don't take it as the run's end. If `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null`, no run started. Otherwise keep tracking the run until its `workflow_run.status_ended`. |
57| Event | When it arrives | What to do |
58| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
59| `workflow_run.created` | The agent started a run. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) (`wrun_…`), the run's `name` (csharp, go: `Name`) and `description` (csharp, go: `Description`), and `phases` (csharp, go: `Phases`), the phases the workflow declares, each with an `id` (csharp, go: `ID`), a `name` (csharp, go: `Name`), and a `description` (csharp, go: `Description`). A `description` (csharp, go: `Description`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) when the workflow gives none. `phases` (csharp, go: `Phases`) is always present and can be empty. The run's and phases' `name` (csharp, go: `Name`) and `description` (csharp, go: `Description`) are text the model wrote, so they can repeat words from your request. A run's `name` (csharp, go: `Name`) can also be one the server assigned. | Track the run as open. Show its `name` (csharp, go: `Name`), and progress against `phases` (csharp, go: `Phases`). |
60| `workflow_run.status_running` | When the run starts to execute, which can be a while after `created`, and each time it resumes after a pause at the budget. A resume after an interrupt might not send it. A run that starts idle might get `workflow_run.status_idle` first. | Show the run as running. |
61| `workflow_run.status_idle` | The run was paused, for example at the session's budget. The event doesn't say why. A pause after an interrupt might not send it. | To continue, see [Cost and budgets](https://platform.claude.com/docs/en/managed-agents/workflow-runs#cost-and-budgets) or [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open). |
62| `workflow_run.phase_started`, `workflow_run.phase_ended` | The workflow entered or left a phase, or the run's end closed a phase that was still open. The end event doesn't say whether the phase's work finished. Both include `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`). The end also has `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`), the `id` (csharp, go: `ID`) of the start event it closes. Neither has the phase's name: look it up by `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`) in the `phases` (csharp, go: `Phases`) of `workflow_run.created`. | Update progress. Phases run one at a time, in the order of `phases` (csharp, go: `Phases`), each at most once, but the API doesn't guarantee it. Match a phase's end to its start by `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`). Handle more than one open phase, a phase that isn't in `phases` (csharp, go: `Phases`), and a listed phase that never starts, even in a run that completes. Every phase that starts also ends, before the run's `workflow_run.status_ended`. |
63| `workflow_run.status_ended` | The run ended. Always the last of the run's `workflow_run.*` events. Includes `result` (csharp, go: `Result`). | Read `result` (csharp, go: `Result`) (next table). The agent then gets a turn to read how the run ended. At the budget, or while the primary thread waits on your client, that turn comes later. After an interrupt, that turn might not come: send a `user.message`, or read `result` (csharp, go: `Result`) yourself. After an archive or termination, it doesn't come. |
64| `workflow_run.error` | The server reports an error of a run, or a start that it refused. A run that ends in `error` gets this event, with the same error, before its `workflow_run.status_ended`. Includes `error` (csharp, go: `Error`): a `type` (csharp, go: `Type`) and a `message` (csharp, go: `Message`) that is safe to log. `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) when no run was created. | Log it, and don't take it as the run's end. If `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`), no run started. Otherwise keep tracking the run until its `workflow_run.status_ended`. |
6565
6666| `result` | Meaning |
6767| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
6868| `{"type": "completed"}` | The workflow finished running. The result doesn't say whether the work passed. A run can end `completed` even though work on its threads failed, or a thread couldn't be created. To find failed work, read the events of each of the [run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads). |
69| `{"type": "stopped"}` | The agent stopped the run, or the session was archived. The event doesn't say which, and later releases might add other causes. |
70| `error` with `timeout_error` | The run reached its lifetime: 24 hours by default, or the one the agent set. |
69| `{"type": "stopped"}` | The agent stopped the run, or the session was archived. The event doesn't say which. Don't treat these as the only causes. |
70| `error` with `timeout_error` | The run reached its [lifetime](https://platform.claude.com/docs/en/managed-agents/workflow-runs#limits), which the agent can set. |
7171| `error` with `program_error` | The workflow failed. Its code failed, or it broke a rule for workflows, other than a limit. Or one of the run's threads failed, or couldn't be created, and the workflow let that end the run. |
72| `error` with `thread_limit_error` | The run went over its [limit on the agents that a workflow starts](https://platform.claude.com/docs/en/managed-agents/workflow-runs#budgets-and-limits). |
72| `error` with `thread_limit_error` | The run went over its [limit on the agents that a workflow starts](https://platform.claude.com/docs/en/managed-agents/workflow-runs#limits). |
7373| `error` with `unknown_error` | The server couldn't continue the run, or the run went over one of the server's other limits on workflows. |
7474
7575An error result looks like `{"type": "error", "error": {"type": "timeout_error", "message": "..."}}`, where `message` is safe to log. Treat an unrecognized `result.type` as a run that ended some other way, and an unrecognized `error.type` as an error. When something the session depends on fails, such as the model, an MCP server, credentials, or billing, the failing thread's stream gets a `session.error`. That doesn't end a run by itself. But if it makes one of the run's threads fail, and the workflow lets that end the run, the run ends with `program_error`.
from line 76
7676
7777For example, you ask the [contract-review agent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows) which of 300 contracts have a change-of-control clause, and the agent starts a run:
7878
791. `workflow_run.created` names the run "Find change-of-control clauses" and lists the phases "Read the contracts" and "Reconcile the findings" in `phases` (java, php; csharp, go: `Phases`). Then `workflow_run.status_running` follows.
791. `workflow_run.created` names the run "Find change-of-control clauses" and lists the phases "Read the contracts" and "Reconcile the findings" in `phases` (csharp, go: `Phases`). Then `workflow_run.status_running` follows.
80802. Phase events mark each phase, and each thread the run creates sends `session.thread_created` with the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`).
81813. `workflow_run.status_ended` arrives with `result: {"type": "completed"}`.
82824. The agent answers, "41 of the 300 contracts have one," and `session.status_idle` arrives with `end_turn`.
from line 128
128128
129129## A run's threads
130130
131Each agent in a run works in its own [session thread](https://platform.claude.com/docs/en/managed-agents/session-threads), which the server creates as the workflow needs it. You can list, read, and stream a run's threads like any child thread, and answer their tool calls from the primary stream. To stop them, ask the agent to stop the run (see [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)). You can't stop one by its ID, or archive one while its run is open.
131Each agent in a run works in its own [session thread](https://platform.claude.com/docs/en/managed-agents/session-threads), which the server creates as the workflow needs it. You can list, read, and stream a run's threads like any child thread, and answer their tool calls from the primary stream. To stop them, ask the agent to stop the run (see [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open)).
132132
133* **Grouping:** A run's thread carries the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), as does the `session.thread_created` event that announces it. Other threads, and the `session.thread_created` events that announce them, have `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) set to `null`.
134* **Agent:** `agent` (java, php; csharp, go: `Agent`) shows the agent the thread runs. For an agent you listed in the [`predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`)](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows) in `multiagent` (java, php; csharp, go: `Multiagent`), `agent` (java, php; csharp, go: `Agent`) has that agent's `id` (java, php; csharp, go: `ID`) and `version` (java, php; csharp, go: `Version`), as on the thread of a subagent you listed. For an agent the workflow defines (an inline agent), `agent` (java, php; csharp, go: `Agent`) has `type` (java, php; csharp, go: `Type`) `inline` and no `id` (java, php; csharp, go: `ID`) or `version` (java, php; csharp, go: `Version`). It has the system prompt the workflow wrote, not the session agent's. It also has the name and description the workflow gave it; the server assigns a name if the workflow gave none. It uses the model of the session agent, the agent the session runs. Its tools, MCP servers, and skills are a subset of the session agent's. It gets all of them, but the API doesn't guarantee that. Its tools keep their permission policies.
133* **Grouping:** A run's thread has the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), as does the `session.thread_created` event that announces it. Other threads, and the `session.thread_created` events that announce them, have `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) set to `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`).
134* **Agent:** `agent` (csharp, go: `Agent`) shows the agent the thread runs. For an agent you listed in the [`predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (csharp, go: `Workflows`)](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows) in `multiagent` (csharp, go: `Multiagent`), `agent` (csharp, go: `Agent`) has that agent's `id` (csharp, go: `ID`) and `version` (csharp, go: `Version`), as on the thread of a subagent you listed. For an agent the workflow defines (an inline agent), `agent` (csharp, go: `Agent`) has `type` `inline` and no `id` (csharp, go: `ID`) or `version` (csharp, go: `Version`). It has the system prompt the workflow wrote, not the session agent's. It also has the name and description the workflow gave it. The server assigns a name if the workflow gave none. It uses the model of the session agent, the agent the session runs. Its tools, MCP servers, and skills are a subset of the session agent's. It gets all of them, but the API doesn't guarantee that. Its tools keep their permission policies.
135135* **What the threads share:** A run's threads work in the session's sandbox, so every thread works with the same files. That includes the files of a memory store the session mounts. An agent the workflow defines uses its MCP servers with the credentials the session resolves for them. Each thread has its own conversation history.
136136* **Events:** A run thread's `session.thread_created`, `session.thread_status_running`, `session.thread_status_idle`, and `session.thread_status_terminated` events also arrive on the primary stream (see [Run events](https://platform.claude.com/docs/en/managed-agents/workflow-runs#run-events)). Its message events stay on its own stream. Its thread webhooks are sent as for any child thread. For what the thread's own stream records, see [Session thread events](https://platform.claude.com/docs/en/managed-agents/session-threads#session-thread-events).
137137* **Phases:** No event or field says which phase a thread works in, and threads of one run can have the same `agent_name`. Follow a run's progress by its phase events, and tell its threads apart by `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`).
138* **Thread limit:** A run's threads are exempt from the session's [child-thread limit](https://platform.claude.com/docs/en/managed-agents/session-threads#primary-thread-and-session-threads).
139* **Starting runs:** Only the agent on the session's primary thread starts runs. An agent working in a run's thread can't start a run of its own, so runs don't nest.
140* **Archiving:** The server archives each thread no later than the end of its run. It can archive one sooner, once the thread returns its result or the run finishes with it. If the thread is still running or waiting on your client at that point, the server stops it first. An archived thread stays in the thread list, with status `terminated`. You don't need to archive a run's threads yourself. While the run is open, a request to archive one that the server hasn't archived yet returns 400 with `error.details.error_code: "workflow_run_open"`.
141* **Visibility:** You don't see the workflow's code, but you can ask the agent for the workflow, as the tip after this list describes. You also don't see the tool calls the agent makes to start and manage runs, or the result each thread returns to the workflow.
138* **Archiving:** The server archives each thread no later than the end of its run. It can archive one sooner, once the thread returns its result or the run finishes with it. If the thread is still running or waiting on your client at that point, the server stops it first. An archived thread stays in the thread list, with status `terminated`. You don't need to archive a run's threads yourself.
139* **Tools:** A run can create more than one thread for the same piece of work, so make the tools your agents call safe to call twice.
142140
143141<Tip>
144142 You can ask the agent for the workflow that it wrote for your request. Wait until the run has ended and the session is `idle`. Then send a `user.message` that asks the agent to print the workflow that it started the run with, word for word, and not to start another run.
from line 156
158156* **Paused runs:** A paused run doesn't keep the session `running`, so the session can go idle while the run is still open. At the budget, for example, the session goes idle with `budget_reached`. The work isn't done until the run ends.
159157* **Another run:** The agent can start a new run when it reads a result, so check again.
160158* **Outcomes:** If you [defined an outcome](https://platform.claude.com/docs/en/managed-agents/define-outcomes), no evaluation starts while a run is open, whether it's running or idle. The turn in which the agent reads the run's result can start one.
161* **`retries_exhausted`:** The agent's turn failed on an error: retries ran out, or the error can't be retried, such as a billing failure. A run might still be running when this idle comes. If a run ended and the agent hasn't read its result yet, the server starts a new turn with no input from you. The session goes `running` again, so wait for the next idle. If the session stays idle, read the `session.error` that came before it and fix the cause. Then send a `user.message`, or read each run's `result` (java, php; csharp, go: `Result`) yourself.
159* **`retries_exhausted`:** The agent's turn failed on an error: retries ran out, or the error can't be retried, such as a billing failure. A run might still be running when this idle comes. If a run ended and the agent hasn't read its result yet, the server starts a new turn with no input from you. The session goes `running` again, so wait for the next idle. If the session stays idle, read the `session.error` that came before it and fix the cause. Then send a `user.message`, or read each run's `result` (csharp, go: `Result`) yourself.
162160
163161## Follow a run
164162
from line 763
765763
766764Send [`user.interrupt`](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#interrupt-the-agent) with no `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`), or with the primary thread's ID. It stops the agent's turn. It ends no run. The session's runs might pause or keep running, and their events might not show which. A paused run's lifetime keeps passing, so the run can end with `timeout_error` while it's paused.
767765
768* **Waiting tool calls:** After the interrupt, a run thread's tool call might still wait on your client. Answer each one. To cancel a call that asks for confirmation, deny it. To cancel a custom tool call, send a result with `is_error` (java, php: `isError`; csharp, go: `IsError`) set to `true` and a text in `content` (java, php; csharp, go: `Content`) that says why. While the session is `idle` with `requires_action`, a `user.message` returns 400, so answer the calls first.
766* **Waiting tool calls:** After the interrupt, a run thread's tool call might still wait on your client. Answer each one. To cancel a call that asks for confirmation, deny it. To cancel a custom tool call, send a result with `is_error` (java, php: `isError`; csharp, go: `IsError`) set to `true` and a text in `content` (csharp, go: `Content`) that says why. While the session is `idle` with `requires_action`, a `user.message` returns 400, so answer the calls first.
769767* **To stop the runs:** Send a `user.message` asking the agent to stop its runs. A stopped run ends with `result` `{"type": "stopped"}`. While the session is `idle` with `budget_reached`, a `user.message` returns 400 until you raise or remove the budget. Raising or removing it also resumes the runs that the budget paused, unless the interrupt also paused them.
770768* **To continue:** Send a `user.message` asking the agent to continue its runs. After an interrupt, the runs might wait for this message. If the session is `idle` with `budget_reached`, raise or remove the budget first.
771769* **Run results:** A run that ends after the interrupt still sends `workflow_run.status_ended`.
from line 770
772770
773771## While a run is open
774772
775| Request | While a run is open | What to do |
776| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
777| Archive or delete the session | Might return 400 while a run is open, whatever the session's status. The error's `error.details.error_code` can be `"workflow_run_open"`. Might also succeed. | Ask the agent to stop its runs, or wait until each run has ended. A paused run ends by itself only when its lifetime passes. Then send the request once the session is `idle`. An archive that succeeds ends each open run with `{"type": "stopped"}`. After an archive, a run's `workflow_run.status_ended`, and the `workflow_run.phase_ended` of a phase that was still open, don't arrive on the stream. List the session's events to read them. After a delete that succeeds, no `workflow_run` event reports the end of the session's runs. |
778| Archive one of a run's threads | Returns 400 with `error.details.error_code: "workflow_run_open"` while the run is open, running or idle, unless the server has already archived the thread. | Nothing. The server archives a run's threads. |
779| Update the session's `agent` (java, php; csharp, go: `Agent`) | Returns 400 with `error.details.error_code: "workflow_run_open"` while any run is open, even a paused one. Updating the underlying agent is still accepted, and the session keeps its own copy. A request that also sends other fields, such as `budget` (java, php; csharp, go: `Budget`), is rejected whole. | Wait until every run has its `workflow_run.status_ended`, or ask the agent to stop its runs. |
780| Answer a tool call or tool confirmation from a run's thread | Allowed. It arrives on the primary stream, and its `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) names the thread. | Answer as soon as the event arrives, passing the event's `id` (java, php; csharp, go: `ID`) as `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) or `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`). Don't wait for `session.status_idle`: the session can stay `running` while the run's other threads work. Once the server has archived the thread, a tool result for one of its calls has no effect, and it can return 400. When a tool result returns 400, find the call's thread in the thread list. If its status is `terminated`, the result came too late, so drop it. Send each tool result in a request of its own, because the server refuses a whole request when it refuses one of its events. A tool confirmation that comes too late returns 200, which doesn't mean that the tool ran. |
773| Request | While a run is open | What to do |
774| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
775| Archive or delete the session | Might return 400 while a run is open, whatever the session's status. The error's `error.details.error_code` can be `"workflow_run_open"`. Might also succeed. | Ask the agent to stop its runs, or wait until each run has ended. A paused run ends by itself only when its lifetime passes. Then send the request once the session is `idle`. An archive that succeeds ends each open run with `{"type": "stopped"}`. After an archive, a run's `workflow_run.status_ended`, and the `workflow_run.phase_ended` of a phase that was still open, don't arrive on the stream. List the session's events to read them. After a delete that succeeds, no `workflow_run` event reports the end of the session's runs. |
776| Archive one of a run's threads | Returns 400 with `error.details.error_code: "workflow_run_open"` while the run is open, running or idle, unless the server has already archived the thread. | Nothing. The server archives a run's threads. |
777| Update the session's `agent` (csharp, go: `Agent`) | Returns 400 with `error.details.error_code: "workflow_run_open"` while any run is open, even a paused one. Updating the underlying agent is still accepted, and the session keeps its own copy. A request that also sends other fields, such as `budget` (csharp, go: `Budget`), is rejected whole. | Wait until every run has its `workflow_run.status_ended`, or ask the agent to stop its runs. |
778| Answer a tool call or tool confirmation from a run's thread | Allowed. It arrives on the primary stream, and its `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) names the thread. | Answer as soon as the event arrives, passing the event's `id` (csharp, go: `ID`) as `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) or `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`). Don't wait for `session.status_idle`: the session can stay `running` while the run's other threads work. Once the server has archived the thread, a tool result for one of its calls has no effect, and it can return 400. When a tool result returns 400, find the call's thread in the thread list. If its status is `terminated`, the result came too late, so drop it. Send each tool result in a request of its own, because the server refuses a whole request when it refuses one of its events. A tool confirmation that comes too late returns 200, which doesn't mean that the tool ran. |
781779
782780### Rebuild run state after you reconnect
783781
784Rebuild each run's state from the session's events. The stream doesn't replay what you missed: a new connection delivers only events emitted after it opened. So list the events with a `types` (java, php; csharp, go: `Types`) filter, one entry for each event type, as in [List past events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#list-past-events). Pass each response's `next_page` (java, php: `nextPage`; csharp, go: `NextPage`) as `page` (java, php; csharp, go: `Page`) until `next_page` (java, php: `nextPage`; csharp, go: `NextPage`) is `null` or missing. `workflow_run.created`, `workflow_run.status_running`, `workflow_run.status_idle`, and `workflow_run.status_ended` give each run's state, except that a run paused after an interrupt might still show as running. `workflow_run.phase_started` and `workflow_run.phase_ended` rebuild progress. A run with no status event yet hasn't started to execute. No endpoint lists runs.
782Rebuild each run's state from the session's events. The stream doesn't replay what you missed: a new connection delivers only events emitted after it opened. So list the events with a `types` (curl: `types[]`; cli: `--type`; csharp, go: `Types`) filter, one entry for each event type, as in [List past events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#list-past-events). Pass each response's `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) as `page` (cli: `--page`; csharp, go: `Page`) until `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) or missing. `workflow_run.created`, `workflow_run.status_running`, `workflow_run.status_idle`, and `workflow_run.status_ended` give each run's state, except that a run paused after an interrupt might still show as running. `workflow_run.phase_started` and `workflow_run.phase_ended` rebuild progress. A run with no status event yet hasn't started to execute. No endpoint lists runs.
785783
786## Budgets and limits
784## Cost and budgets
787785
788786A run's model requests count toward the [session's budget](https://platform.claude.com/docs/en/managed-agents/budgets). A run has no price of its own. The tokens its agents use are billed like the session's other tokens, at each model's rates. For all of a session's charges, see [Claude Managed Agents pricing](https://platform.claude.com/docs/en/about-claude/pricing#claude-managed-agents-pricing).
789787
790* **One run's usage:** List the session's threads and add up the token counts in `usage` (java, php; csharp, go: `Usage`) of the threads with the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`). The list includes archived threads, whose status is `terminated`, so a finished run's threads are counted. Pass each response's `next_page` (java, php: `nextPage`; csharp, go: `NextPage`) as `page` (java, php; csharp, go: `Page`) until `next_page` (java, php: `nextPage`; csharp, go: `NextPage`) is `null` or missing, and skip a thread whose `usage` (java, php; csharp, go: `Usage`) is `null`. If you add up the threads' `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) instead, the total leaves out session runtime, and each figure is rounded separately.
791* **At the budget:** Every open run pauses, and the session reports `idle` with `budget_reached`, or `requires_action` if a tool call is also waiting. Each thread finishes the model request it already started, so a run can pass the budget by one request for each working thread. Raising or removing the budget resumes the runs it paused, unless an interrupt also paused them. If the session's usage includes a model with no list price, only removing the budget does; see [Models without a list price](https://platform.claude.com/docs/en/managed-agents/budgets#models-without-a-list-price).
788* **One run's usage:** List the session's threads and add up the token counts in `usage` (csharp, go: `Usage`) of the threads with the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`). The list includes archived threads, whose status is `terminated`, so a finished run's threads are counted. Pass each response's `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) as `page` (cli: `--page`; csharp, go: `Page`) until `next_page` (ruby: `next_page_`; java, php: `nextPage`; csharp, go: `NextPage`) is `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `""`) or missing, and skip a thread with no `usage` (csharp, go: `Usage`). If you add up the threads' `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) instead, the total leaves out session runtime, and each figure is rounded separately.
789* **At the budget:** Every open run pauses, and the session reports `idle` with `budget_reached`, or `requires_action` if a tool call is also waiting. Each thread finishes the model request it already started, so a run can pass the budget by one request for each working thread. Raising or removing the budget resumes the runs it paused, unless an interrupt also paused them. If the session's usage includes a model with no list price, only removing the budget does; see [Models without a list price](https://platform.claude.com/docs/en/managed-agents/budgets#models-without-a-list-price). A paused run's lifetime keeps passing, so the run can end with `timeout_error` while it's paused.
792790
791## Limits
792
793793| Limit | Value | At the limit |
794794| -------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
795| Threads working at once in one run | 64 | The run creates no more until one finishes. The API doesn't guarantee this number, so it can change. |
795| Threads working at once in one run | 64 | The run creates no more until one finishes. The API doesn't guarantee this number. |
796796| Agents a workflow starts over the run's whole life | 1,000 | When the workflow asks for more, the server doesn't start another agent, and the run ends with `thread_limit_error`. The server can run a failed agent again on a new thread, so a run might have more than 1,000 threads. |
797797| Run lifetime | 24 hours by default, or the lifetime the agent sets | The run ends with `timeout_error`. No event says what lifetime the agent set. |
798798| Runs open at once in a session | 10 by default | The server refuses to start another run. The agent's tool call gets an error, and you get a `workflow_run.error` whose `error.type` is `max_workflow_runs_error`. Idle runs count toward the limit. |
799799
800The server shortens a run's or phase's `name` (java, php; csharp, go: `Name`) to 64 characters and its `description` (java, php; csharp, go: `Description`) to 256. The server has other limits on workflows, and rules for them, that aren't listed here. What you see depends on when the server finds the problem:
800The server shortens a run's or phase's `name` (csharp, go: `Name`) to 64 characters and its `description` (csharp, go: `Description`) to 256. The server has other limits on workflows, and rules for them, that aren't listed here. What you see depends on when the server finds the problem:
801801
802802| What happens | What you see |
803803| -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
from line 807
807807
808808A session can start any number of runs over its life.
809809
810* **Starting runs:** Only the agent on the session's primary thread starts runs. An agent working in a run's thread can't start a run of its own, so runs don't nest.
811* **Ending runs:** No event you send ends a run; archiving the session can.
812* **A run's threads:** You can't [stop one by its ID](https://platform.claude.com/docs/en/managed-agents/session-threads#interrupt-a-session-thread), or archive one while its run is open.
813* **Thread limit:** A run's threads are exempt from the session's [child-thread limit](https://platform.claude.com/docs/en/managed-agents/session-threads#primary-thread-and-session-threads).
814* **Visibility:** You don't see the workflow's code, but you can ask the agent for the workflow, as the tip in [A run's threads](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads) describes. You also don't see the tool calls the agent makes to start and manage runs, or the result each thread returns to the workflow.
815
810816### Rate limits
811817
812818A run's work counts toward rate limits that your organization already has.
from line 828
822828* If it's `exhausted`, the thread has failed. If the workflow lets that failure end the run, the run ends with `program_error`, which doesn't name the cause. Read the failed threads' events to find it.
823829
824830The server also limits how much all of your organization's sessions do each minute. A thread that meets this limit stops, with a `session.error` on its own stream whose message names a rate limit. Wait a minute before you ask the agent to continue.
825
826A run can create more than one thread for the same piece of work, so make the tools your agents call safe to call twice.
827831
agents-and-tools/agent-skills/claude-api-skill Changed · +1 / -1 lines
from line 121
121121* **Cloud platform detection**, preserving platform-specific model ID formats (for example, the `anthropic.` prefix on Amazon Bedrock) and skipping changes for features that are unavailable on partner-operated platforms
122122* **Breaking parameter changes**, such as removing `temperature`, `top_p`, and `top_k` for Claude Opus 4.8 and Claude Opus 4.7, and converting `thinking: {type: "enabled", budget_tokens: N}` to `thinking: {type: "adaptive"}`
123123* **Prefill replacement**, converting assistant-message prefill patterns to [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) where applicable
124* **Beta header cleanup**, removing beta headers that the target model doesn't require (for example, `effort-2025-11-24`, `fine-grained-tool-streaming-2025-05-14`, `interleaved-thinking-2025-05-14`) and switching back from `client.beta.messages.create()` (python, typescript, ruby; go: `client.Beta.Messages.New()`; java: `client.beta().messages().create()`; csharp: `client.Beta.Messages.Create()`; php: `$client->beta->messages->create()`) to `client.messages.create()` (python, typescript, ruby; go: `client.Messages.New()`; java: `client.messages().create()`; csharp: `client.Messages.Create()`; php: `$client->messages->create()`)
124* **Beta header cleanup**, removing beta headers that the target model doesn't require (for example, `effort-2025-11-24`, `fine-grained-tool-streaming-2025-05-14`, `interleaved-thinking-2025-05-14`) and switching back from `client.beta.messages.create()` (go: `client.Beta.Messages.New()`; java: `client.beta().messages().create()`; csharp: `client.Beta.Messages.Create()`; php: `$client->beta->messages->create()`) to `client.messages.create()` (go: `client.Messages.New()`; java: `client.messages().create()`; csharp: `client.Messages.Create()`; php: `$client->messages->create()`)
125125* **Effort calibration**, recommending an `output_config.effort` starting point for the target model (for example, the default `high` on Claude Opus 5, and `xhigh` for coding and agentic use cases on Claude Opus 4.8 and Claude Opus 4.7)
126126* **Prompt-behavior tuning**, flagging length-control, tool-triggering, subagent, and instruction-following prompts that may behave differently on the target model
127127* **Silent default handling**, opting back into thinking summarization (`thinking.display: "summarized"`) when reasoning is surfaced to users on Claude Opus 4.8 and Claude Opus 4.7
agents-and-tools/tool-use/advisor-tool Changed · +1 / -1 lines
from line 1584
15841584| Feature | Interaction |
15851585| ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15861586| [Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing) | Supported. `usage.iterations` is reported per item. |
1587| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | Returns the executor's first-iteration input tokens only. For a rough advisor estimate, call `client.beta.messages.count_tokens()` (python, ruby; typescript: `client.beta.messages.countTokens()`; go, csharp: `client.Beta.Messages.CountTokens()`; java: `client.beta().messages().countTokens()`; php: `$client->beta->messages->countTokens()`; cli: `ant beta:messages count-tokens`; curl: `POST /v1/messages/count_tokens`) with `model` set to the advisor model and the same messages. |
1587| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | Returns the executor's first-iteration input tokens only. For a rough advisor estimate, call `client.beta.messages.count_tokens()` (typescript: `client.beta.messages.countTokens()`; go, csharp: `client.Beta.Messages.CountTokens()`; java: `client.beta().messages().countTokens()`; php: `$client->beta->messages->countTokens()`; cli: `ant beta:messages count-tokens`; curl: `POST /v1/messages/count_tokens`) with `model` set to the advisor model and the same messages. |
15881588| [Context editing](https://platform.claude.com/docs/en/build-with-claude/context-editing) | `clear_tool_uses` is not fully compatible with advisor tool blocks. With `clear_thinking`, see the earlier caching warning. |
15891589| `pause_turn` | A dangling advisor call ends the response with `stop_reason: "pause_turn"` and a `server_tool_use` block with no result when no client `tool_use` block is awaiting your result in the same turn. The advisor runs on resumption. If the executor also called one of your tools in that turn, the response ends with `stop_reason: "tool_use"` instead, and the pending advisor call runs at the start of your next request, after you send the `tool_result` blocks. See [Resuming a paused turn](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#resuming-a-paused-turn), [Mixing server tools and client tools in one turn](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#mixing-server-tools-and-client-tools-in-one-turn), and [Server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#the-server-side-loop-and-pause-turn). |
15901590
agents-and-tools/tool-use/computer-use-tool Changed · +2 / -2 lines
from line 2123
21232123
21242124Upgrading from `computer_20251124` to the toolset is optional: the models listed for `computer_20251124` under [Earlier tool versions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#earlier-tool-versions) keep accepting it with its beta header, so an existing integration keeps working until you change it. Claude 5.5 and later models are the exception on the Claude API and Google Cloud: there they accept only the toolset. Upgrade an integration before you move it to one of them. On Amazon Bedrock, Claude Opus 5.5, Claude Sonnet 5.5, and Claude Haiku 5.5 accept `computer_20251124`. To upgrade, make the following changes together:
21252125
21261. **Remove the beta header.** Drop `anthropic-beta: computer-use-2025-11-24` from your requests. With the SDK, remove `betas` (python, typescript, php, ruby; csharp, go: `Betas`; java: `.addBeta()`) and call the Messages API through the standard client rather than the beta namespace.
21261. **Remove the beta header.** Drop `anthropic-beta: computer-use-2025-11-24` from your requests. With the SDK, remove `betas` (csharp, go: `Betas`; java: `.addBeta()`) and call the Messages API through the standard client rather than the beta namespace.
212721272. **Change the `tools` entry.** Set `type` to `computer_toolset_20260801` and delete `name`, `display_width_px`, `display_height_px`, `display_number`, and `enable_zoom`. The toolset rejects each of these fields.
212821283. **Choose whether to keep zoom enabled.** Zoom is enabled by default on the toolset, whereas `enable_zoom` defaults to `false`. If your environment doesn't implement zoom, add `"configs": {"zoom": {"enabled": false}}` to keep the previous behavior; otherwise implement it (see [Available actions](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool#available-actions)).
212921294. **Handle every block in a turn.** Update your agent loop to iterate over every `tool_use` block in a response rather than reading only the first, and to dispatch on the block's `name` together with `toolset_name` instead of on `input.action`. Member inputs no longer contain an `action` field; the remaining fields are unchanged.
from line 2179
21792179
21802180## Earlier tool versions
21812181
2182Two earlier versions of the computer use tool remain available in beta for existing integrations, for models that don't support the toolset, and on platforms where the toolset isn't currently available. Each requires its [beta header](https://platform.claude.com/docs/en/api/beta-headers) on every request, and their parameters are documented in the [beta Messages API reference](https://platform.claude.com/docs/en/api/beta/messages/create). With the SDK, pass the header through `betas` (python, typescript, php, ruby; csharp, go: `Betas`; java: `.addBeta()`) and use the beta namespace; only the computer use tool needs the header, not the bash or text editor tools in the same request.
2182Two earlier versions of the computer use tool remain available in beta for existing integrations, for models that don't support the toolset, and on platforms where the toolset isn't currently available. Each requires its [beta header](https://platform.claude.com/docs/en/api/beta-headers) on every request, and their parameters are documented in the [beta Messages API reference](https://platform.claude.com/docs/en/api/beta/messages/create). With the SDK, pass the header through `betas` (csharp, go: `Betas`; java: `.addBeta()`) and use the beta namespace; only the computer use tool needs the header, not the bash or text editor tools in the same request.
21832183
21842184| Tool version | Beta header | Use with | Parameters |
21852185| ------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
api/claude-platform-on-aws-iam-actions Changed · +1 / -1 lines
from line 23
2323
2424## Actions
2525
26The service defines 72 actions. Actions follow the AWS `VerbNoun` convention and use verb discipline so that `Get*` and `List*` wildcards produce a clean read-only boundary.
26Actions follow the AWS `VerbNoun` convention and use verb discipline so that `Get*` and `List*` wildcards produce a clean read-only boundary.
2727
2828### Inference
2929
api/errors Changed · +1 / -1 lines
from line 72
7272
7373## SDK error types
7474
75The official SDK raises typed exceptions for these errors instead of returning raw JSON. For example, a 404 surfaces as `anthropic.NotFoundError` (python; typescript: `Anthropic.NotFoundError`; ruby: `Anthropic::Errors::NotFoundError`; java: `com.anthropic.errors.NotFoundException`; csharp: `AnthropicNotFoundException`; php: `Anthropic\Core\Exceptions\NotFoundException`; go: `*anthropic.Error`). The Go SDK has one error type for every status, `*anthropic.Error`: branch on `StatusCode`. Catch the SDK's typed classes rather than string-matching error messages, handling the most specific classes first. Your SDK's page documents the full exception hierarchy:
75The official SDK raises typed exceptions for these errors instead of returning raw JSON. For example, a 404 surfaces as `anthropic.NotFoundError` (typescript: `Anthropic.NotFoundError`; ruby: `Anthropic::Errors::NotFoundError`; java: `com.anthropic.errors.NotFoundException`; csharp: `AnthropicNotFoundException`; php: `Anthropic\Core\Exceptions\NotFoundException`; go: `*anthropic.Error`). The Go SDK has one error type for every status, `*anthropic.Error`: branch on `StatusCode`. Catch the SDK's typed classes rather than string-matching error messages, handling the most specific classes first. Your SDK's page documents the full exception hierarchy:
7676
7777* [Python](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/python#handling-errors) · [TypeScript](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/typescript#handling-errors) · [C#](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/csharp#error-handling) · [Go](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/go#error-handling) · [Java](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/java#error-handling) · [PHP](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/php#error-handling) · [Ruby](https://platform.claude.com/docs/en/cli-sdks-libraries/sdks/ruby#handling-errors)
7878
api/overview Changed · +1 / -1 lines
from line 148
148148
149149To go back a page, pass `prev_page` as the `page` parameter. `prev_page` is `null` when you're on the first page. Not all list endpoints support `prev_page`. Only `GET /v1/sessions` returns `prev_page`; on list endpoints that do not support backward pagination, the field is absent from the response rather than `null`. For a request walkthrough, see [Listing sessions](https://platform.claude.com/docs/en/managed-agents/session-operations#listing-sessions).
150150
151The SDK provides an auto-paginating iterator that follows `next_page` for you. For example, `for session in client.beta.sessions.list()` (python; typescript: `for await (const session of client.beta.sessions.list())`; go: `client.Beta.Sessions.ListAutoPaging()`; java: `client.beta().sessions().list().autoPager()`; csharp: `(await client.Beta.Sessions.List()).Paginate()`; php: `$client->beta->sessions->list()->pagingEachItem()`; ruby: `client.beta.sessions.list.auto_paging_each`) walks through every session. SDK auto-pagination is forward-only; to go back a page, read `prev_page` from the response and pass it back as the `page` parameter yourself. See [client SDKs](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) for details.
151The SDK provides an auto-paginating iterator that follows `next_page` for you. For example, `for session in client.beta.sessions.list()` (typescript: `for await (const session of client.beta.sessions.list())`; go: `client.Beta.Sessions.ListAutoPaging()`; java: `client.beta().sessions().list().autoPager()`; csharp: `(await client.Beta.Sessions.List()).Paginate()`; php: `$client->beta->sessions->list()->pagingEachItem()`; ruby: `client.beta.sessions.list.auto_paging_each`) walks through every session. SDK auto-pagination is forward-only; to go back a page, read `prev_page` from the response and pass it back as the `page` parameter yourself. See [client SDKs](https://platform.claude.com/docs/en/cli-sdks-libraries/overview) for details.
152152
153153<Note>
154154 Some list endpoints use a different cursor scheme. The [Message Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing), the [Models API](https://platform.claude.com/docs/en/api/models/list), and several [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) endpoints take `after_id` and `before_id` query parameters instead of `page`. Their responses return `has_more`, `first_id`, and `last_id` instead of `next_page`. See the reference page for each endpoint for its exact pagination fields.
build-with-claude/claude-in-amazon-bedrock Changed · +1 / -1 lines
from line 325
325325</Tabs>
326326
327327<Tip>
328 You can also create the standard client with `Anthropic` (python, typescript; go: `anthropic.NewClient()`; java: `AnthropicOkHttpClient.builder()`; csharp: `AnthropicClient`; php: `Anthropic\Client`; ruby: `Anthropic::Client`): set `base_url` (python, ruby; typescript: `baseURL`; go: `option.WithBaseURL()`; java: `.baseUrl()`; csharp: `BaseUrl`; php: `baseUrl`) to `https://bedrock-mantle.{region}.api.aws/anthropic` and pass your bearer token as `api_key` (python, ruby; typescript, php: `apiKey`; go: `option.WithAPIKey()`; java: `.apiKey()`; csharp: `ApiKey`). This path supports bearer-token authentication only. SigV4 signing requires `AnthropicBedrockMantle` (csharp: `AnthropicBedrockMantleClient`; go: `bedrock.NewMantleClient`; java: `BedrockMantleBackend`; php: `MantleClient`; ruby: `Anthropic::BedrockMantleClient`).
328 You can also create the standard client with `Anthropic` (go: `anthropic.NewClient()`; java: `AnthropicOkHttpClient.builder()`; csharp: `AnthropicClient`; php: `Anthropic\Client`; ruby: `Anthropic::Client`): set `base_url` (typescript: `baseURL`; go: `option.WithBaseURL()`; java: `.baseUrl()`; csharp: `BaseUrl`; php: `baseUrl`) to `https://bedrock-mantle.{region}.api.aws/anthropic` and pass your bearer token as `api_key` (typescript, php: `apiKey`; go: `option.WithAPIKey()`; java: `.apiKey()`; csharp: `ApiKey`). This path supports bearer-token authentication only. SigV4 signing requires `AnthropicBedrockMantle` (csharp: `AnthropicBedrockMantleClient`; go: `bedrock.NewMantleClient`; java: `BedrockMantleBackend`; php: `MantleClient`; ruby: `Anthropic::BedrockMantleClient`).
329329</Tip>
330330
331331## Supported models
build-with-claude/preserved-thinking Changed · +1 / -1 lines
from line 122
122122
123123#### Output-token cost of `"drop_block"`
124124
125In Anthropic's testing on a multi-turn coding benchmark, dropping thinking blocks once per session increased output tokens by 2.5% at low effort, 3.9% at medium, 4.5% at high, and 20.1% at max. Dropping them on every turn after the first increased output tokens by 4.6% at low effort, 9.7% at medium, 10.3% at high, and 67.1% at max. The exact impact depends on your harness.
125In Anthropic's testing on a multi-turn coding benchmark, dropping thinking blocks once per session increased output tokens by 2.5% at low effort, 3.9% at medium, 4.5% at high, and 20.1% at max. Dropping them on every turn after the first increased output tokens by 4.6% at low effort, 9.7% at medium, 10.3% at high, and 67.1% at max. These figures are estimates with wide error bars, and the impact on your workload depends on your harness.
126126
127127When Claude can no longer read reasoning from earlier turns, it re-creates that reasoning, so requests that drop thinking blocks generate more output tokens and can take longer to respond. A drop on every turn costs more than an occasional drop, and how much more depends on your harness: how often it edits the prefix and how much each turn builds on earlier reasoning.
128128
build-with-claude/prompt-engineering/prompting-claude-opus-5 Changed · +1 / -1 lines
from line 74
7474Delegate to a subagent only for large tasks that are genuinely independent and parallelizable, such as a wide multi-file investigation. Do not delegate work you can finish yourself in a handful of tool calls, and do not use subagents to verify or double-check your own work. If one subagent can complete the task, use one rather than several, and keep spawn counts low.
7575```
7676
77If your harness is Claude Code or the Claude Agent SDK, the deterministic caps are the `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` and `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` environment variables and the SDK's `max_budget_usd` (python; typescript: `maxBudgetUsd`) option. They require Claude Code 2.1.217 or later, so update a pinned SDK before pointing it at Claude Opus 5. Claude Code adds a delegation instruction of its own on Claude Opus 5 only when you use its `claude_code` system prompt preset; with a custom or omitted system prompt, add a delegation instruction such as the example in this section yourself. See [Cap subagent depth, concurrency, and spend](https://code.claude.com/docs/en/agent-sdk/subagents#cap-subagent-depth-concurrency-and-spend) in the Agent SDK docs.
77If your harness is Claude Code or the Claude Agent SDK, the deterministic caps are the `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` and `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` environment variables and the SDK's `max_budget_usd` (typescript: `maxBudgetUsd`) option. They require Claude Code 2.1.217 or later, so update a pinned SDK before pointing it at Claude Opus 5. Claude Code adds a delegation instruction of its own on Claude Opus 5 only when you use its `claude_code` system prompt preset; with a custom or omitted system prompt, add a delegation instruction such as the example in this section yourself. See [Cap subagent depth, concurrency, and spend](https://code.claude.com/docs/en/agent-sdk/subagents#cap-subagent-depth-concurrency-and-spend) in the Agent SDK docs.
7878
7979## Self-correction
8080
build-with-claude/streaming Changed · +1 / -1 lines
from line 138
138138
139139## Get the final message without handling events
140140
141If you don't need to process text as it arrives, the SDK provides a way to use streaming internally while returning the complete `Message` object, identical to what `client.messages.create()` (python, typescript, ruby; go: `client.Messages.New()`; java: `client.messages().create()`; csharp: `client.Messages.Create()`; php: `$client->messages->create()`) returns. This is especially useful for requests with large `max_tokens` values, where the SDK requires streaming to avoid HTTP timeouts.
141If you don't need to process text as it arrives, the SDK provides a way to use streaming internally while returning the complete `Message` object, identical to what `client.messages.create()` (go: `client.Messages.New()`; java: `client.messages().create()`; csharp: `client.Messages.Create()`; php: `$client->messages->create()`) returns. This is especially useful for requests with large `max_tokens` values, where the SDK requires streaming to avoid HTTP timeouts.
142142
143143<CodeGroup exclude="shell:cURL">
144144 ```bash CLI
claude_api_primer Changed · +4 / -0 lines
from line 248
248248* Claude Opus 5.5 (`claude-opus-5-5`, adaptive thinking only, always on)
249249* Claude Sonnet 5.5 (`claude-sonnet-5-5`, adaptive thinking only, on by default; `thinking: {"type": "disabled"}` returns a 400 error, so send `thinking: {"type": "between_tools"}` to turn off up-front thinking)
250250* Claude Haiku 5.5 (`claude-haiku-5-5`, adaptive thinking only, on by default)
251* Claude Fable 5.1 (`claude-fable-5-1`, adaptive thinking only, always on)
252* Claude Mythos 5.1 (`claude-mythos-5-1`, adaptive thinking only, always on)
253* Claude Fable 5 (`claude-fable-5`, adaptive thinking only, always on)
254* Claude Mythos 5 (`claude-mythos-5`, adaptive thinking only, always on)
251255* Claude Opus 5 (claude-opus-5, adaptive thinking only, on by default)
252256* Claude Sonnet 5 (`claude-sonnet-5`, adaptive thinking only, on by default)
253257* Claude Opus 4.8 (claude-opus-4-8, adaptive thinking only)
cli-sdks-libraries/middleware Changed · +1 / -1 lines
from line 30
3030
3131## Registering middleware
3232
33Each middleware is a function that receives the outgoing request and the next handler. Call `call_next(request)` (python; typescript: `next(request)`; csharp: `next(request, cancellationToken)`; go: `next(req)`; java: `nextClient.execute(request, requestOptions)`; php: `$next($request)`; ruby: `call_next.call(request)`) to forward the request to the rest of the chain (or directly to the SDK core if this is the last middleware), and return its response. Anything before that call runs on the way out; anything after runs on the way back.
33Each middleware is a function that receives the outgoing request and the next handler. Call `call_next(request)` (typescript: `next(request)`; csharp: `next(request, cancellationToken)`; go: `next(req)`; java: `nextClient.execute(request, requestOptions)`; php: `$next($request)`; ruby: `call_next.call(request)`) to forward the request to the rest of the chain (or directly to the SDK core if this is the last middleware), and return its response. Anything before that call runs on the way out; anything after runs on the way back.
3434
3535<CodeGroup exclude="shell">
3636 ```python Python
cli-sdks-libraries/sdks/csharp Changed · +1 / -1 lines
from line 449
4494491. Changes to library internals that are technically public but not intended or documented for external use.
4504502. Changes that aren't expected to impact the vast majority of users in practice.
451451
452Backward-compatibility is taken seriously to ensure you can rely on a smooth upgrade experience.
452Backward compatibility is taken seriously to ensure you can rely on a smooth upgrade experience.
453453
454454## Additional resources
455455
cli-sdks-libraries/sdks/java Changed · +2 / -2 lines
from line 432
432432
433433### Tool name conversion
434434
435Tool names are derived from the camel case tool class names (for example, `GetWeather`) and converted to snake case (for example, `get_weather`). Word boundaries begin where the current character is not the first character, is upper-case, and either the preceding character is lower-case, or the following character is lower-case. For example, `MyJSONParser` becomes `my_json_parser` and `ParseJSON` becomes `parse_json`. This conversion can be overridden using the `@JsonTypeName` annotation.
435Tool names are derived from the camel case tool class names (for example, `GetWeather`) and converted to snake case (for example, `get_weather`). Word boundaries begin where the current character is not the first character, is uppercase, and either the preceding character is lowercase, or the following character is lowercase. For example, `MyJSONParser` becomes `my_json_parser` and `ParseJSON` becomes `parse_json`. This conversion can be overridden using the `@JsonTypeName` annotation.
436436
437437### Local tool JSON schema validation
438438
from line 660
660660
661661This results in a timeout of up to 60 minutes, scaled by the `maxTokens` parameter, unless overridden.
662662
663For non-streaming requests, the dynamic timeout scales from a 30 second minimum up to a 10 minute maximum based on `maxTokens`.
663For non-streaming requests, the dynamic timeout scales from a 30-second minimum up to a 10-minute maximum based on `maxTokens`.
664664
665665To set a custom timeout per-request:
666666
manage-claude/admin-api-keys Changed · +2 / -2 lines
from line 64
6464| To call... | Select these scopes |
6565| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
6666| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): list and look up members and invites; read custom roles and their permissions | `read:members` |
67| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): change member roles, remove members, create and withdraw invites | `write:members` |
67| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): change member roles, remove members, create and withdraw invites (to assign the `managed` role on a role change or an invite, also select `write:rbac_groups`) | `write:members` |
6868| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): read groups and their members | `read:rbac_groups` |
69| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): create, rename, and delete groups; add and remove group members; assign groups on invite creation | `write:rbac_groups` |
69| Admin API [user management](https://platform.claude.com/docs/en/manage-claude/user-management): create, rename, and delete groups; add and remove group members; with `write:members`, assign the `managed` role (on an invite or a role change) or assign groups on an invite | `write:rbac_groups` |
7070| [Spend Limits API](https://platform.claude.com/docs/en/manage-claude/spend-limits-api): read members' effective spend limits and increase requests | `read:spend_limits` |
7171| [Spend Limits API](https://platform.claude.com/docs/en/manage-claude/spend-limits-api): set or clear per-user spend limits; approve or deny increase requests | `write:spend_limits` |
7272| [Claude Enterprise Analytics API](https://platform.claude.com/docs/en/manage-claude/analytics-api): engagement, adoption, cost, and usage reports | `read:analytics` |
manage-claude/wif-providers/kubernetes Changed · +1 / -1 lines
from line 4
44description: Authenticate to the Claude API from self-managed Kubernetes clusters using projected service account tokens.
55---
66
7Self-managed Kubernetes clusters (kubeadm, k3s, OpenShift, and on-premises distributions) sign OIDC JSON Web Tokens (JWTs) for every pod through [projected service account tokens](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection). The cluster's API server acts as the OIDC issuer, and each token's `sub` claim follows the form `system:serviceaccount:<namespace>:<service-account>`. You can find your cluster's issuer URL by reading its discovery document:
7Self-managed Kubernetes clusters (kubeadm, k3s, OpenShift, and on-premise distributions) sign OIDC JSON Web Tokens (JWTs) for every pod through [projected service account tokens](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#serviceaccount-token-volume-projection). The cluster's API server acts as the OIDC issuer, and each token's `sub` claim follows the form `system:serviceaccount:<namespace>:<service-account>`. You can find your cluster's issuer URL by reading its discovery document:
88
99```bash cURL
1010kubectl get --raw /.well-known/openid-configuration | jq -r .issuer