One read of Claude Developer Platformapi-20261012T020710Z
32 pages moved out of 760 read.
Pages moved
32
significant first
Pages read
760
in this capture
Captured
02:07 UTC
Corpus hash
d6ae6b63892e
corpus-hash
What this read moved
1-25 of 32, page 1 of 2This capture is too large to show at once. Changes 1-25 of 32 are below, significant first; the rest are on the following screens.
managed-agents/agent-setup Changed · +144 / -28 lines
from line 16
1616
1717## Agent configuration fields
1818
19| Field | Description |
20| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21| `name` | Required. A human-readable name for the agent. |
22| `model` | Required. The Claude [model](https://platform.claude.com/docs/en/models/overview) that powers the agent. Accepts a model ID string or an object, for example `{"id": "claude-opus-5"}`. Claude 4.5 and later models are supported. The object form also accepts `speed`, `effort`, and `inference_geo` fields; see the tips under [Create an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#create-an-agent), [Effort levels](https://platform.claude.com/docs/en/build-with-claude/effort#effort-levels), and [Pin the inference geo](https://platform.claude.com/docs/en/managed-agents/agent-setup#pin-the-inference-geo). |
23| `system` | A [system prompt](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#give-claude-a-role) that defines the agent's behavior and persona. The system prompt is distinct from [user messages](https://platform.claude.com/docs/en/managed-agents/reference#event-types), which should describe the work to be done. |
24| `tools` | The tools available to the agent. Combines [pre-built agent tools](https://platform.claude.com/docs/en/managed-agents/tools), [MCP tools](https://platform.claude.com/docs/en/managed-agents/mcp-connector), and [custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools). |
25| `mcp_servers` | [MCP servers](https://platform.claude.com/docs/en/managed-agents/mcp-connector) that provide standardized third-party capabilities. |
26| `skills` | [Skills](https://platform.claude.com/docs/en/managed-agents/skills) that supply domain-specific context with progressive disclosure. |
27| `multiagent` | Lets the agent hand work to other agents, as subagents or in [dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#dynamic-workflows), and optionally consult an [advisor](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#give-the-session-an-advisor) model. With the `multiagent_20261001` type, dynamic workflows are on unless you disable them. See [Multiagent orchestration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). |
28| `description` | A description of what the agent does. |
29| `metadata` | Arbitrary key-value pairs for your own tracking. |
19| Field | Description |
20| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21| `name` (java, php; csharp, go: `Name`) | Required. A human-readable name for the agent. |
22| `model` (java, php; csharp, go: `Model`) | Required. The Claude [model](https://platform.claude.com/docs/en/models/overview) that powers the agent. Accepts a model ID string or an object, for example `{"id": "claude-opus-5"}`. Claude 4.5 and later models are supported. The object form also accepts `speed`, `effort`, and `inference_geo` fields; see the tips under [Create an agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#create-an-agent), [Effort levels](https://platform.claude.com/docs/en/build-with-claude/effort#effort-levels), and [Pin the inference geo](https://platform.claude.com/docs/en/managed-agents/agent-setup#pin-the-inference-geo). |
23| `system` (java, php; csharp, go: `System`; ruby: `system_`) | A [system prompt](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#give-claude-a-role) that defines the agent's behavior and persona. The system prompt is distinct from [user messages](https://platform.claude.com/docs/en/managed-agents/reference#event-types), which should describe the work to be done. |
24| `tools` (java, php; csharp, go: `Tools`) | The tools available to the agent. Combines [pre-built agent tools](https://platform.claude.com/docs/en/managed-agents/tools), [MCP tools](https://platform.claude.com/docs/en/managed-agents/mcp-connector), and [custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools). |
25| `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) | [MCP servers](https://platform.claude.com/docs/en/managed-agents/mcp-connector) that provide standardized third-party capabilities. |
26| `skills` (java, php; csharp, go: `Skills`) | [Skills](https://platform.claude.com/docs/en/managed-agents/skills) that supply domain-specific context with progressive disclosure. |
27| `multiagent` (java, php; csharp, go: `Multiagent`) | Lets the agent hand work to other agents, as subagents or in [dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#dynamic-workflows), and optionally consult an [advisor](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#give-the-session-an-advisor) model. With the `multiagent_20261001` type, dynamic workflows are on unless you disable them. See [Multiagent orchestration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). |
28| `description` (java, php; csharp, go: `Description`) | A description of what the agent does. |
29| `metadata` (java, php; csharp, go: `Metadata`) | Arbitrary key-value pairs for your own tracking. |
3030
31You can also override `model`, `system`, `tools`, `mcp_servers`, and `skills` for a single session without changing the agent. A `model` override replaces the agent's `model` object in full, so the agent's own `effort` isn't carried over. To run the session at a specific effort level, set `effort` inside the override's `model` object. See [Override agent configuration for a session](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session).
31You can also override `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`), and `skills` (java, php; csharp, go: `Skills`) for a single session without changing the agent. 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. See [Override agent configuration for a session](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session).
3232
3333## Create an agent
3434
from line 212
212212
213213### Pin the inference geo
214214
215Like `speed` and `effort`, `inference_geo` is set through the object form of `model`: pass `model` as an object and set `inference_geo` alongside `id`. The field accepts `"us"` or `"global"`. When it's unset, each model request follows the workspace's default inference geo at the time it's served. See [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) for the workspace-level geo controls and pricing.
215Like `speed` (java, php; csharp, go: `Speed`) and `effort` (java, php; csharp, go: `Effort`), `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) is set through the object form of `model` (java, php; csharp, go: `Model`): pass `model` (java, php; csharp, go: `Model`) as an object and set `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) alongside `id` (java, php; csharp, go: `ID`). The field accepts `"us"` or `"global"`. When it's unset, each model request follows the workspace's default inference geo at the time it's served. See [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) for the workspace-level geo controls and pricing.
216216
217The following example pins an agent to US inference and prints the `inference_geo` value from the agent's `model` object:
217The following example pins an agent to US inference and prints the `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) value from the agent's `model` (java, php; csharp, go: `Model`) object:
218218
219219<CodeGroup defaultLanguage="CLI">
220220 ```bash cURL
from line 346
346346 ```
347347</CodeGroup>
348348
349An `inference_geo` pin is validated against the workspace's [`allowed_inference_geos`](https://platform.claude.com/docs/en/manage-claude/data-residency#workspace-level-restrictions) when the agent is saved, when a session is created from it, and on every turn the session serves. If the workspace allowlist narrows so a pin is no longer allowed, new sessions can't be created from the agent and running sessions refuse further turns; pins are never exempted, because workspaces rely on them for compliance and data residency.
349An `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) pin is validated against the workspace's [`allowed_inference_geos`](https://platform.claude.com/docs/en/manage-claude/data-residency#workspace-level-restrictions) when the agent is saved, when a session is created from it, and on every turn the session serves. If the workspace allowlist narrows so a pin is no longer allowed, new sessions can't be created from the agent and running sessions refuse further turns; pins are never exempted, because workspaces rely on them for compliance and data residency.
350350
351Setting `inference_geo` on a model that doesn't support geographic inference pinning returns a 400 error; see [Model availability](https://platform.claude.com/docs/en/manage-claude/data-residency#model-availability) for the models that do. In a `multiagent` configuration, the agent's pin and the pin of every agent listed in `subagents.predefined_agents` or `workflows.predefined_agents` must all be set to the same value or all be unset; see [Multiagent orchestration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). To change or clear the pin later, update the agent's `model` object; supplying `model` without `inference_geo` clears it, as described under [Update semantics](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-semantics).
351Setting `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) on a model that doesn't support geographic inference pinning returns a 400 error; see [Model availability](https://platform.claude.com/docs/en/manage-claude/data-residency#model-availability) for the models that do. In a `multiagent` (java, php; csharp, go: `Multiagent`) configuration, the agent's pin and the pin of every agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or `workflows` (java, php; csharp, go: `Workflows`) must all be set to the same value or all be unset; see [Multiagent orchestration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). To change or clear the pin later, update the agent's `model` (java, php; csharp, go: `Model`) object; supplying `model` (java, php; csharp, go: `Model`) without `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) clears it, as described under [Update semantics](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-semantics).
352352
353353## Update an agent
354354
355Updating an agent generates a new version when the configuration changes. The `version` field is optional: supply it for optimistic concurrency (a mismatch returns a 409), or omit it to apply the update unconditionally (last write wins). Updates to archived agents are rejected.
355Updating an agent generates a new version when the configuration changes. The `version` (java, php; csharp, go: `Version`) field is optional: supply it for optimistic concurrency (a mismatch returns a 409), or omit it to apply the update unconditionally (last write wins). Updates to archived agents are rejected.
356356
357357With the CLI, edit the agent's file and run `ant apply` again; apply supplies `version` for you.
358358
from line 486
486486
487487### Update semantics
488488
489* **`version`** is optional and must be at least 1 when supplied. When supplied, the request returns a 409 if it doesn't match the agent's current version, even when the fields you send already match the stored values; re-read the agent and retry. When omitted, the update applies unconditionally and the most recent update silently replaces any concurrent one, with no error to either caller. Supplying `version` is the recommended default for interactive callers, and omitting it fits declarative apply loops, such as a CI job that syncs checked-in agent definitions, where the loop owns the agent.
489* **`version` (java, php; csharp, go: `Version`)** is optional and must be at least 1 when supplied. When supplied, the request returns a 409 if it doesn't match the agent's current version, even when the fields you send already match the stored values; re-read the agent and retry. When omitted, the update applies unconditionally and the most recent update silently replaces any concurrent one, with no error to either caller. Supplying `version` (java, php; csharp, go: `Version`) is the recommended default for interactive callers, and omitting it fits declarative apply loops, such as a CI job that syncs checked-in agent definitions, where the loop owns the agent.
490490
491491* **Omitted fields are preserved.** You only need to include the fields you want to change.
492492
493* **Scalar fields** (`model`, `system`, `name`, `description`) are replaced with the new value. `system` and `description` can be cleared by passing `null`. `model` and `name` are mandatory and cannot be cleared. Within a `model` object you supply, `effort` is the sole exception: if the model `id` is unchanged, omitting `effort` leaves the stored effort level unchanged. If you change the model `id`, an omitted `effort` resets to the new model's default. Other `model` fields are replaced along with the object: supplying `model` without `inference_geo` clears the agent's inference geo pin.
493* **Scalar fields** (`model` (java, php; csharp, go: `Model`), `system` (java, php; csharp, go: `System`; ruby: `system_`), `name` (java, php; csharp, go: `Name`), `description` (java, php; csharp, go: `Description`)) are replaced with the new value. `system` (java, php; csharp, go: `System`; ruby: `system_`) and `description` (java, php; csharp, go: `Description`) can be cleared by passing `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `param.Null[string]()`; php: `requestOptions: ['extraBodyParams' => ['system' => null, 'description' => null]]`). `model` (java, php; csharp, go: `Model`) and `name` (java, php; csharp, go: `Name`) are mandatory and cannot be cleared. Within a `model` (java, php; csharp, go: `Model`) object you supply, `effort` (java, php; csharp, go: `Effort`) is the sole exception: if the model `id` (java, php; csharp, go: `ID`) is unchanged, omitting `effort` (java, php; csharp, go: `Effort`) leaves the stored effort level unchanged. If you change the model `id` (java, php; csharp, go: `ID`), an omitted `effort` (java, php; csharp, go: `Effort`) resets to the new model's default. Other `model` (java, php; csharp, go: `Model`) fields are replaced along with the object: supplying `model` (java, php; csharp, go: `Model`) without `inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) clears the agent's inference geo pin.
494494
495* **Array fields** (`tools`, `mcp_servers`, `skills`) are fully replaced by the new array. To clear an array field entirely, pass `null` or an empty array.
495* **Array fields** (`tools` (java, php; csharp, go: `Tools`), `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`), `skills` (java, php; csharp, go: `Skills`)) are fully replaced by the new array. To clear an array field entirely, pass `null` (python: `None`; ruby: `nil`; java: `Optional.empty()`; go: `param.NullSlice[[]anthropic.BetaAgentUpdateParamsToolUnion]()`; php: `requestOptions: ['extraBodyParams' => ['mcp_servers' => null]]`) or an empty array.
496496
497* **`multiagent`** is merged into the stored block level by level when the update keeps the `multiagent_20261001` type. A setting that you omit keeps its stored value, and a `predefined_agents` list that you send replaces the stored list. Any other update that sends `multiagent` replaces the stored block as a whole, and the settings that it omits take their defaults. Pass `"multiagent": null` to clear the whole block. Inside the block, `null` resets a setting to its default, so `"workflows": null` turns dynamic workflows on. See [Turn on dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows).
497* **`multiagent` (java, php; csharp, go: `Multiagent`)** is merged into the stored block level by level when the update keeps the `multiagent_20261001` type. A setting that you omit keeps its stored value, and a `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list that you send replaces the stored list. Any other update that sends `multiagent` (java, php; csharp, go: `Multiagent`) replaces the stored block as a whole, and the settings that it omits take their defaults. Pass `"multiagent": null` (python: `multiagent=None`; typescript: `multiagent: null`; ruby: `multiagent: nil`; go: `Multiagent: param.NullStruct[anthropic.BetaManagedAgentsMultiagentParamsUnion]()`; java: `.multiagent(Optional.empty())`; csharp: `Multiagent = null`; php: `requestOptions: ['extraBodyParams' => ['multiagent' => null]]`) to clear the whole block. Inside the block, `null` resets a setting to its default, so setting `workflows` (java, php; csharp, go: `Workflows`) to `null` turns dynamic workflows on. See [Turn on dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows).
498498
499499* **Metadata** is merged at the key level. Keys you provide are added or updated. Keys you omit are preserved. To delete a specific key, set its value to `null`.
500500
501501* **No-op detection.** If the update produces no change relative to the current version, no new version is created and the existing version is returned.
502502
503* **Other agents' `predefined_agents` lists are not updated.** Agents that list this agent in `subagents.predefined_agents` or `workflows.predefined_agents` keep the version that was pinned when they were created or when an update last sent that list, even if the reference omits `version`. To delegate to the new version, [update the agent that lists it](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#list-the-subagents) so that the list references the new version.
503* **Other agents' `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) lists are not updated.** Agents that list this agent in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or `workflows` (java, php; csharp, go: `Workflows`) keep the version that was pinned when they were created or when an update last sent that list, even if the reference omits `version` (java, php; csharp, go: `Version`). To delegate to the new version, [update the agent that lists it](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#list-the-subagents) so that the list references the new version.
504504
505The following update clears the description, deletes the `team` key from `metadata` (java, php; csharp, go: `Metadata`), and sets `workflows` (java, php; csharp, go: `Workflows`) to `null`, which turns dynamic workflows on:
506
507<CodeGroup exclude="shell:CLI">
508 ```bash cURL
509 cleared_agent=$(curl -fsSL "https://api.anthropic.com/v1/agents/$AGENT_ID" \
510 -H "x-api-key: $ANTHROPIC_API_KEY" \
511 -H "anthropic-version: 2023-06-01" \
512 -H "anthropic-beta: managed-agents-2026-04-01" \
513 -H "content-type: application/json" \
514 -d '{
515 "description": null,
516 "metadata": {"team": null},
517 "multiagent": {"type": "multiagent_20261001", "workflows": null}
518 }')
519
520 echo "Description: $(jq -r '.description' <<< "$cleared_agent")"
521 ```
522
523 ```python Python
524 cleared_agent = client.beta.agents.update(
525 agent.id,
526 description=None,
527 metadata={"team": None},
528 multiagent={"type": "multiagent_20261001", "workflows": None},
529 )
530
531 print(f"Description: {cleared_agent.description}")
532 ```
533
534 ```typescript TypeScript
535 const clearedAgent = await client.beta.agents.update(agent.id, {
536 description: null,
537 metadata: { team: null },
538 multiagent: { type: "multiagent_20261001", workflows: null },
539 });
540
541 console.log(`Description: ${clearedAgent.description}`);
542 ```
543
544 ```csharp C#
545 var clearedAgent = await client.Beta.Agents.Update(agent.ID, new()
546 {
547 Description = null,
548 Metadata = new Dictionary<string, string?> { ["team"] = null },
549 Multiagent = new BetaManagedAgentsMultiagent20261001Params { Workflows = null },
550 });
551
552 Console.WriteLine($"Description: {clearedAgent.Description}");
553 ```
554
555 ```go Go
556 // Metadata is a map[string]string, so send the null for team as a request option.
557 clearedAgent, err := client.Beta.Agents.Update(ctx, agent.ID, anthropic.BetaAgentUpdateParams{
558 Description: param.Null[string](),
559 Multiagent: anthropic.BetaManagedAgentsMultiagentParamsUnion{
560 OfMultiagent20261001: &anthropic.BetaManagedAgentsMultiagent20261001Params{
561 Workflows: param.NullStruct[anthropic.BetaManagedAgentsMultiagentWorkflowsParamsUnion](),
562 },
563 },
564 }, option.WithJSONSet("metadata.team", nil))
565 if err != nil {
566 panic(err)
567 }
568
569 fmt.Printf("Description: %q\n", clearedAgent.Description)
570 ```
571
572 ```java Java
573 var clearedAgent = client.beta().agents().update(
574 agent.id(),
575 AgentUpdateParams.builder()
576 .description(Optional.empty())
577 .metadata(
578 AgentUpdateParams.Metadata.builder()
579 .putAdditionalProperty("team", JsonValue.from(null))
580 .build()
581 )
582 .multiagent(
583 BetaManagedAgentsMultiagent20261001Params.builder()
584 .workflows(Optional.empty())
585 .build()
586 )
587 .build()
588 );
589
590 IO.println("Description: " + clearedAgent.description().orElse(null));
591 ```
592
593 ```php PHP
594 // update() drops null arguments, so pass the nulls in extraBodyParams.
595 $clearedAgent = $client->beta->agents->update(
596 $agent->id,
597 requestOptions: [
598 'extraBodyParams' => [
599 'description' => null,
600 'metadata' => ['team' => null],
601 'multiagent' => ['type' => 'multiagent_20261001', 'workflows' => null],
602 ],
603 ],
604 );
605
606 echo 'Description: ' . json_encode($clearedAgent->description) . "\n";
607 ```
608
609 ```ruby Ruby
610 cleared_agent = client.beta.agents.update(
611 agent.id,
612 description: nil,
613 metadata: {team: nil},
614 multiagent: {type: :multiagent_20261001, workflows: nil}
615 )
616
617 puts "Description: #{cleared_agent.description.inspect}"
618 ```
619</CodeGroup>
620
505621## Agent lifecycle
506622
507623| Operation | Behavior |
from line 694
578694
579695### Archive an agent
580696
581Archiving makes the agent read-only and cannot be undone. Existing sessions continue to run, but new sessions cannot reference the agent. The response sets `archived_at` to the archive timestamp.
697Archiving makes the agent read-only and cannot be undone. Existing sessions continue to run, but new sessions cannot reference the agent. The response sets `archived_at` (java, php: `archivedAt`; csharp, go: `ArchivedAt`) to the archive timestamp.
582698
583699<CodeGroup>
584700 ```bash cURL
managed-agents/budgets Changed · +28 / -27 lines
from line 14
1414
1515## Set a budget at session creation
1616
17Pass the optional `budget` field when you create the session:
17Pass the optional `budget` (java, php; csharp, go: `Budget`) field when you create the session:
1818
1919<CodeGroup>
2020 ```bash cURL
from line 141
141141 ```
142142</CodeGroup>
143143
144The `budget` object has two fields:
144The `budget` (java, php; csharp, go: `Budget`) object has two fields:
145145
146* `type` is always `"limit"`.
147* `max_list_cost` is the cap itself: `amount` is a whole number of US cents written as a string with no leading zeros (`"125"` is $1.25 and `"50"` is 50 cents) and must be greater than zero. Decimal forms such as `"25.00"` are rejected. The amount is a string rather than a number so no float rounding is ever applied to it. `currency` is an uppercase ISO-4217 currency code; `USD` is the only supported currency.
146* `type` (java, php; csharp, go: `Type`) is always `"limit"`.
147* `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`) is the cap itself: `amount` (java, php; csharp, go: `Amount`) is a whole number of US cents written as a string with no leading zeros (`"125"` is $1.25 and `"50"` is 50 cents) and must be greater than zero. Decimal forms such as `"25.00"` are rejected. The amount is a string rather than a number so no float rounding is ever applied to it. `currency` (java, php; csharp, go: `Currency`) is an uppercase ISO-4217 currency code; `USD` is the only supported currency.
148148
149149A budget can only be attached when the session is created. Adding a budget to an existing session that doesn't have one is rejected with a 400 error. A budgeted session's cap can be [changed](https://platform.claude.com/docs/en/managed-agents/budgets#change-the-budget) or [removed](https://platform.claude.com/docs/en/managed-agents/budgets#remove-the-budget) at any time.
150150
from line 158
158158
159159This running dollar total is the session's **list cost**, and it is what the budget compares against. List cost is not your contracted price: if your organization has negotiated discounts, the session reaches its cap when the list-price total does, and your billed spend might be lower than the cap.
160160
161Enforcement uses the exact, unrounded list cost. The `list_cost` figures reported on the session and its events are whole cents, rounded to the nearest cent, so a reported figure can read up to half a cent either side of the exact amount enforcement uses.
161Enforcement uses the exact, unrounded list cost. The `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) figures reported on the session and its events are whole cents, rounded to the nearest cent, so a reported figure can read up to half a cent either side of the exact amount enforcement uses.
162162
163163## When a session reaches its budget
164164
165The cap is enforced between model requests, not mid-request. Before each model request, the platform checks the session's consumed list cost, and once that total reaches the cap every thread pauses before its next request. The request that carried the total past the cap was admitted while the session was still under it and runs to completion, so a paused session's recorded `list_cost` reads at or a fraction past `max_list_cost`: a session capped at `"50"` (50 cents) can pause with a `list_cost` of `"53"`. This is expected, not a billing error, and the overshoot is bounded by one model request per thread. Treat the budget as a bound on new work rather than an exact stopping point, and size the cap with that one-request margin in mind.
165The cap is enforced between model requests, not mid-request. Before each model request, the platform checks the session's consumed list cost, and once that total reaches the cap every thread pauses before its next request. The request that carried the total past the cap was admitted while the session was still under it and runs to completion, so a paused session's recorded `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) reads at or a fraction past `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`): a session capped at `"50"` (50 cents) can pause with a `list_cost` (java, php: `listCost`; csharp, go: `ListCost`) of `"53"`. This is expected, not a billing error, and the overshoot is bounded by one model request per thread. Treat the budget as a bound on new work rather than an exact stopping point, and size the cap with that one-request margin in mind.
166166
167A session that reaches its budget goes idle with a `stop_reason` of `budget_reached`; it is not terminated, and its history and sandbox are preserved like any other idle session's. On the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) you'll see, in order:
167A session that reaches its budget goes idle with a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) of `budget_reached`; it is not terminated, and its history and sandbox are preserved like any other idle session's. On the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) you'll see, in order:
168168
1691. A `session.thread_status_idle` event with a `stop_reason` of `budget_reached` as each thread pauses.
1691. A `session.thread_status_idle` event with a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) of `budget_reached` as each thread pauses.
1701702. A [`session.usage`](https://platform.claude.com/docs/en/managed-agents/budgets#monitor-spend) event with the session's cumulative usage and list cost.
1713. A `session.status_idle` event with a `stop_reason` of `budget_reached`. The usage event always immediately precedes this idle event.
1713. A `session.status_idle` event with a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) of `budget_reached`. The usage event always immediately precedes this idle event.
172172
173173If [workflow runs](https://platform.claude.com/docs/en/managed-agents/workflow-runs#budgets-and-limits) are open, each one that isn't already idle also gets a `workflow_run.status_idle` event.
174174
175A thread whose final request both crosses the cap and completes its turn reports `end_turn` on its own `session.thread_status_idle` event while the session still reports `budget_reached`; treat the session-level `stop_reason` as the signal that the session paused at its budget.
175A thread whose final request both crosses the cap and completes its turn reports `end_turn` on its own `session.thread_status_idle` event while the session still reports `budget_reached`; treat the session-level `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) as the signal that the session paused at its budget.
176176
177177### Events accepted at the cap
178178
from line 197
197197
198198### Change the budget
199199
200Update the session with a new `max_list_cost`. The new value can be higher or lower than the current cap, but it must be strictly greater than the session's consumed list cost; otherwise the update is rejected with a 400 error: `budget.max_list_cost must be greater than the session's consumed list cost`. Because the consumed cost usually sits [a fraction past the old cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) when the session pauses, base the new value on the session's reported `usage.list_cost`, not on the old `max_list_cost`. Set it a cent or more above that figure: the reported value is rounded and can sit a fraction below the exact consumed cost the check uses.
200Update the session with a new `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`). The new value can be higher or lower than the current cap, but it must be strictly greater than the session's consumed list cost; otherwise the update is rejected with a 400 error: `budget.max_list_cost must be greater than the session's consumed list cost`. Because the consumed cost usually sits [a fraction past the old cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) when the session pauses, base the new value on the session's reported `usage.list_cost` (java, php: `usage.listCost`; csharp, go: `Usage.ListCost`), not on the old `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`). Set it a cent or more above that figure: the reported value is rounded and can sit a fraction below the exact consumed cost the check uses.
201201
202202<CodeGroup>
203203 ```bash cURL
from line 307
307307
308308### Remove the budget
309309
310Set `budget` to `null` to remove the cap entirely. The work that the budget paused resumes, and the resulting `session.updated` event carries `budget` set to `null`.
310Pass `"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`) to remove the cap entirely. The work that the budget paused resumes, and the resulting `session.updated` event carries `budget` (java, php; csharp, go: `Budget`) set to `null`.
311311
312312<CodeGroup>
313313 ```bash cURL
from line 360
360360 ```
361361
362362 ```php PHP
363 // update(budget: null) omits the field, so send the explicit null through the raw client.
364 $unbudgetedSession = $client->beta->sessions->raw
365 ->update($session->id, ['budget' => null])
366 ->parse();
363 // update(budget: null) omits the field, so send the explicit null as an extra body parameter.
364 $unbudgetedSession = $client->beta->sessions->update(
365 $session->id,
366 requestOptions: ['extraBodyParams' => ['budget' => null]],
367 );
367368 echo json_encode($unbudgetedSession->budget), "\n"; // null
368369 ```
369370
from line 380
379380
380381## Monitor spend
381382
382The session object carries its `budget` and a `usage` object with the tracked spend: `usage.list_cost` is the session's consumed list cost, and `usage.active_seconds` is the running time its runtime cost is priced on. On a session paused at `budget_reached`, expect `usage.list_cost` to read at or a fraction past `max_list_cost`: the [request that crossed the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) finished before the pause. Session-level `active_seconds` counts overlapping activity from concurrent threads once. Thread retrieval responses carry the same two fields on the thread's own `usage`, priced per thread. Per-thread figures are rounded independently and exclude the session's running-time cost, so they don't sum exactly to the session's `list_cost`; the session figure is the one the budget is enforced against.
383The session object carries its `budget` (java, php; csharp, go: `Budget`) and a `usage` (java, php; csharp, go: `Usage`) object with the tracked spend: `usage.list_cost` (java, php: `usage.listCost`; csharp, go: `Usage.ListCost`) is the session's consumed list cost, and `usage.active_seconds` (java, php: `usage.activeSeconds`; csharp, go: `Usage.ActiveSeconds`) is the running time its runtime cost is priced on. On a session paused at `budget_reached`, expect `usage.list_cost` (java, php: `usage.listCost`; csharp, go: `Usage.ListCost`) to read at or a fraction past `max_list_cost` (java, php: `maxListCost`; csharp, go: `MaxListCost`): the [request that crossed the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget) finished before the pause. Session-level `active_seconds` (java, php: `activeSeconds`; csharp, go: `ActiveSeconds`) counts overlapping activity from concurrent threads once. Thread retrieval responses carry the same two fields on the thread's own `usage` (java, php; csharp, go: `Usage`), priced per thread. Per-thread figures are rounded independently and exclude the session's running-time cost, so they don't sum exactly to the session's `list_cost` (java, php: `listCost`; csharp, go: `ListCost`); the session figure is the one the budget is enforced against.
383384
384The `session.usage` event is a snapshot of the session's cumulative usage and tracked list cost. It carries the session's token totals, `list_cost`, `active_seconds`, `server_tool_use` request counts (`web_search_requests`, priced into list cost per request, and `web_fetch_requests`, which reads `0` because web fetch requests carry no per-request charge and aren't metered), and an echo of the session's `budget`, or `null` when the session has none. It appears in the events list and the session stream. The session emits one immediately before it goes idle, whatever the stop reason, so a session that reaches its budget always emits one immediately before the budget-reached idle event.
385The `session.usage` event is a snapshot of the session's cumulative usage and tracked list cost. It carries the session's token totals, `list_cost` (java, php: `listCost`; csharp, go: `ListCost`), `active_seconds` (java, php: `activeSeconds`; csharp, go: `ActiveSeconds`), `server_tool_use` (java, php: `serverToolUse`; csharp, go: `ServerToolUse`) request counts (`web_search_requests` (java, php: `webSearchRequests`; csharp, go: `WebSearchRequests`), priced into list cost per request, and `web_fetch_requests` (java, php: `webFetchRequests`; csharp, go: `WebFetchRequests`), which reads `0` because web fetch requests carry no per-request charge and aren't metered), and an echo of the session's `budget` (java, php; csharp, go: `Budget`), or `null` when the session has none. It appears in the events list and the session stream. The session emits one immediately before it goes idle, whatever the stop reason, so a session that reaches its budget always emits one immediately before the budget-reached idle event.
385386
386387To read usage from the stream and the session object, see [Track usage](https://platform.claude.com/docs/en/managed-agents/session-observability#track-usage).
387388
from line 405
404405}
405406```
406407
407The cap is copied onto each session the deployment starts, so it bounds each run separately rather than the deployment's cumulative spend. Changing the deployment's budget applies to sessions the deployment starts afterward, not to sessions already running. Unlike a session, a deployment's budget can be cleared with `null` and set again later. See [Set a budget on each run](https://platform.claude.com/docs/en/managed-agents/scheduled-deployments#set-a-budget-on-each-run).
408The cap is copied onto each session the deployment starts, so it bounds each run separately rather than the deployment's cumulative spend. Changing the deployment's budget applies to sessions the deployment starts afterward, not to sessions already running. Unlike a session, a deployment's budget can be cleared with `"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`) and set again later. See [Set a budget on each run](https://platform.claude.com/docs/en/managed-agents/scheduled-deployments#set-a-budget-on-each-run).
408409
409410## Models without a list price
410411
411A budget can only track consumption the platform can price. Creating a budgeted session whose agent, or any agent listed in `subagents.predefined_agents` or `workflows.predefined_agents`, or the advisor set in its [multiagent configuration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), uses a model with no public list price is rejected with a 400 error stating that no list price is available for the model.
412A budget can only track consumption the platform can price. Creating a budgeted session whose agent, or any agent listed in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or `workflows` (java, php; csharp, go: `Workflows`), or the advisor set in its [multiagent configuration](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), uses a model with no public list price is rejected with a 400 error stating that no list price is available for the model.
412413
413If a budgeted session's usage comes to include a model with no list price, the budget can no longer measure the session's spend: the session can pause with a `stop_reason` of `budget_reached`, and changing the budget is rejected. Remove the budget to resume the session.
414If a budgeted session's usage comes to include a model with no list price, the budget can no longer measure the session's spend: the session can pause with a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) of `budget_reached`, and changing the budget is rejected. Remove the budget to resume the session.
414415
415416## Error reference
416417
from line 422
421422| A work-starting event (for example, `user.message`) is sent while the session is at or over its budget; the error names the [accepted settle events](https://platform.claude.com/docs/en/managed-agents/budgets#events-accepted-at-the-cap) | 400 |
422423| The budget is set to a value at or below the session's consumed list cost | 400 |
423424| A budget is added to a session created without one, or re-added after removal | 400 |
424| `amount` is not a whole number of cents (for example, `"25.00"`), is zero or negative, or `currency` is not `USD` | 400 |
425| `amount` (java, php; csharp, go: `Amount`) is not a whole number of cents (for example, `"25.00"`), is zero or negative, or `currency` (java, php; csharp, go: `Currency`) is not `USD` | 400 |
425426| A budgeted create references a model with [no public list price](https://platform.claude.com/docs/en/managed-agents/budgets#models-without-a-list-price) | 400 |
426427
427428<Note>
managed-agents/define-outcomes Changed · +4 / -4 lines
from line 531
531531</CodeGroup>
532532
533533<Note>
534 You can also define the outcome in the create request itself: pass a single `user.define_outcome` event in [`initial_events`](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events) to create the session and start work toward the outcome in one call.
534 You can also define the outcome in the create request itself: pass a single `user.define_outcome` event in [`initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`)](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events) to create the session and start work toward the outcome in one call.
535535</Note>
536536
537537## Outcome events
from line 541
541541* `agent.*` events (such as messages and tool use) show progress toward the outcome.
542542* `span.outcome_evaluation_*` events are only emitted for outcome-oriented sessions and show the number of iteration loops and the grader's feedback process.
543543* You can also send `user.message` [events](https://platform.claude.com/docs/en/managed-agents/reference#event-types) to an outcome-oriented session to direct the agent's work as it progresses, but it isn't required: the agent works toward the outcome on its own, iterating until it succeeds or runs out of iterations.
544* A `user.interrupt` event pauses work on the current outcome and marks the `span.outcome_evaluation_end.result` as `interrupted`, allowing you to kick off a new outcome.
544* A `user.interrupt` event pauses work on the current outcome and marks the `result` (java, php; csharp, go: `Result`) of the `span.outcome_evaluation_end` event as `interrupted`, allowing you to kick off a new outcome.
545545* After the final outcome evaluation, the session can be continued as a conversational session, or a new outcome can be started. The session retains history of the prior outcome.
546546
547547### Define outcome user event
from line 550
550550 Only one outcome is supported at a time, but you may chain outcomes in sequence. To do this, send a new `user.define_outcome` event after the terminal `span.outcome_evaluation_end` event of the previous outcome.
551551</Note>
552552
553This is the event you send to initiate an outcome. It is echoed back on receipt, including a `processed_at` timestamp and `outcome_id`.
553This is the event you send to initiate an outcome. It is echoed back on receipt, including a `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) timestamp and `outcome_id` (java: `outcomeId`; php: `outcomeID`; csharp, go: `OutcomeID`).
554554
555555```json
556556{
from line 705
705705
706706## Retrieve deliverables
707707
708The agent writes output files to `/mnt/session/outputs/` inside the sandbox. To retrieve them, list files through the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) with the session ID as the `scope_id`, then download them by ID. Filtering by `scope_id` requires the `managed-agents-2026-04-01` beta header on the list request, so the SDK and CLI examples make that call through the `beta` namespace and pass the header explicitly. Files appear in the list shortly after the agent finishes writing them, sometimes a few seconds after the session goes idle. If a file you expect is not listed yet, list again after a short delay; once it appears in the list, its upload has finished.
708The agent writes output files to `/mnt/session/outputs/` inside the sandbox. To retrieve them, list files through the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) with the session ID as the `scope_id` (java: `scopeId`; php: `scopeID`; csharp, go: `ScopeID`), then download them by ID. Filtering by `scope_id` (java: `scopeId`; php: `scopeID`; csharp, go: `ScopeID`) requires the `managed-agents-2026-04-01` beta header on the list request, so the SDK and CLI examples make that call through the `beta` namespace and pass the header explicitly. Files appear in the list shortly after the agent finishes writing them, sometimes a few seconds after the session goes idle. If a file you expect is not listed yet, list again after a short delay; once it appears in the list, its upload has finished.
709709
710710<CodeGroup>
711711 ```bash cURL
managed-agents/dreams Changed · +23 / -23 lines
from line 25
2525* a pre-existing **memory store:** the store Claude verifies, deduplicates, and reorganizes, and
2626* 1 to 100 **sessions:** past transcripts Claude mines for patterns and insights to fold into the output.
2727
28The dream produces another **output memory store**, separate from the input. The output store ID appears in the dream's `outputs[]` shortly after the dream starts `running`, once the workflow has cloned the input store; a `running` dream can briefly report an empty `outputs[]`.
28The dream produces another **output memory store**, separate from the input. The output store ID appears in the dream's `outputs` (java, php; csharp, go: `Outputs`) array shortly after the dream starts `running`, once the workflow has cloned the input store; a `running` dream can briefly report an empty `outputs` (java, php; csharp, go: `Outputs`) array.
2929
3030## Create a dream
3131
from line 160
160160 ```
161161</CodeGroup>
162162
163Dreaming inputs include the pre-existing memory store and an array of sessions. The selected model runs the dreaming pipeline. During the research preview, `claude-opus-5-5`, `claude-fable-5-1`, `claude-opus-5`, `claude-fable-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-5-5`, `claude-sonnet-5`, and `claude-sonnet-4-6` are supported. You can optionally pass `instructions` to steer the dreaming process. See [Steer with instructions](https://platform.claude.com/docs/en/managed-agents/dreams#steer-with-instructions).
163Dreaming inputs include the pre-existing memory store and an array of sessions. The selected model runs the dreaming pipeline. During the research preview, `claude-opus-5-5`, `claude-fable-5-1`, `claude-opus-5`, `claude-fable-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-5-5`, `claude-sonnet-5`, and `claude-sonnet-4-6` are supported. You can optionally pass `instructions` (java, php; csharp, go: `Instructions`) to steer the dreaming process. See [Steer with instructions](https://platform.claude.com/docs/en/managed-agents/dreams#steer-with-instructions).
164164
165165The response is the full `dream` resource with `status: "pending"`:
166166
from line 196
196196
197197### Steer with instructions
198198
199The optional `instructions` field steers what the dreaming pipeline synthesizes. It is applied throughout the pipeline: what to read closely, what to merge or drop, and how to structure the output store.
199The optional `instructions` (java, php; csharp, go: `Instructions`) field steers what the dreaming pipeline synthesizes. It is applied throughout the pipeline: what to read closely, what to merge or drop, and how to structure the output store.
200200
201Use `instructions` for high-level synthesis guidance such as focus areas ("focus on coding-style preferences"), content to preserve unchanged, or output conventions you want applied across the store. The pipeline is a synthesis pass over the inputs, not an editor applied to the text of the store, so imperative directives that target specific lines ("change sentence X to Y", "fix the count in section Z") generally produce no change. To make targeted edits to individual memories, use the [Memory Stores API](https://platform.claude.com/docs/en/managed-agents/memory#view-and-edit-memories) on the output store directly.
201Use `instructions` (java, php; csharp, go: `Instructions`) for high-level synthesis guidance such as focus areas ("focus on coding-style preferences"), content to preserve unchanged, or output conventions you want applied across the store. The pipeline is a synthesis pass over the inputs, not an editor applied to the text of the store, so imperative directives that target specific lines ("change sentence X to Y", "fix the count in section Z") generally produce no change. To make targeted edits to individual memories, use the [Memory Stores API](https://platform.claude.com/docs/en/managed-agents/memory#view-and-edit-memories) on the output store directly.
202202
203203## Track progress
204204
from line 285
285285
286286### Lifecycle
287287
288| `status` | Meaning |
289| ----------- | ----------------------------------------------------------------------------------------------------------------- |
290| `pending` | Dream successfully created and queued. |
291| `running` | The pipeline is processing. `usage` updates as work progresses. |
292| `completed` | Finished successfully. The `outputs[]` value is the new memory store. |
293| `failed` | Dreaming run ended with an error. The output memory store is left as-is with whatever was written before failure. |
294| `canceled` | Dreaming run canceled. The output memory store is left as-is. |
288| `status` (java, php; csharp, go: `Status`) | Meaning |
289| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
290| `pending` | Dream successfully created and queued. |
291| `running` | The pipeline is processing. `usage` (java, php; csharp, go: `Usage`) updates as work progresses. |
292| `completed` | Finished successfully. The `outputs` (java, php; csharp, go: `Outputs`) value is the new memory store. |
293| `failed` | Dreaming run ended with an error. The output memory store is left as-is with whatever was written before failure. |
294| `canceled` | Dreaming run canceled. The output memory store is left as-is. |
295295
296296### Watch the pipeline run
297297
298Once a dream is `running`, its `session_id` field points at the underlying [session](https://platform.claude.com/docs/en/managed-agents/sessions) running the pipeline. You can stream that session's [events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) to observe what the dream is reading and writing in real time. The session is archived (not deleted) when the dream reaches a terminal state, so the transcript remains available afterward.
298Once a dream is `running`, its `session_id` (java: `sessionId`; php: `sessionID`; csharp, go: `SessionID`) field points at the underlying [session](https://platform.claude.com/docs/en/managed-agents/sessions) running the pipeline. You can stream that session's [events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) to observe what the dream is reading and writing in real time. The session is archived (not deleted) when the dream reaches a terminal state, so the transcript remains available afterward.
299299
300300## Use the output
301301
302When `status` reaches `completed`, the `memory_store` entry in `outputs[]` references a fully populated store. It's an ordinary memory store in your workspace. Review it with the [Memory Stores API](https://platform.claude.com/docs/en/managed-agents/memory#view-and-edit-memories) or in the Console, then either:
302When `status` (java, php; csharp, go: `Status`) reaches `completed`, the `memory_store` entry in `outputs` (java, php; csharp, go: `Outputs`) references a fully populated store. It's an ordinary memory store in your workspace. Review it with the [Memory Stores API](https://platform.claude.com/docs/en/managed-agents/memory#view-and-edit-memories) or in the Console, then either:
303303
304304* **Leverage it:** attach it to future sessions as a `memory_store` resource in place of (or alongside) the input memory store, or
305305* **Discard it:** [delete the memory store](https://platform.claude.com/docs/en/api/beta/memory_stores/delete) or [archive the memory store](https://platform.claude.com/docs/en/api/beta/memory_stores/archive).
from line 469
469469Cancel moves a `pending` or `running` dream to `canceled` immediately. Canceling an already-`canceled` dream is an idempotent no-op; canceling a `completed` or `failed` dream returns 400.
470470
471471<Note>
472 After cancellation, the dream's `usage` fields might continue to update for a few seconds while in-flight work winds down. Poll the dream until `usage` stabilizes if you need the final count.
472 After cancellation, the dream's `usage` (java, php; csharp, go: `Usage`) fields might continue to update for a few seconds while in-flight work winds down. Poll the dream until `usage` (java, php; csharp, go: `Usage`) stabilizes if you need the final count.
473473</Note>
474474
475475<CodeGroup>
from line 518
518518
519519## Archive a dream
520520
521Archive sets `archived_at` on a dream that has reached a terminal state (`completed`, `failed`, or `canceled`); `status` is left unchanged. Archived dreams are excluded from default list responses but remain readable by ID. Archiving an already-archived dream is an idempotent no-op. Archiving a `pending` or `running` dream returns 400; cancel it first. There is no unarchive.
521Archive sets `archived_at` (java, php: `archivedAt`; csharp, go: `ArchivedAt`) on a dream that has reached a terminal state (`completed`, `failed`, or `canceled`); `status` (java, php; csharp, go: `Status`) is left unchanged. Archived dreams are excluded from default list responses but remain readable by ID. Archiving an already-archived dream is an idempotent no-op. Archiving a `pending` or `running` dream returns 400; cancel it first. There is no unarchive.
522522
523523<CodeGroup>
524524 ```bash cURL
from line 568
568568
569569## List dreams
570570
571Returns all non-archived dreams in the workspace, newest first. Use `limit` (default 20, max 100) and the `page` cursor to paginate. Pass `include_archived=true` to include archived dreams.
571Returns all non-archived dreams in the workspace, newest first. Use `limit` (java, php; csharp, go: `Limit`) (default 20, max 100) and the `page` (java, php; csharp, go: `Page`) cursor to paginate. Set `include_archived` (java, php: `includeArchived`; csharp, go: `IncludeArchived`) to `true` to include archived dreams.
572572
573573<CodeGroup>
574574 ```bash cURL
from line 650
650650
651651## Billing
652652
653Dreams are billed at standard API token rates for the model you select; `usage` on the resource reports the exact totals. Cost scales roughly linearly with the number and length of input sessions. Start with a small batch of sessions and scale up once you're satisfied with the curation quality.
653Dreams are billed at standard API token rates for the model you select; `usage` (java, php; csharp, go: `Usage`) on the resource reports the exact totals. Cost scales roughly linearly with the number and length of input sessions. Start with a small batch of sessions and scale up once you're satisfied with the curation quality.
654654
655655## Limits
656656
657| Limit | Value |
658| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
659| Sessions per dream | 100 |
660| `instructions` length | 4,096 characters |
661| Supported models | `claude-opus-5-5`, `claude-fable-5-1`, `claude-opus-5`, `claude-fable-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-5-5`, `claude-sonnet-5`, `claude-sonnet-4-6` |
657| Limit | Value |
658| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
659| Sessions per dream | 100 |
660| `instructions` (java, php; csharp, go: `Instructions`) length | 4,096 characters |
661| Supported models | `claude-opus-5-5`, `claude-fable-5-1`, `claude-opus-5`, `claude-fable-5`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-sonnet-5-5`, `claude-sonnet-5`, `claude-sonnet-4-6` |
662662
663663Default rate limits apply to dream creation while this feature is in research preview. [Contact support](https://support.claude.com) if you need higher limits.
664664
managed-agents/environments Changed · +18 / -18 lines
from line 150
150150 ```
151151</CodeGroup>
152152
153Use a unique, descriptive `name` so you can tell environments apart. This example uses `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking) with package managers allowed, so the sandbox can reach the package registries and code hosts. To let it reach other hosts, add them to `allowed_hosts`.
153Use a unique, descriptive `name` (java, php; csharp, go: `Name`) so you can tell environments apart. This example uses `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking) with package managers allowed, so the sandbox can reach the package registries and code hosts. To let it reach other hosts, add them to `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`).
154154
155155## Use the environment in a session
156156
from line 235
235235
236236### Packages
237237
238The `packages` field pre-installs packages into the sandbox before the agent starts. Packages are installed by their respective package managers and cached across sessions that share the same environment. When multiple package managers are specified, they run in alphabetical order (apt, cargo, gem, go, npm, pip). You can optionally pin specific versions. Unpinned packages install the latest version. If the environment uses `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), also set `networking.allow_package_managers` to `true`; otherwise the request is rejected with a 400 error.
238The `packages` (java, php; csharp, go: `Packages`) field pre-installs packages into the sandbox before the agent starts. Packages are installed by their respective package managers and cached across sessions that share the same environment. When multiple package managers are specified, they run in alphabetical order (apt, cargo, gem, go, npm, pip). You can optionally pin specific versions. Unpinned packages install the latest version. If the environment uses `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), also set `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) in `networking` (java, php; csharp, go: `Networking`) to `true`; otherwise the request is rejected with a 400 error.
239239
240240<CodeGroup defaultLanguage="CLI">
241241 ```bash cURL
from line 416
416416
417417### Networking
418418
419The `networking` field controls the sandbox's outbound network access.
419The `networking` (java, php; csharp, go: `Networking`) field controls the sandbox's outbound network access.
420420
421With `limited` networking, `allowed_hosts` also applies to the `web_search` and `web_fetch` tools, which run on Anthropic's servers. A `web_fetch` call for a URL on a host that `allowed_hosts` does not match returns an error result to the agent. `web_search` omits results from hosts that `allowed_hosts` does not match. `allow_package_managers` and `allow_mcp_servers` add no hosts for these tools. When `allowed_hosts` lists no hosts, no `web_fetch` or `web_search` call returns a page or a search result. A host that you add to `allowed_hosts` for these tools is also open to the sandbox. `unrestricted` networking and self-hosted environments do not limit these tools. To restrict them further, set `allowed_domains` or `blocked_domains` on the tool's entry in the agent toolset. See [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions).
421With `limited` networking, `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) also applies to the `web_search` and `web_fetch` tools, which run on Anthropic's servers. A `web_fetch` call for a URL on a host that `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) does not match returns an error result to the agent. `web_search` omits results from hosts that `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) does not match. `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) and `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) add no hosts for these tools. When `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) lists no hosts, no `web_fetch` or `web_search` call returns a page or a search result. A host that you add to `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) for these tools is also open to the sandbox. `unrestricted` networking and self-hosted environments do not limit these tools. To restrict them further, set `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) or `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) on the tool's entry in the agent toolset. See [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions).
422422
423| Mode | Description |
424| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
425| `limited` | Restricts sandbox network access to the hosts in `allowed_hosts`. Set `allow_package_managers` and `allow_mcp_servers` to `true` to allow additional access. Use this mode unless the agent must reach sites you cannot list in advance. |
426| `unrestricted` | Full outbound network access, except for a general safety blocklist. Before you use it, read [Risks of unrestricted networking](https://platform.claude.com/docs/en/managed-agents/environments#risks-of-unrestricted-networking). |
423| Mode | Description |
424| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
425| `limited` | Restricts sandbox network access to the hosts in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Set `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) and `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) to `true` to allow additional access. Use this mode unless the agent must reach sites you cannot list in advance. |
426| `unrestricted` | Full outbound network access, except for a general safety blocklist. Before you use it, read [Risks of unrestricted networking](https://platform.claude.com/docs/en/managed-agents/environments#risks-of-unrestricted-networking). |
427427
428428<Note>
429 Set `networking` explicitly in API requests; a create request that omits it gets `unrestricted`. The Claude Console's form for creating an environment starts with **Limited** selected and nothing else allowed.
429 Set `networking` (java, php; csharp, go: `Networking`) explicitly in API requests; a create request that omits it gets `unrestricted`. The Claude Console's form for creating an environment starts with **Limited** selected and nothing else allowed.
430430</Note>
431431
432432The following example creates an environment with `limited` networking:
from line 590
590590</CodeGroup>
591591
592592<Info>
593 Use `limited` networking with an explicit `allowed_hosts` list. Follow the principle of least privilege by granting only the minimum network access your agent requires, and regularly audit your allowed domains.
593 Use `limited` networking with an explicit `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) list. Follow the principle of least privilege by granting only the minimum network access your agent requires, and regularly audit your allowed domains.
594594</Info>
595595
596596With `limited` networking and no other fields set, no hosts are allowed. Files, memory stores, and GitHub repositories that you attach to the session stay available. When a request from the sandbox on port 80 or 443 is refused because its host is not allowed, the response is a 403 that names the blocked host.
from line 597
597597
598598When using `limited` networking:
599599
600* `allowed_hosts` specifies domains the sandbox can reach. Specify bare hostnames or wildcard patterns (such as `*.example.com`). Do not include a URL scheme, port, or path. A bare hostname matches that exact host: `example.com` does not match `www.example.com`. `*.example.com` matches every subdomain of `example.com`, but not `example.com` itself.
601* `allow_mcp_servers` allows outbound access to MCP server endpoints configured on the agent, beyond those listed in the `allowed_hosts` array. Defaults to `false`. While it is `false`, session creation fails with a 400 error if the agent declares an MCP server whose host is not in `allowed_hosts`. The same applies to [an agent it can delegate to](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). To fix it, add the host to `allowed_hosts` or set `allow_mcp_servers` to `true`.
602* `allow_package_managers` allows outbound access to a set of public package registries and code hosts beyond those listed in the `allowed_hosts` array. See [Package manager hosts](https://platform.claude.com/docs/en/managed-agents/environments#package-manager-hosts) for the list. Defaults to `false`. Set it to `true` whenever the environment specifies `packages`; otherwise the request is rejected with a 400 error, even if the registry hosts are listed in `allowed_hosts`.
600* `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) specifies domains the sandbox can reach. Specify bare hostnames or wildcard patterns (such as `*.example.com`). Do not include a URL scheme, port, or path. A bare hostname matches that exact host: `example.com` does not match `www.example.com`. `*.example.com` matches every subdomain of `example.com`, but not `example.com` itself.
601* `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) allows outbound access to MCP server endpoints configured on the agent, beyond those listed in the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) array. Defaults to `false`. While it is `false`, session creation fails with a 400 error if the agent declares an MCP server whose host is not in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). The same applies to [an agent it can delegate to](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration). To fix it, add the host to `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) or set `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) to `true`.
602* `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) allows outbound access to a set of public package registries and code hosts beyond those listed in the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) array. See [Package manager hosts](https://platform.claude.com/docs/en/managed-agents/environments#package-manager-hosts) for the list. Defaults to `false`. Set it to `true` whenever the environment specifies `packages` (java, php; csharp, go: `Packages`); otherwise the request is rejected with a 400 error, even if the registry hosts are listed in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`).
603603
604604#### Package manager hosts
605605
606When `allow_package_managers` is `true`, the sandbox can reach the following hosts in addition to those in `allowed_hosts`. Anthropic maintains this list and can change it.
606When `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) is `true`, the sandbox can reach the following hosts in addition to those in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Anthropic maintains this list and can change it.
607607
608608| Ecosystem | Hosts |
609609| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
from line 619
619619| Containers | `registry-1.docker.io`, `auth.docker.io`, `production.cloudflare.docker.com`, `download.docker.com`, `ghcr.io` |
620620
621621<Warning>
622 Network access is granted per host, not per operation. The sandbox can send any request to an allowed host, including uploads such as `git push` and package publishing, with any credential the command supplies. If the agent processes untrusted input (repository files, fetched web content, or third-party tool output), a successful prompt injection could use an allowed host to copy files out of the sandbox. To reduce this risk, set the `bash` tool's [permission policy](https://platform.claude.com/docs/en/managed-agents/permission-policies) to `always_ask` or `auto`. If the environment does not specify `packages`, you can instead leave `allow_package_managers` set to `false` and list only the hosts your agent needs in `allowed_hosts`.
622 Network access is granted per host, not per operation. The sandbox can send any request to an allowed host, including uploads such as `git push` and package publishing, with any credential the command supplies. If the agent processes untrusted input (repository files, fetched web content, or third-party tool output), a successful prompt injection could use an allowed host to copy files out of the sandbox. To reduce this risk, set the `bash` tool's [permission policy](https://platform.claude.com/docs/en/managed-agents/permission-policies) to `always_ask` or `auto`. If the environment does not specify `packages` (java, php; csharp, go: `Packages`), you can instead leave `allow_package_managers` (java, php: `allowPackageManagers`; csharp, go: `AllowPackageManagers`) set to `false` and list only the hosts your agent needs in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`).
623623</Warning>
624624
625625#### Risks of unrestricted networking
from line 644
644644}
645645```
646646
647An agent that only uses the `web_search` and `web_fetch` tools does not need `unrestricted` networking if you can list the sites it needs. With `limited` networking, `allowed_hosts` also applies to those tools (see [Networking](https://platform.claude.com/docs/en/managed-agents/environments#networking)), so list those sites in `allowed_hosts`. Listing them in `web_search`'s `allowed_domains` too makes it search those sites. A host that you add to `allowed_hosts` is also open to the sandbox. To restrict the tools further, see [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions).
647An agent that only uses the `web_search` and `web_fetch` tools does not need `unrestricted` networking if you can list the sites it needs. With `limited` networking, `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) also applies to those tools (see [Networking](https://platform.claude.com/docs/en/managed-agents/environments#networking)), so list those sites in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Listing them in `web_search`'s `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) too makes it search those sites. A host that you add to `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) is also open to the sandbox. To restrict the tools further, see [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions).
648648
649649Use `unrestricted` only when the agent must reach sites you cannot list in advance. In that case, keep secrets and sensitive files out of the sandbox, and give the agent only the credentials the task needs. Consider setting the `bash` tool's permission policy to `always_ask` or `auto`, and [watch the session's events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming).
650650
managed-agents/events-and-streaming Changed · +7 / -7 lines
from line 728
728728 ```
729729</CodeGroup>
730730
731Every event in the session's history includes a `processed_at` timestamp, set when the event finishes processing. On events you send, `processed_at` is null while the event is still queued behind earlier events. The exceptions are `user.define_outcome`, `user.custom_tool_result`, and `user.tool_result`, which are processed on receipt and echoed back with `processed_at` already populated.
731Every event in the session's history includes a `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) timestamp, set when the event finishes processing. On events you send, `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) is null while the event is still queued behind earlier events. The exceptions are `user.define_outcome`, `user.custom_tool_result`, and `user.tool_result`, which are processed on receipt and echoed back with `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) already populated.
732732
733733## Respond when the session goes idle
734734
from line 755
755755
756756### Return a custom tool result
757757
758The `agent.custom_tool_use` event contains the tool name and input. Run the tool in your system. Then send a `user.custom_tool_result` event, passing the event ID in the `custom_tool_use_id` parameter along with the result content.
758The `agent.custom_tool_use` event contains the tool name and input. Run the tool in your system. Then send a `user.custom_tool_result` event, passing the event ID in the `custom_tool_use_id` (java: `customToolUseId`; php: `customToolUseID`; csharp, go: `CustomToolUseID`) parameter along with the result content.
759759
760760You can send the result as soon as the `agent.custom_tool_use` event arrives, without waiting for `session.status_idle`. The session still emits `session.status_idle` with a `requires_action` stop reason for the call, and your client can ignore it. A second result for the same call is accepted and has no effect.
761761
from line 1021
10211021
10221022### Confirm a tool call
10231023
1024Send a `user.tool_confirmation` event, passing the event ID in the `tool_use_id` parameter. Set `result` to `"allow"` or `"deny"`. See [Respond to confirmation requests](https://platform.claude.com/docs/en/managed-agents/permission-policies#respond-to-confirmation-requests) for which calls wait for a confirmation and how to explain a denial.
1024Send a `user.tool_confirmation` event, passing the event ID in the `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) parameter. Set `result` (java, php; csharp, go: `Result`) to `"allow"` or `"deny"`. See [Respond to confirmation requests](https://platform.claude.com/docs/en/managed-agents/permission-policies#respond-to-confirmation-requests) for which calls wait for a confirmation and how to explain a denial.
10251025
10261026The following example approves every pending call:
10271027
from line 1251
12511251 ```
12521252</CodeGroup>
12531253
1254The previous example approves each call after the session goes idle. If the agent has [workflow runs](https://platform.claude.com/docs/en/managed-agents/workflow-runs) open, a tool call can wait for your confirmation while the session stays `running`. Don't wait for the idle event: when an `agent.tool_use` or `agent.mcp_tool_use` event arrives whose [`evaluated_permission`](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated) is `ask`, answer it. The sample in [Follow a run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#follow-a-run) answers custom tool calls this way, and its introduction says how to add confirmations.
1254The previous example approves each call after the session goes idle. If the agent has [workflow runs](https://platform.claude.com/docs/en/managed-agents/workflow-runs) open, a tool call can wait for your confirmation while the session stays `running`. Don't wait for the idle event: when an `agent.tool_use` or `agent.mcp_tool_use` event arrives whose [`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated) is `ask`, answer it. The sample in [Follow a run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#follow-a-run) answers custom tool calls this way, and its introduction says how to add confirmations.
12551255
12561256## Resume an idle session
12571257
from line 1615
16151615
16161616The call returns as soon as the events are queued. The interrupt then takes effect in this order:
16171617
16181. The agent applies the interrupt. Until then, the interrupt's `processed_at` stays null and the session stays `running`. A model response in progress stops immediately, but the interrupt can take longer to apply while tool calls are running.
16181. The agent applies the interrupt. Until then, the interrupt's `processed_at` (java, php: `processedAt`; csharp, go: `ProcessedAt`) stays null and the session stays `running`. A model response in progress stops immediately, but the interrupt can take longer to apply while tool calls are running.
161916192. The `user.interrupt` event appears on the stream, and the interrupted turn ends with a `session.status_idle` event.
162016203. The agent starts its next turn with the `user.message` you sent after the interrupt.
16211621
from line 1693
16931693 ```
16941694</CodeGroup>
16951695
1696Pass a `types` filter to return only specific event types:
1696Pass a `types` (java, php; csharp, go: `Types`) filter to return only specific event types:
16971697
16981698<CodeGroup>
16991699 ```bash cURL
from line 1785
17851785
17861786On a [supported model](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#supported-models), send a `system.message` event to give the agent privileged system-level context. The context applies to the accompanying turn and all subsequent turns. Use it when the agent needs updated system-level guidance mid-session, for example a different persona, revised constraints, or context fetched at runtime.
17871787
1788The event's `content` accepts 1–1000 text items. The content is appended to the session's system context as a `role: "system"` turn. It doesn't replace the top-level system prompt, which the `system` field on the agent definition sets.
1788The event's `content` (java, php; csharp, go: `Content`) accepts 1–1000 text items. The content is appended to the session's system context as a `role: "system"` turn. It doesn't replace the top-level system prompt, which the `system` (java, php; csharp, go: `System`; ruby: `system_`) field on the agent definition sets.
17891789
17901790<CodeGroup>
17911791 ```bash cURL
managed-agents/files Changed · +10 / -10 lines
from line 84
8484
8585## Mounting files in a session
8686
87Mount uploaded files into the sandbox by adding them to the `resources` array when creating a session:
87Mount uploaded files into the sandbox by adding them to the `resources` (java, php; csharp, go: `Resources`) array when creating a session:
8888
8989<Tip>
90 The `mount_path` is optional, but make sure the uploaded file has a descriptive name so the agent can identify it.
90 The `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) is optional, but make sure the uploaded file has a descriptive name so the agent can identify it.
9191</Tip>
9292
9393<CodeGroup>
from line 229
229229 ```
230230</CodeGroup>
231231
232With the preceding `mount_path`, the agent reads the file at `/mnt/session/uploads/data.csv` (see [File paths](https://platform.claude.com/docs/en/managed-agents/files#file-paths)).
232With the preceding `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`), the agent reads the file at `/mnt/session/uploads/data.csv` (see [File paths](https://platform.claude.com/docs/en/managed-agents/files#file-paths)).
233233
234A new `file_id` is created that references the instance of the file in the session. These copies do not count against your [storage limits](https://platform.claude.com/docs/en/build-with-claude/files).
234A new `file_id` (java: `fileId`; php: `fileID`; csharp, go: `FileID`) is created that references the instance of the file in the session. These copies do not count against your [storage limits](https://platform.claude.com/docs/en/build-with-claude/files).
235235
236236## Multiple files
237237
238Mount multiple files by adding entries to the `resources` array:
238Mount multiple files by adding entries to the `resources` (java, php; csharp, go: `Resources`) array:
239239
240240<CodeGroup>
241241 ```bash cURL
from line 354
354354
355355## Managing files on a running session
356356
357You can add or remove files from a session after creation using the session resources API. Each resource has an `id` returned when it is added (or listed), which you use for deletes.
357You can add or remove files from a session after creation using the session resources API. Each resource has an `id` (java, php; csharp, go: `ID`) returned when it is added (or listed), which you use for deletes.
358358
359359<CodeGroup>
360360 ```bash cURL
from line 555
555555
556556Use the [Files API](https://platform.claude.com/docs/en/build-with-claude/files) to list files scoped to a session and download them. Files the agent writes to `/mnt/session/outputs/` appear in the list shortly after the agent finishes writing them, sometimes a few seconds after the session goes idle. If an output file you expect is missing, list again after a short delay; once it appears in the list, its upload has finished.
557557
558Filtering by `scope_id` requires the `managed-agents-2026-04-01` beta header, so the list examples call `GET /v1/files` (curl; python, typescript, ruby: `client.beta.files.list()`; go, csharp: `client.Beta.Files.List()`; java: `client.beta().files().list()`; php: `$client->beta->files->list()`; cli: `ant beta:files list`) and pass that header explicitly.
558Filtering by `scope_id` (java: `scopeId`; php: `scopeID`; csharp, go: `ScopeID`) requires the `managed-agents-2026-04-01` beta header, so the list examples call `GET /v1/files` (curl; python, typescript, ruby: `client.beta.files.list()`; go, csharp: `client.Beta.Files.List()`; java: `client.beta().files().list()`; php: `$client->beta->files->list()`; cli: `ant beta:files list`) and pass that header explicitly.
559559
560560<CodeGroup>
561561 ```bash cURL
from line 710
710710 Files mounted in the sandbox are read-only copies. The agent can read them but cannot modify the original uploaded file. To work with modified versions, the agent writes to new paths within the sandbox.
711711</Note>
712712
713* The path you specify is rooted under the session's uploads directory: a `mount_path` of `/data.csv` places the file at `/mnt/session/uploads/data.csv` in the sandbox
714* If you omit `mount_path`, the file is placed at `/mnt/session/uploads/<file_id>`
713* The path you specify is rooted under the session's uploads directory: a `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) of `/data.csv` places the file at `/mnt/session/uploads/data.csv` in the sandbox
714* If you omit `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`), the file is placed at `/mnt/session/uploads/<file_id>`
715715* Parent directories are created automatically
716716* Paths should be absolute (starting with `/`)
717717* Files the agent writes to `/mnt/session/outputs/` become available through the Files API, scoped to the session; see [Listing and downloading session files](https://platform.claude.com/docs/en/managed-agents/files#listing-and-downloading-session-files)
managed-agents/github Changed · +10 / -10 lines
from line 241
241241 ```
242242</CodeGroup>
243243
244Then create a session that mounts the GitHub repository. With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent declares an MCP server whose host is not in `allowed_hosts`. Setting `allow_mcp_servers: true` in the environment's networking turns this check off.
244Then create a session that mounts the GitHub repository. With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent declares an MCP server whose host is not in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Setting `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) to `true` in the environment's networking turns this check off.
245245
246246<CodeGroup>
247247 ```bash cURL
from line 395
395395
396396A `github_repository` resource accepts the following fields:
397397
398| Field | Description |
399| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
400| `type` | Required. Must be `"github_repository"`. |
401| `url` | Required. The repository's HTTPS URL in the form `https://github.com/<owner>/<repo>`, without a `.git` suffix. Other forms, including SSH URLs, are rejected with an `invalid_request_error`. |
402| `authorization_token` | Required. The GitHub token used to clone the repository. It is not echoed in API responses. See [Token permissions](https://platform.claude.com/docs/en/managed-agents/github#token-permissions). |
403| `mount_path` | Optional. The directory under `/workspace` to clone the repository into. Defaults to `/workspace/<repo-name>`. |
404| `checkout` | Optional. A branch (`{"type": "branch", "name": "main"}`) or commit (`{"type": "commit", "sha": "..."}`) to check out. Defaults to the repository's default branch. |
398| Field | Description |
399| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
400| `type` (java, php; csharp, go: `Type`) | Required. Must be `"github_repository"`. |
401| `url` (java, php; csharp: `Url`; go: `URL`) | Required. The repository's HTTPS URL in the form `https://github.com/<owner>/<repo>`, without a `.git` suffix. Other forms, including SSH URLs, are rejected with an `invalid_request_error`. |
402| `authorization_token` (java, php: `authorizationToken`; csharp, go: `AuthorizationToken`) | Required. The GitHub token used to clone the repository. It is not echoed in API responses. See [Token permissions](https://platform.claude.com/docs/en/managed-agents/github#token-permissions). |
403| `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) | Optional. The directory under `/workspace` to clone the repository into. Defaults to `/workspace/<repo-name>`. |
404| `checkout` (java, php; csharp, go: `Checkout`) | Optional. A branch (`{"type": "branch", "name": "main"}`) or commit (`{"type": "commit", "sha": "..."}`) to check out. Defaults to the repository's default branch. |
405405
406406Mounting a repository also loads any skills stored in its root `.claude/skills` directory. Skills are discovered once per session, from the repository state checked out at session start. See [Load skills from a GitHub repository](https://platform.claude.com/docs/en/managed-agents/skills#load-skills-from-a-github-repository).
407407
from line 422
422422
423423## Multiple repositories
424424
425Mount multiple repositories by adding entries to the `resources` array:
425Mount multiple repositories by adding entries to the `resources` (java, php; csharp, go: `Resources`) array:
426426
427427<CodeGroup>
428428 ```bash cURL
from line 585
585585
586586## Managing repositories on a running session
587587
588After a session is created, you can list its repository resources and rotate their authorization tokens. Each resource has an `id` returned at session creation time (or through `GET /v1/sessions/{session_id}/resources` (curl; python, typescript, ruby: `client.beta.sessions.resources.list()`; go, csharp: `client.Beta.Sessions.Resources.List()`; java: `client.beta().sessions().resources().list()`; php: `$client->beta->sessions->resources->list()`; cli: `ant beta:sessions:resources list`)) that you use for updates. Repositories are attached for the lifetime of the session; to change which repositories are mounted, create a new session.
588After a session is created, you can list its repository resources and rotate their authorization tokens. Each resource has an `id` (java, php; csharp, go: `ID`) returned at session creation time (or through `GET /v1/sessions/{session_id}/resources` (curl; python, typescript, ruby: `client.beta.sessions.resources.list()`; go, csharp: `client.Beta.Sessions.Resources.List()`; java: `client.beta().sessions().resources().list()`; php: `$client->beta->sessions->resources->list()`; cli: `ant beta:sessions:resources list`)) that you use for updates. Repositories are attached for the lifetime of the session; to change which repositories are mounted, create a new session.
589589
590590<CodeGroup>
591591 ```bash cURL
managed-agents/mcp-connector Changed · +18 / -18 lines
from line 21
2121
2222## Declare MCP servers on the agent
2323
24Specify MCP servers in the `mcp_servers` array when creating an agent. Each server needs a `type`, a unique `name`, and a `url`. No authentication tokens are provided at this stage.
24Specify MCP servers in the `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) array when creating an agent. Each server needs a `type` (java, php; csharp, go: `Type`), a unique `name` (java, php; csharp, go: `Name`), and a `url` (java, php; csharp: `Url`; go: `URL`). No authentication tokens are provided at this stage.
2525
26Each declared server also needs a matching `mcp_toolset` entry in the `tools` array. The toolset's `mcp_server_name` must match the server's `name`.
26Each declared server also needs a matching `mcp_toolset` entry in the `tools` (java, php; csharp, go: `Tools`) array. The toolset's `mcp_server_name` (java, php: `mcpServerName`; csharp: `McpServerName`; go: `MCPServerName`) must match the server's `name` (java, php; csharp, go: `Name`).
2727
2828<CodeGroup defaultLanguage="CLI">
2929 ```bash cURL
from line 237
237237
238238### `mcp_servers` field reference
239239
240Each entry in the `mcp_servers` array defines one connection.
240Each entry in the `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) array defines one connection.
241241
242| Field | Description |
243| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
244| `type` | Required. Must be `"url"`. |
245| `name` | Required. A unique name for this server within the agent (1–255 characters). Used as the `mcp_server_name` in the `tools` array and surfaced on MCP tool events in the [session event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming). |
246| `url` | Required. The endpoint of the remote MCP server (up to 2,048 characters). See [Supported MCP server types](https://platform.claude.com/docs/en/managed-agents/reference#supported-mcp-server-types) for transport requirements. |
242| Field | Description |
243| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
244| `type` (java, php; csharp, go: `Type`) | Required. Must be `"url"`. |
245| `name` (java, php; csharp, go: `Name`) | Required. A unique name for this server within the agent (1–255 characters). Used as the `mcp_server_name` (java, php: `mcpServerName`; csharp: `McpServerName`; go: `MCPServerName`) in the `tools` (java, php; csharp, go: `Tools`) array and surfaced on MCP tool events in the [session event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming). |
246| `url` (java, php; csharp: `Url`; go: `URL`) | Required. The endpoint of the remote MCP server (up to 2,048 characters). See [Supported MCP server types](https://platform.claude.com/docs/en/managed-agents/reference#supported-mcp-server-types) for transport requirements. |
247247
248248Constraints:
249249
250250* An agent can declare up to 20 MCP servers. Server names must be unique within the array.
251* Every `mcp_servers` entry must be referenced by an `mcp_toolset` in the `tools` array, and every `mcp_toolset` must reference a declared server. The API rejects agent definitions with unreferenced servers or dangling toolsets.
251* Every `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) entry must be referenced by an `mcp_toolset` in the `tools` (java, php; csharp, go: `Tools`) array, and every `mcp_toolset` must reference a declared server. The API rejects agent definitions with unreferenced servers or dangling toolsets.
252252
253253## Configure which MCP tools are available
254254
255The `mcp_toolset` entry supports a `default_config` object and a `configs` array, applied to the tools the MCP server exposes. Each `configs` entry accepts only `name`, `enabled`, and `permission_policy`. Unlike entries in the built-in agent toolset, MCP tool entries do not take a `type` field, and the [web settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) available on `web_search` and `web_fetch` do not apply to MCP tools. The `name` in each `configs` entry is the bare tool name as reported by the server.
255The `mcp_toolset` entry supports a `default_config` (java, php: `defaultConfig`; csharp, go: `DefaultConfig`) object and a `configs` (java, php; csharp, go: `Configs`) array, applied to the tools the MCP server exposes. Each `configs` (java, php; csharp, go: `Configs`) entry accepts only `name` (java, php; csharp, go: `Name`), `enabled` (java, php; csharp, go: `Enabled`), and `permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`). Unlike entries in the built-in agent toolset, MCP tool entries do not take a `type` (java, php; csharp, go: `Type`) field, and the [web settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) available on `web_search` and `web_fetch` do not apply to MCP tools. The `name` (java, php; csharp, go: `Name`) in each `configs` (java, php; csharp, go: `Configs`) entry is the bare tool name as reported by the server.
256256
257257By default all tools exposed by the MCP server are enabled. To enable only specific tools, set `default_config.enabled` to `false` and explicitly enable the tools you want:
258258
from line 281
281281}
282282```
283283
284See [configuring the toolset](https://platform.claude.com/docs/en/managed-agents/tools#configuring-the-toolset) for the general `default_config` / `configs` pattern, and [MCP toolset permissions](https://platform.claude.com/docs/en/managed-agents/permission-policies#mcp-toolset-permissions) for setting `permission_policy` on MCP tools and handling confirmation requests.
284See [configuring the toolset](https://platform.claude.com/docs/en/managed-agents/tools#configuring-the-toolset) for the general `default_config` (java, php: `defaultConfig`; csharp, go: `DefaultConfig`) / `configs` (java, php; csharp, go: `Configs`) pattern, and [MCP toolset permissions](https://platform.claude.com/docs/en/managed-agents/permission-policies#mcp-toolset-permissions) for setting `permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`) on MCP tools and handling confirmation requests.
285285
286286### MCP tool output handling
287287
from line 289
289289
290290## Provide authentication at session creation
291291
292When starting a session, pass `vault_ids` to provide credentials for your MCP servers. Vaults are collections of credentials that you register once and reference by ID. See [Authenticate with vaults](https://platform.claude.com/docs/en/managed-agents/vaults) for how to create vaults and manage credentials.
292When starting a session, pass `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) to provide credentials for your MCP servers. Vaults are collections of credentials that you register once and reference by ID. See [Authenticate with vaults](https://platform.claude.com/docs/en/managed-agents/vaults) for how to create vaults and manage credentials.
293293
294With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent declares an MCP server whose host is not in `allowed_hosts`. Setting `allow_mcp_servers: true` in the environment's networking turns this check off.
294With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent declares an MCP server whose host is not in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Setting `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) to `true` in the environment's networking turns this check off.
295295
296296<CodeGroup>
297297 ```bash cURL
from line 382
382382 ```
383383</CodeGroup>
384384
385Credentials are matched by URL, so the vault must contain a credential whose `mcp_server_url` refers to the same server as the `url` declared in `mcp_servers`. Both URLs are normalized before matching (scheme and host lowercased, default ports and trailing slashes stripped), so differences in host casing, a default port, or a trailing slash don't prevent a match; a different path, subdomain, or non-default port does. If none matches, the connection is attempted unauthenticated. See [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential) for the `static_bearer` and `mcp_oauth` credential types.
385Credentials are matched by URL, so the vault must contain a credential whose `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) refers to the same server as the `url` (java, php; csharp: `Url`; go: `URL`) declared in `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`). Both URLs are normalized before matching (scheme and host lowercased, default ports and trailing slashes stripped), so differences in host casing, a default port, or a trailing slash don't prevent a match; a different path, subdomain, or non-default port does. If none matches, the connection is attempted unauthenticated. See [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential) for the `static_bearer` and `mcp_oauth` credential types.
386386
387387### Handle connection and authentication failures
388388
389Session creation does not validate MCP connectivity or credentials. It does check each declared server's host against the environment's networking: with a `limited` environment, session creation fails with a 400 error when a host is not allowed, as described under [Provide authentication at session creation](https://platform.claude.com/docs/en/managed-agents/mcp-connector#provide-authentication-at-session-creation). If an MCP server is unreachable or rejects the supplied credential, the session still starts and interaction remains possible. A [`session.error`](https://platform.claude.com/docs/en/managed-agents/reference#event-types) event is emitted with the `mcp_server_name` of the affected server and a `retry_status`:
389Session creation does not validate MCP connectivity or credentials. It does check each declared server's host against the environment's networking: with a `limited` environment, session creation fails with a 400 error when a host is not allowed, as described under [Provide authentication at session creation](https://platform.claude.com/docs/en/managed-agents/mcp-connector#provide-authentication-at-session-creation). If an MCP server is unreachable or rejects the supplied credential, the session still starts and interaction remains possible. A [`session.error`](https://platform.claude.com/docs/en/managed-agents/reference#event-types) event is emitted with the `mcp_server_name` (java, php: `mcpServerName`; csharp: `McpServerName`; go: `MCPServerName`) of the affected server and a `retry_status` (java, php: `retryStatus`; csharp, go: `RetryStatus`):
390390
391391| Error type | Meaning |
392392| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
managed-agents/memory Changed · +15 / -15 lines
from line 25
2525
2626## Create a memory store
2727
28Give the store a `name` and a `description`. The description is passed to the agent, telling it what the store contains.
28Give the store a `name` (java, php; csharp, go: `Name`) and a `description` (java, php; csharp, go: `Description`). The description is passed to the agent, telling it what the store contains.
2929
3030<CodeGroup defaultLanguage="CLI">
3131 ```bash cURL
from line 122
122122 ```
123123</CodeGroup>
124124
125The memory store `id` (`memstore_...`) is what you pass when attaching the store to a session.
125The memory store `id` (java, php; csharp, go: `ID`) (`memstore_...`) is what you pass when attaching the store to a session.
126126
127127### Seed it with content (optional)
128128
from line 212
212212
213213## Attach a memory store to a session
214214
215Memory stores are attached in the session's `resources[]` array when the [session is created](https://platform.claude.com/docs/en/managed-agents/sessions#creating-a-session). Unlike file resources, memory stores can only be attached at session creation time; adding or removing one from a running session is not supported. You attach memory stores the same way for sessions on cloud and [self-hosted environments](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory); self-hosted environments accept only `memory_store` resources.
215Memory stores are attached in the session's `resources` (java, php; csharp, go: `Resources`) array when the [session is created](https://platform.claude.com/docs/en/managed-agents/sessions#creating-a-session). Unlike file resources, memory stores can only be attached at session creation time; adding or removing one from a running session is not supported. You attach memory stores the same way for sessions on cloud and [self-hosted environments](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory); self-hosted environments accept only `memory_store` resources.
216216
217Optionally include `instructions` to provide session-specific guidance for how the agent should use this store. It is shown to the agent alongside the store's `name` and `description`, and is capped at 4,096 characters.
217Optionally include `instructions` (java, php; csharp, go: `Instructions`) to provide session-specific guidance for how the agent should use this store. It is shown to the agent alongside the store's `name` (java, php; csharp, go: `Name`) and `description` (java, php; csharp, go: `Description`), and is capped at 4,096 characters.
218218
219You can configure `access` as well. It defaults to `read_write` (shown explicitly in the following example), but `read_only` is also supported.
219You can configure `access` (java, php; csharp, go: `Access`) as well. It defaults to `read_write` (shown explicitly in the following example), but `read_only` is also supported.
220220
221221<CodeGroup>
222222 ```bash cURL
from line 381
381381
382382### How the agent accesses memory
383383
384Each attached store is mounted inside the session's sandbox as a directory under `/mnt/memory/`. The directory name is the store's display name sanitized to a filesystem-safe slug (lowercased; non-alphanumeric runs become a single hyphen), so a store named "Demo Memory" mounts at `/mnt/memory/demo-memory/`. The exact path is returned in the `mount_path` field on the session's memory-store resource; read it from there rather than constructing it yourself. The agent reads and writes the store with the standard [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools). Writes under the mount path are persisted back to the store and stay in sync across sessions that share it; writes to any other path under `/mnt/memory/` fail, because the sandbox mounts that parent directory read-only. A short description of each mount (display name, mount path, access mode, store `description`, and any `instructions`) is automatically added to the system prompt.
384Each attached store is mounted inside the session's sandbox as a directory under `/mnt/memory/`. The directory name is the store's display name sanitized to a filesystem-safe slug (lowercased; non-alphanumeric runs become a single hyphen), so a store named "Demo Memory" mounts at `/mnt/memory/demo-memory/`. The exact path is returned in the `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) field on the session's memory-store resource; read it from there rather than constructing it yourself. The agent reads and writes the store with the standard [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools). Writes under the mount path are persisted back to the store and stay in sync across sessions that share it; writes to any other path under `/mnt/memory/` fail, because the sandbox mounts that parent directory read-only. A short description of each mount (display name, mount path, access mode, store `description` (java, php; csharp, go: `Description`), and any `instructions` (java, php; csharp, go: `Instructions`)) is automatically added to the system prompt.
385385
386`access` is enforced at the filesystem level: a `read_only` mount rejects writes, while writes to a `read_write` mount produce [memory versions](https://platform.claude.com/docs/en/managed-agents/memory#audit-memory-changes) attributed to the session.
386`access` (java, php; csharp, go: `Access`) is enforced at the filesystem level: a `read_only` mount rejects writes, while writes to a `read_write` mount produce [memory versions](https://platform.claude.com/docs/en/managed-agents/memory#audit-memory-changes) attributed to the session.
387387
388388<Note>
389389 On [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory), each store's directory is a local copy that the worker manages rather than a live mount. The worker reconciles each copy with its store after tool calls, at most once per sync interval (15 seconds by default), and once more when the session ends. The agent's `write` and `edit` tools change only the local copy; the worker uploads those changes at its next sync, so another session running on a self-hosted sandbox sees a change only after both workers have synced. Paths under `/mnt/memory/` outside the store directories are not scratch space there: the worker's file tools refuse to write to them, and anything a shell command writes there is never synced to a store.
from line 573
573573
574574### Create a memory
575575
576`POST /v1/memory_stores/{memory_store_id}/memories` (curl; python, ruby: `client.beta.memory_stores.memories.create()`; typescript: `client.beta.memoryStores.memories.create()`; go: `client.Beta.MemoryStores.Memories.New()`; java: `client.beta().memoryStores().memories().create()`; csharp: `client.Beta.MemoryStores.Memories.Create()`; php: `$client->beta->memoryStores->memories->create()`; cli: `ant beta:memory-stores:memories create`) creates a memory at a given `path`. Create does not overwrite; to change an existing memory, [update it](https://platform.claude.com/docs/en/managed-agents/memory#update-a-memory) with `POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`).
576`POST /v1/memory_stores/{memory_store_id}/memories` (curl; python, ruby: `client.beta.memory_stores.memories.create()`; typescript: `client.beta.memoryStores.memories.create()`; go: `client.Beta.MemoryStores.Memories.New()`; java: `client.beta().memoryStores().memories().create()`; csharp: `client.Beta.MemoryStores.Memories.Create()`; php: `$client->beta->memoryStores->memories->create()`; cli: `ant beta:memory-stores:memories create`) creates a memory at a given `path` (java, php; csharp, go: `Path`). Create does not overwrite; to change an existing memory, [update it](https://platform.claude.com/docs/en/managed-agents/memory#update-a-memory) with `POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`).
577577
578578<CodeGroup>
579579 ```bash cURL
from line 656
656656
657657### Update a memory
658658
659`POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`) modifies an existing memory by ID. You can change `content`, `path` (a rename), or both. The example renames a memory to an archive path:
659`POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`) modifies an existing memory by ID. You can change `content` (java, php; csharp, go: `Content`), `path` (java, php; csharp, go: `Path`) (a rename), or both. The example renames a memory to an archive path:
660660
661661<CodeGroup>
662662 ```bash cURL
from line 918
918918
919919Versions belong to the store (not the individual memory) and are not deleted when the memory itself is deleted, so the audit trail also covers deleted memories, subject to the retention described below. Versions are retained for 30 days after they are written; however, the recent versions of a live memory are always kept regardless of age, so memories that change infrequently might retain history beyond 30 days. The live `GET /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.retrieve()`; typescript: `client.beta.memoryStores.memories.retrieve()`; go: `client.Beta.MemoryStores.Memories.Get()`; java: `client.beta().memoryStores().memories().retrieve()`; csharp: `client.Beta.MemoryStores.Memories.Retrieve()`; php: `$client->beta->memoryStores->memories->retrieve()`; cli: `ant beta:memory-stores:memories retrieve`) call always returns the latest version; the version endpoints give you the retained history.
920920
921There is no dedicated restore endpoint; to roll back, retrieve the version you want and write its `content` back with `POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`) (or `POST /v1/memory_stores/{memory_store_id}/memories` (curl; python, ruby: `client.beta.memory_stores.memories.create()`; typescript: `client.beta.memoryStores.memories.create()`; go: `client.Beta.MemoryStores.Memories.New()`; java: `client.beta().memoryStores().memories().create()`; csharp: `client.Beta.MemoryStores.Memories.Create()`; php: `$client->beta->memoryStores->memories->create()`; cli: `ant beta:memory-stores:memories create`) if the parent memory has been deleted, provided the version you want is still retained).
921There is no dedicated restore endpoint; to roll back, retrieve the version you want and write its `content` (java, php; csharp, go: `Content`) back with `POST /v1/memory_stores/{memory_store_id}/memories/{memory_id}` (curl; python, ruby: `client.beta.memory_stores.memories.update()`; typescript: `client.beta.memoryStores.memories.update()`; go, csharp: `client.Beta.MemoryStores.Memories.Update()`; java: `client.beta().memoryStores().memories().update()`; php: `$client->beta->memoryStores->memories->update()`; cli: `ant beta:memory-stores:memories update`) (or `POST /v1/memory_stores/{memory_store_id}/memories` (curl; python, ruby: `client.beta.memory_stores.memories.create()`; typescript: `client.beta.memoryStores.memories.create()`; go: `client.Beta.MemoryStores.Memories.New()`; java: `client.beta().memoryStores().memories().create()`; csharp: `client.Beta.MemoryStores.Memories.Create()`; php: `$client->beta->memoryStores->memories->create()`; cli: `ant beta:memory-stores:memories create`) if the parent memory has been deleted, provided the version you want is still retained).
922922
923923Past memory versions might be deleted after 30 days. To preserve memory history for longer, export versions through the API.
924924
from line 1040
10401040
10411041### Retrieve a version
10421042
1043Fetching an individual version returns the same fields as the list response plus the full `content` body.
1043Fetching an individual version returns the same fields as the list response plus the full `content` (java, php; csharp, go: `Content`) body.
10441044
10451045<CodeGroup>
10461046 ```bash cURL
from line 1197
11971197
11981198### List stores
11991199
1200List stores in the workspace. Archived stores are excluded by default; pass `include_archived: true` to include them.
1200List stores in the workspace. Archived stores are excluded by default; set `include_archived` (java, php: `includeArchived`; csharp, go: `IncludeArchived`) to `true` to include them.
12011201
12021202<CodeGroup>
12031203 ```bash cURL
managed-agents/migration Changed · +6 / -6 lines
from line 609
609609
610610* **System prompt and model:** Same fields, now on the agent definition.
611611* **Custom tools:** Still declared with JSON Schema. Execution moves from inline handling to responding to `agent.custom_tool_use` events. See [Session event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming).
612* **Web search and web fetch settings:** Same `allowed_domains`, `blocked_domains`, `max_content_tokens`, and `user_location` fields, now set once on the `web_search` and `web_fetch` entries of the agent toolset's `configs` array instead of on every request. The `max_uses`, `citations`, and `cache_control` fields are not available. See [Differences from the Messages API tools](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#differences-from-the-messages-api-tools).
612* **Web search and web fetch settings:** Same `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`), `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`), `max_content_tokens` (java, php: `maxContentTokens`; csharp, go: `MaxContentTokens`), and `user_location` (java, php: `userLocation`; csharp, go: `UserLocation`) fields, now set once on the `web_search` and `web_fetch` entries of the agent toolset's `configs` (java, php; csharp, go: `Configs`) array instead of on every request. The `max_uses` (java, php: `maxUses`; csharp, go: `MaxUses`), `citations` (java, php; csharp, go: `Citations`), and `cache_control` (java, php: `cacheControl`; csharp, go: `CacheControl`) fields are not available. See [Differences from the Messages API tools](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#differences-from-the-messages-api-tools).
613613* **Context:** You can still inject context through the system prompt, [file resources](https://platform.claude.com/docs/en/managed-agents/files), or [skills](https://platform.claude.com/docs/en/managed-agents/skills).
614614
615615## From the Claude Agent SDK
from line 625
625625| Functions defined with `@tool` (python; typescript: `tool()`), dispatched automatically by the SDK | Declare as `{"type": "custom", ...}` on the Agent; your client handles `agent.custom_tool_use` events and replies with `user.custom_tool_result`. See [Tools](https://platform.claude.com/docs/en/managed-agents/tools). |
626626| Built-in tools run in your process against your filesystem | `{"type": "agent_toolset_20260401"}` runs the same tools inside the session sandbox against `/workspace`. |
627627| `cwd`, `add_dirs` (python; typescript: `additionalDirectories`) point at local paths | Upload or mount [files](https://platform.claude.com/docs/en/managed-agents/files) as session resources. |
628| `system_prompt` (python; typescript: `systemPrompt`) and the `CLAUDE.md` hierarchy | A single `system` string on the Agent. Each update that changes the agent produces a new server-side version; pin sessions to a specific version to promote or roll back without a deploy. See [Agent setup](https://platform.claude.com/docs/en/managed-agents/agent-setup). |
628| `system_prompt` (python; typescript: `systemPrompt`) and the `CLAUDE.md` hierarchy | A single `system` (java, php; csharp, go: `System`; ruby: `system_`) string on the Agent. Each update that changes the agent produces a new server-side version; pin sessions to a specific version to promote or roll back without a deploy. See [Agent setup](https://platform.claude.com/docs/en/managed-agents/agent-setup). |
629629| `mcp_servers` (python; typescript: `mcpServers`) configured and authenticated in one place | Declare servers on the Agent; provide credentials through a [Vault](https://platform.claude.com/docs/en/managed-agents/vaults) on the Session. |
630| `permission_mode` (python; typescript: `permissionMode`), `can_use_tool` (python; typescript: `canUseTool`) | Per-tool [`permission_policy`](https://platform.claude.com/docs/en/managed-agents/permission-policies) (`always_allow`, `always_ask`, or `auto`); send `user.tool_confirmation` events for calls that pause for your approval. |
630| `permission_mode` (python; typescript: `permissionMode`), `can_use_tool` (python; typescript: `canUseTool`) | Per-tool [`permission_policy` (java, php: `permissionPolicy`; csharp, go: `PermissionPolicy`)](https://platform.claude.com/docs/en/managed-agents/permission-policies) (`always_allow`, `always_ask`, or `auto`); send `user.tool_confirmation` events for calls that pause for your approval. |
631631
632632### Code comparison
633633
from line 1357
135713571. [Create an environment](https://platform.claude.com/docs/en/managed-agents/environments) with the networking and runtimes your agent needs.
135813582. Port your system prompt and tool selection to an [agent definition](https://platform.claude.com/docs/en/managed-agents/agent-setup).
135913593. Replace your loop: [create a session](https://platform.claude.com/docs/en/managed-agents/sessions) with `client.beta.sessions.create()` (python, typescript, ruby; go: `client.Beta.Sessions.New()`; csharp: `client.Beta.Sessions.Create()`; java: `client.beta().sessions().create()`; php: `$client->beta->sessions->create()`; cli: `ant beta:sessions create`; curl: `POST /v1/sessions`) and [stream its events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) with `client.beta.sessions.events.stream()` (python, typescript; ruby: `client.beta.sessions.events.stream_events()`; go: `client.Beta.Sessions.Events.StreamEvents()`; csharp: `client.Beta.Sessions.Events.StreamStreaming()`; java: `client.beta().sessions().events().streamStreaming()`; php: `$client->beta->sessions->events->streamStream()`; cli: `ant beta:sessions:events stream`; curl: `GET /v1/sessions/{session_id}/events/stream`).
13604. For any local files the agent reads, upload them through the [Files API](https://platform.claude.com/docs/en/managed-agents/files) and mount them as `resources`.
13604. For any local files the agent reads, upload them through the [Files API](https://platform.claude.com/docs/en/managed-agents/files) and mount them as `resources` (java, php; csharp, go: `Resources`).
136113615. For any custom tool handlers, move execution into your event loop as responses to `agent.custom_tool_use` events.
136213626. Verify with a test session before pointing production traffic at the new flow.
13631363
13641364## Migrating between model versions
13651365
1366When a new Claude model is released, migrating a Claude Managed Agents integration is typically a one-field change: update `model` on your [agent definition](https://platform.claude.com/docs/en/managed-agents/agent-setup) and the change takes effect on the next session you create.
1366When a new Claude model is released, migrating a Claude Managed Agents integration is typically a one-field change: update `model` (java, php; csharp, go: `Model`) on your [agent definition](https://platform.claude.com/docs/en/managed-agents/agent-setup) and the change takes effect on the next session you create.
13671367
13681368<CodeGroup defaultLanguage="CLI">
13691369 ```bash cURL
from line 1457
14571457
14581458Most model-level behavior changes documented in the [Messages API migration guide](https://platform.claude.com/docs/en/about-claude/models/migration-guide) do not require action on your side:
14591459
1460* **Request parameter changes** (`max_tokens` defaults, `thinking` configuration) are handled by the Claude Managed Agents runtime. These fields are not exposed on the agent definition.
1460* **Request parameter changes** (`max_tokens` (java, php: `maxTokens`; csharp, go: `MaxTokens`) defaults, `thinking` (java, php; csharp, go: `Thinking`) configuration) are handled by the Claude Managed Agents runtime. These fields are not exposed on the agent definition.
14611461* **Assistant message prefilling** does not exist in the event-based session model, so its removal on newer models is a no-op.
14621462* **Tool argument JSON escaping** is parsed by the runtime before you receive `agent.custom_tool_use` events. You see structured data, not raw strings.
14631463
managed-agents/multiagent-orchestration Changed · +30 / -30 lines
from line 42
4242
4343Every subagent, and every agent in a workflow run, is one of two kinds:
4444
45* **Predefined agent:** An agent that you have already [created](https://platform.claude.com/docs/en/managed-agents/agent-setup), and that you list in the `multiagent` block. It uses its own configuration: model, system prompt, tools, MCP servers, and skills.
45* **Predefined agent:** An agent that you have already [created](https://platform.claude.com/docs/en/managed-agents/agent-setup), and that you list in the `multiagent` (java, php; csharp, go: `Multiagent`) block. It uses its own configuration: model, system prompt, tools, MCP servers, and skills.
4646* **Inline agent:** An agent that is not saved. The agent that the session runs, or a workflow, defines it when it hands out the work. It uses that agent's model, tools, MCP servers, and skills.
4747
4848Both kinds work under `subagents` and under `workflows`:
from line 107
107107
108108### List the subagents
109109
110When [defining your agent](https://platform.claude.com/docs/en/managed-agents/agent-setup), set `subagents.predefined_agents` in the `multiagent` block to list the agents that it can delegate to:
110When [defining your agent](https://platform.claude.com/docs/en/managed-agents/agent-setup), set the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) in the `multiagent` (java, php; csharp, go: `Multiagent`) block to list the agents that it can delegate to:
111111
112112<CodeGroup defaultLanguage="CLI">
113113 ```bash cURL
from line 359
359359 ```
360360</CodeGroup>
361361
362The agent can also delegate to inline agents unless you turn them off. For that setting, and for the forms that an entry of `subagents.predefined_agents` takes, see [Predefined and inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents).
362The agent can also delegate to inline agents unless you turn them off. For that setting, and for the forms that an entry of the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) takes, see [Predefined and inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents).
363363
364`"advisor": {"type": "enabled", "model": "<model id>"}` gives the session's primary thread an advisor it can consult mid-turn. The advisor is a setting in the `multiagent` block, not an entry in this list. See [Give the session an advisor](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#give-the-session-an-advisor).
364`"advisor": {"type": "enabled", "model": "<model id>"}` gives the session's primary thread an advisor it can consult mid-turn. The advisor is a setting in the `multiagent` (java, php; csharp, go: `Multiagent`) block, not an entry in this list. See [Give the session an advisor](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#give-the-session-an-advisor).
365365
366366Dynamic workflows are also enabled by default with this type, so this agent can plan large work that runs many agents in the background. To turn them off, or to list agents that a workflow can use, see [Turn on dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#turn-on-dynamic-workflows).
367367
368The following rules apply to the agents you list in `subagents.predefined_agents`, and also to the agents you list in `workflows.predefined_agents`:
368The following rules apply to the agents you list in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`), and also to the agents you list in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`):
369369
370* **Pinning:** The agent's configuration, including its `subagents.predefined_agents` list, is snapshotted when the agent is created or updated. Referenced agents stay pinned to the versions resolved then and don't pick up later updates to their definitions. An update that doesn't send the list keeps the versions that are already pinned. To delegate to a newer version of a referenced agent, [update the agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent) so its `subagents.predefined_agents` list references that version.
371* **One level:** The agent can delegate to only one level of agents. Referencing another agent that has `multiagent` set fails the create or update request with a 400 validation error.
372* **Up to 20 agents:** `subagents.predefined_agents` can list up to 20 unique agents. The limit is per list: `workflows.predefined_agents` can also list up to 20. The agent can call multiple copies of each agent, within the session's [thread limit](https://platform.claude.com/docs/en/managed-agents/session-threads).
373* **Inference geography:** The agent and every agent that you list, in `subagents.predefined_agents` or in `workflows.predefined_agents`, must pin the same [inference geography](https://platform.claude.com/docs/en/manage-claude/data-residency) (`model.inference_geo` in the [agent definition](https://platform.claude.com/docs/en/managed-agents/agent-setup)), or none of them can pin one. A mismatch in either list is rejected with a 400 validation error. That check runs both when the agent is saved and when a [session-create override](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session) changes any of the pins.
370* **Pinning:** The agent's configuration, including the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of its `subagents` (java, php; csharp, go: `Subagents`), is snapshotted when the agent is created or updated. Referenced agents stay pinned to the versions resolved then and don't pick up later updates to their definitions. An update that doesn't send the list keeps the versions that are already pinned. To delegate to a newer version of a referenced agent, [update the agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent) so the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of its `subagents` (java, php; csharp, go: `Subagents`) references that version.
371* **One level:** The agent can delegate to only one level of agents. Referencing another agent that has `multiagent` (java, php; csharp, go: `Multiagent`) set fails the create or update request with a 400 validation error.
372* **Up to 20 agents:** The `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) can list up to 20 unique agents. The limit is per list: the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`) can also list up to 20. The agent can call multiple copies of each agent, within the session's [thread limit](https://platform.claude.com/docs/en/managed-agents/session-threads).
373* **Inference geography:** The agent and every agent that you list, in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or of `workflows` (java, php; csharp, go: `Workflows`), must pin the same [inference geography](https://platform.claude.com/docs/en/manage-claude/data-residency) (`inference_geo` (java, php: `inferenceGeo`; csharp, go: `InferenceGeo`) in the `model` (java, php; csharp, go: `Model`) of the [agent definition](https://platform.claude.com/docs/en/managed-agents/agent-setup)), or none of them can pin one. A mismatch in either list is rejected with a 400 validation error. That check runs both when the agent is saved and when a [session-create override](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session) changes any of the pins.
374374
375375### Create the session
376376
377Create a session referencing the agent. The agent delegates to the agents you list in `subagents.predefined_agents` as needed. It can also delegate to [inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents) unless you turn them off.
377Create a session referencing the agent. The agent delegates to the agents you list in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) as needed. It can also delegate to [inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents) unless you turn them off.
378378
379379<CodeGroup>
380380 ```bash cURL
from line 457
457457
458458### Connect agents to MCP servers
459459
460MCP servers are agent-scoped: each agent definition declares its own servers and tools. An inline agent has no agent definition, so it uses the MCP servers and tools of the agent that the session runs. Vault credentials are session-scoped: `vault_ids` passed at session creation apply to every thread. Two implications for your integration:
460MCP servers are agent-scoped: each agent definition declares its own servers and tools. An inline agent has no agent definition, so it uses the MCP servers and tools of the agent that the session runs. Vault credentials are session-scoped: `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) passed at session creation apply to every thread. Two implications for your integration:
461461
462462* To authenticate MCP servers, include a vault credential for every MCP server used across all agents.
463* To limit an agent's access, declare only the servers it needs in its agent definition. You can't limit an inline agent this way. To allow only the agents you list, disable `inline_agents` in both `subagents` and `workflows`, and list at least one agent in each. See [Predefined and inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents).
463* To limit an agent's access, declare only the servers it needs in its agent definition. You can't limit an inline agent this way. To allow only the agents you list, disable `inline_agents` (java, php: `inlineAgents`; csharp, go: `InlineAgents`) in both `subagents` (java, php; csharp, go: `Subagents`) and `workflows` (java, php; csharp, go: `Workflows`), and list at least one agent in each. See [Predefined and inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents).
464464
465465[Agent configuration overrides](https://platform.claude.com/docs/en/managed-agents/sessions#override-agent-configuration-for-a-session) at session creation can replace the MCP servers of the agent that the session runs and those of its `self` copies.
466466
467With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent, or an agent you list in `subagents.predefined_agents` or `workflows.predefined_agents`, declares an MCP server whose host is not in `allowed_hosts`. Setting `allow_mcp_servers: true` in the environment's networking turns this check off.
467With a `limited` [environment](https://platform.claude.com/docs/en/managed-agents/environments#networking), session creation fails with a 400 error when the agent, or an agent you list in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or `workflows` (java, php; csharp, go: `Workflows`), declares an MCP server whose host is not in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). Setting `allow_mcp_servers` (java: `allowMcpServers`; php: `allowMCPServers`; csharp: `AllowMcpServers`; go: `AllowMCPServers`) to `true` in the environment's networking turns this check off.
468468
469469Create the researcher, which declares the GitHub MCP server, and the agent that delegates to the researcher:
470470
from line 880
880880 ```
881881</CodeGroup>
882882
883In this example, only the researcher declares the GitHub MCP server, so the agent that the session runs does not have access. The session's `vault_ids` supply the GitHub credential to the researcher's thread.
883In this example, only the researcher declares the GitHub MCP server, so the agent that the session runs does not have access. The session's `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) supply the GitHub credential to the researcher's thread.
884884
885885<Tip>
886 If an agent's MCP calls fail to authenticate after you declare the server, confirm the credential's `mcp_server_url` refers to the same server as the agent's `mcp_servers[].url`. Both URLs are normalized before matching (scheme and host lowercased, default ports and trailing slashes stripped), so differences in host casing, a default port, or a trailing slash don't prevent a match; a different path, subdomain, or non-default port does.
886 If an agent's MCP calls fail to authenticate after you declare the server, confirm the credential's `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) refers to the same server as the agent's `mcp_servers[].url` (java, php: `mcpServers[].url`; csharp: `McpServers[].Url`; go: `MCPServers[].URL`). Both URLs are normalized before matching (scheme and host lowercased, default ports and trailing slashes stripped), so differences in host casing, a default port, or a trailing slash don't prevent a match; a different path, subdomain, or non-default port does.
887887</Tip>
888888
889889### Threads
from line 892
892892
893893## Dynamic workflows
894894
895With dynamic workflows, an agent can take on work with many pieces, such as reviewing hundreds of documents or cross-checking many sources. The agent writes a **workflow**: a program that runs many agents in phases and combines what they return. The server runs it in the background as a **workflow run**, while the agent keeps working or ends its turn. You turn dynamic workflows on or off with the `workflows` setting in the agent's `multiagent` block. A run's agents can work at the same time, so a long task can finish sooner than if one agent did each piece in turn.
895With dynamic workflows, an agent can take on work with many pieces, such as reviewing hundreds of documents or cross-checking many sources. The agent writes a **workflow**: a program that runs many agents in phases and combines what they return. The server runs it in the background as a **workflow run**, while the agent keeps working or ends its turn. You turn dynamic workflows on or off with the `workflows` (java, php; csharp, go: `Workflows`) setting in the agent's `multiagent` (java, php; csharp, go: `Multiagent`) block. A run's agents can work at the same time, so a long task can finish sooner than if one agent did each piece in turn.
896896
897897* **How a run starts:** You describe the work in a `user.message`. From that, the agent determines whether and when to start a run, so there's no additional API call. Instead, you influence the agent's determination by describing when to use a run in `user.message` or in the agent's system prompt. (Permission policies apply to the tools that a run's agents call, not to starting the run.)
898* **Which agents it uses:** [Inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents) that the workflow defines, predefined agents that you list in `workflows.predefined_agents`, or both. If you list none, the workflow defines them all. An inline agent uses the model of the agent that the session runs. To let a run use another model for some of its agents, create them as agents and list them in `workflows.predefined_agents`.
898* **Which agents it uses:** [Inline agents](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#predefined-and-inline-agents) that the workflow defines, predefined agents that you list in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`), or both. If you list none, the workflow defines them all. An inline agent uses the model of the agent that the session runs. To let a run use another model for some of its agents, create them as agents and list them in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`).
899899* **How you follow it:** Run events arrive on the session's event stream, and each agent in the run works in a [session thread](https://platform.claude.com/docs/en/managed-agents/session-threads) that you can list, read, and stream. See [Workflow runs](https://platform.claude.com/docs/en/managed-agents/workflow-runs) for the events, interrupts, limits, and [what a run's threads show](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads).
900900
901901### Turn on dynamic workflows
from line 1092
10921092
10931093 * A setting or field you leave out keeps its stored value.
10941094 * A setting or field you send as `null` takes its default, and so does everything inside it, whatever you had stored.
1095 * A `predefined_agents` list you send replaces the stored list.
1095 * A `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list you send replaces the stored list.
10961096 * A setting you send with a different `type` replaces the stored setting, and the fields you leave out of it take their defaults.
10971097 * Every object you send needs its `type`, and an enabled `advisor` needs its `model`.
10981098
from line 1100
11001100
11011101* **Existing sessions:** A session copies the setting when it is created, so changing the agent later doesn't change a session that already exists.
11021102
1103* **Agents you can list:** An agent that has `multiagent` set can't be listed as a subagent of another agent, or in another agent's `workflows.predefined_agents`. An agent can list itself in either list with `{"type": "self"}`, which reads back as its own `id` and `version`.
1103* **Agents you can list:** An agent that has `multiagent` (java, php; csharp, go: `Multiagent`) set can't be listed as a subagent of another agent, or in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `workflows` (java, php; csharp, go: `Workflows`) in another agent. An agent can list itself in either list with `{"type": "self"}`, which reads back as its own `id` and `version`.
11041104
1105* **Tool names:** The `ant__` prefix is reserved. If your agent already has a custom tool whose name starts with `ant__`, every update fails with a 400 error until you send `tools` without that name. A new session is refused with a 400 error too if its agent, or an agent in either list, has such a tool. Rename or remove the tool in the same update that turns dynamic workflows on. See [Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools).
1105* **Tool names:** The `ant__` prefix is reserved. If your agent already has a custom tool whose name starts with `ant__`, every update fails with a 400 error until you send `tools` (java, php; csharp, go: `Tools`) without that name. A new session is refused with a 400 error too if its agent, or an agent in either list, has such a tool. Rename or remove the tool in the same update that turns dynamic workflows on. See [Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools).
11061106
11071107* **Budget:** Set a [session budget](https://platform.claude.com/docs/en/managed-agents/budgets) when you create the session to cap the session's spend, runs included; you can't add one to an existing session. Runs pause when the session reaches the budget, and runs that the budget paused resume when you raise or remove it, unless an interrupt also paused them. See [Budgets and limits](https://platform.claude.com/docs/en/managed-agents/workflow-runs#budgets-and-limits).
11081108
from line 1128
11281128
11291129## Give the session an advisor
11301130
1131An enabled `advisor` setting in the agent's `multiagent` block gives the session's primary thread an **advisor**: a model it can consult mid-turn for strategic guidance, such as planning an approach, getting unstuck, or reviewing work before finishing. The setting is disabled by default. To enable it, set `advisor` to `{"type": "enabled", "model": "..."}`, which has exactly two fields, `type` and `model`:
1131An enabled `advisor` setting in the agent's `multiagent` (java, php; csharp, go: `Multiagent`) block gives the session's primary thread an **advisor**: a model it can consult mid-turn for strategic guidance, such as planning an approach, getting unstuck, or reviewing work before finishing. The setting is disabled by default. To enable it, set `advisor` to `{"type": "enabled", "model": "..."}`, which has exactly two fields, `type` and `model`:
11321132
11331133<CodeGroup defaultLanguage="CLI">
11341134 ```bash cURL
from line 1275
12751275 ```
12761276</CodeGroup>
12771277
1278This example sets only `advisor`. The other two settings, `subagents` and `workflows`, keep their defaults, so both are enabled, and the agent can also delegate to inline agents and start workflow runs. For an agent that consults an advisor and does all the work itself, set both to `{"type": "disabled"}`.
1278This example sets only `advisor` (java, php; csharp, go: `Advisor`). The other two settings, `subagents` (java, php; csharp, go: `Subagents`) and `workflows` (java, php; csharp, go: `Workflows`), keep their defaults, so both are enabled, and the agent can also delegate to inline agents and start workflow runs. For an agent that consults an advisor and does all the work itself, set both to `{"type": "disabled"}`.
12791279
1280You can't list the advisor in `subagents.predefined_agents` or `workflows.predefined_agents`. An enabled `advisor` reserves the name `anthropic.advisor`. While it is enabled, neither list can hold an agent literally named `anthropic.advisor`: the request is rejected with a 400 validation error.
1280You can't list the advisor in the `predefined_agents` (java, php: `predefinedAgents`; csharp, go: `PredefinedAgents`) list of `subagents` (java, php; csharp, go: `Subagents`) or `workflows` (java, php; csharp, go: `Workflows`). An enabled `advisor` (java, php; csharp, go: `Advisor`) reserves the name `anthropic.advisor`. While it is enabled, neither list can hold an agent literally named `anthropic.advisor`: the request is rejected with a 400 validation error.
12811281
12821282The advisor model must meet a minimum capability bar, and the agent's own model must not be more capable than its advisor; models of equal capability can pair. An invalid pairing is rejected with a 400 validation error when the agent is saved, and again when a session is created. The pairing is also checked when each consultation starts: if it's no longer valid, that consultation fails and the session continues. Valid pairings follow the advisor tool's [model compatibility](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#model-compatibility) table.
12831283
1284The advisor is also available as a [server tool on the Messages API](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool). The Managed Agents surface differs in configuration and delivery: the `advisor` setting has no `max_uses`, `max_tokens`, or `caching` fields, and advice arrives through thread events rather than `advisor_tool_result` blocks.
1284The advisor is also available as a [server tool on the Messages API](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool). The Managed Agents surface differs in configuration and delivery: the `advisor` (java, php; csharp, go: `Advisor`) setting has no `max_uses`, `max_tokens`, or `caching` fields, and advice arrives through thread events rather than `advisor_tool_result` blocks.
12851285
12861286### How consultations work
12871287
1288Each consultation runs as a platform-spawned thread named `anthropic.advisor` that terminates itself when the consultation completes, and the advice is delivered to the primary thread as an `agent.thread_message_received` event. A consultation emits the standard thread events, identified by the reserved name `anthropic.advisor` (the thread lifecycle events carry it as `agent_name`, and the advice delivery carries it as `from_agent_name`), typically in this order:
1288Each consultation runs as a platform-spawned thread named `anthropic.advisor` that terminates itself when the consultation completes, and the advice is delivered to the primary thread as an `agent.thread_message_received` event. A consultation emits the standard thread events, identified by the reserved name `anthropic.advisor` (the thread lifecycle events carry it as `agent_name` (java, php: `agentName`; csharp, go: `AgentName`), and the advice delivery carries it as `from_agent_name` (java, php: `fromAgentName`; csharp, go: `FromAgentName`)), typically in this order:
12891289
129012901. `session.thread_created`
129112912. `session.thread_status_running`
from line 1297
12971297
12981298Whether your client can read the advice is the advisor model's policy. It mirrors the [result variants](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#result-variants) split on the Messages API advisor tool. An advisor model that returns plaintext results there delivers readable text here. One that returns redacted results delivers a `[{"type": "redacted"}]` placeholder on every client surface, while the agent still reads the full advice server-side. The preceding example uses the newest Opus model available to you as the advisor. Claude Opus 5 and Claude Opus 5.5 return redacted results, so with either one your client sees only the placeholder. To read the advice on the event stream, use an advisor that returns plaintext, such as Claude Opus 4.8. A model's policy can change with no change to the API, so handle both `text` and `redacted` blocks. Some agent models pair only with redacted-result advisors; see the advisor tool's [compatibility table](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool#model-compatibility). Advisor thinking is never surfaced. Clients cannot send `redacted` blocks themselves; an event containing one is rejected with a 400 validation error.
12991299
1300A failed or interrupted consultation never fails the agent's turn: the agent continues after a generic notice that the consultation failed. A session-level `user.interrupt` during a consultation terminates the advisor thread with no advice delivered; a `user.interrupt` with the advisor thread's `session_thread_id` abandons only that consultation.
1300A failed or interrupted consultation never fails the agent's turn: the agent continues after a generic notice that the consultation failed. A session-level `user.interrupt` during a consultation terminates the advisor thread with no advice delivered; a `user.interrupt` with the advisor thread's `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) abandons only that consultation.
13011301
13021302### Advisor threads
13031303
managed-agents/permission-policies Changed · +12 / -12 lines
from line 26
2626
2727## Set a policy for a toolset
2828
29You set permission policies in the agent's `tools` configuration when you create the agent, and you can change them later by [updating the agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent). Running sessions keep the toolset configuration they were created with. Updates apply to sessions created afterward.
29You set permission policies in the agent's `tools` (java, php; csharp, go: `Tools`) configuration when you create the agent, and you can change them later by [updating the agent](https://platform.claude.com/docs/en/managed-agents/agent-setup#update-an-agent). Running sessions keep the toolset configuration they were created with. Updates apply to sessions created afterward.
3030
3131### Agent toolset permissions
3232
33When creating an agent, you can apply a policy to every tool in `agent_toolset_20260401` using `default_config.permission_policy`:
33When creating an agent, you can apply a policy to every tool in `agent_toolset_20260401` using `default_config.permission_policy` (java, php: `defaultConfig.permissionPolicy`; csharp, go: `DefaultConfig.PermissionPolicy`):
3434
3535<CodeGroup defaultLanguage="CLI">
3636 ```bash cURL
from line 209
209209 ```
210210</CodeGroup>
211211
212`default_config` is optional. If you omit it, the agent toolset is enabled with the default permission policy, `always_allow`.
212`default_config` (java, php: `defaultConfig`; csharp, go: `DefaultConfig`) is optional. If you omit it, the agent toolset is enabled with the default permission policy, `always_allow`.
213213
214214### MCP toolset permissions
215215
216MCP toolsets default to `always_ask`. This ensures that new tools added to an MCP server do not execute in your application without approval. To auto-approve tools from a trusted MCP server, set `default_config.permission_policy` on the `mcp_toolset` entry.
216MCP toolsets default to `always_ask`. This ensures that new tools added to an MCP server do not execute in your application without approval. To auto-approve tools from a trusted MCP server, set `default_config.permission_policy` (java, php: `defaultConfig.permissionPolicy`; csharp, go: `DefaultConfig.PermissionPolicy`) on the `mcp_toolset` entry.
217217
218The `mcp_server_name` must match the `name` of a server in the `mcp_servers` array.
218The `mcp_server_name` (java, php: `mcpServerName`; csharp: `McpServerName`; go: `MCPServerName`) must match the `name` (java, php; csharp, go: `Name`) of a server in the `mcp_servers` (java, php: `mcpServers`; csharp: `McpServers`; go: `MCPServers`) array.
219219
220220This example connects a GitHub MCP server and allows its tools to run without confirmation:
221221
from line 475
475475
476476## Override an individual tool policy
477477
478Use the `configs` array to override the default for individual tools. The `name` values for the agent toolset are listed in [Available tools](https://platform.claude.com/docs/en/managed-agents/tools#available-tools). This example allows the full agent toolset by default but requires confirmation before any bash command runs:
478Use the `configs` (java, php; csharp, go: `Configs`) array to override the default for individual tools. The `name` (java, php; csharp, go: `Name`) values for the agent toolset are listed in [Available tools](https://platform.claude.com/docs/en/managed-agents/tools#available-tools). This example allows the full agent toolset by default but requires confirmation before any bash command runs:
479479
480480<CodeGroup defaultLanguage="CLI">
481481 ```bash cURL
from line 673
673673 ```
674674</CodeGroup>
675675
676Pass this `tools` configuration in the agent create request (the CLI tab shows the complete command). MCP toolsets support the same per-tool overrides, with `name` set to the tool name reported by the MCP server. See [Configure which MCP tools are available](https://platform.claude.com/docs/en/managed-agents/mcp-connector#configure-which-mcp-tools-are-available).
676Pass this `tools` (java, php; csharp, go: `Tools`) configuration in the agent create request (the CLI tab shows the complete command). MCP toolsets support the same per-tool overrides, with `name` (java, php; csharp, go: `Name`) set to the tool name reported by the MCP server. See [Configure which MCP tools are available](https://platform.claude.com/docs/en/managed-agents/mcp-connector#configure-which-mcp-tools-are-available).
677677
678678## Let the server evaluate each call with `auto`
679679
from line 683
683683* **The call is denied.** When the server evaluates the call as high-risk, the tool does not run. The agent receives an error tool result with the content `Permission to use {tool_name} has been denied.` and `is_error: true`. The session keeps running, and your client cannot override the denial.
684684* **The call pauses for your approval.** When the server reaches no determination, the session pauses as it does under `always_ask`. See [Respond to confirmation requests](https://platform.claude.com/docs/en/managed-agents/permission-policies#respond-to-confirmation-requests).
685685
686To turn on `auto`, set `permission_policy` to `{"type": "auto"}`. It goes in the same two places as the other policies: a toolset's [`default_config`](https://platform.claude.com/docs/en/managed-agents/permission-policies#set-a-policy-for-a-toolset) for the whole toolset, or a [`configs` entry](https://platform.claude.com/docs/en/managed-agents/permission-policies#override-an-individual-tool-policy) for one tool. The agent toolset and MCP toolsets both accept it. No toolset uses `auto` by default.
686To turn on `auto`, set `permission_policy` to `{"type": "auto"}`. It goes in the same two places as the other policies: a toolset's [`default_config` (java, php: `defaultConfig`; csharp, go: `DefaultConfig`)](https://platform.claude.com/docs/en/managed-agents/permission-policies#set-a-policy-for-a-toolset) for the whole toolset, or a [`configs` (java, php; csharp, go: `Configs`) entry](https://platform.claude.com/docs/en/managed-agents/permission-policies#override-an-individual-tool-policy) for one tool. The agent toolset and MCP toolsets both accept it. No toolset uses `auto` by default.
687687
688688The following example sets `auto` as the default for the agent toolset and for the `github` MCP toolset, and overrides `bash` to `always_ask`:
689689
from line 1076
10761076
107710771. The session emits an `agent.tool_use` or `agent.mcp_tool_use` event.
107810782. The session pauses with a `session.status_idle` event whose `stop_reason.type` is `requires_action`. The blocking event IDs are in the `stop_reason.event_ids` array. The session waits indefinitely for a response. A call from a thread of a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#while-a-run-is-open) reaches your client on the primary stream. While anything else in the session is working, the session can stay `running` and send no `session.status_idle`, so answer the tool-use event itself. The call waits only until the run finishes with that thread or the run ends. An interrupt might leave it waiting, so allow or deny it yourself.
10793. Send a `user.tool_confirmation` event for each blocking event, passing the event ID in the `tool_use_id` parameter. Set `result` to `"allow"` or `"deny"`. Use `deny_message` to explain a denial. You can send several confirmations in a single `events` request.
10804. Once all blocking events are resolved, the session transitions back to `running`. Allowed tools execute. Denied tools do not run, and the agent receives a tool result saying the call was rejected, including your `deny_message`.
10793. Send a `user.tool_confirmation` event for each blocking event, passing the event ID in the `tool_use_id` (java: `toolUseId`; php: `toolUseID`; csharp, go: `ToolUseID`) parameter. Set `result` (java, php; csharp, go: `Result`) to `"allow"` or `"deny"`. Use `deny_message` (java, php: `denyMessage`; csharp, go: `DenyMessage`) to explain a denial. You can send several confirmations in a single `events` request.
10804. Once all blocking events are resolved, the session transitions back to `running`. Allowed tools execute. Denied tools do not run, and the agent receives a tool result saying the call was rejected, including your `deny_message` (java, php: `denyMessage`; csharp, go: `DenyMessage`).
10811081
10821082For example, a `bash` call paused under an `always_ask` policy appears on the stream as follows:
10831083
from line 1097
10971097}
10981098```
10991099
1100If you send a `user.tool_confirmation` for an event whose `evaluated_permission` is not `ask`, the API rejects it with a 400 error. That includes calls the server denied under `auto`: your client cannot override them.
1100If you send a `user.tool_confirmation` for an event whose `evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`) is not `ask`, the API rejects it with a 400 error. That includes calls the server denied under `auto`: your client cannot override them.
11011101
11021102To answer interactively instead, use `ant beta:sessions connect`, which shows the waiting call and sends this event when you allow or deny it. See [Connect to a Managed Agents session from your terminal](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/sessions-connect#follow-and-steer-the-session).
11031103
managed-agents/reference Changed · +42 / -42 lines
from line 29
2929 </Tab>
3030
3131 <Tab title="Agent events">
32 | Type | Description |
33 | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34 | `agent.message` | Agent response content blocks. |
35 | `agent.thinking` | Signals the agent is making forward progress through extended thinking. This is a progress signal only and does not carry the thinking content. |
36 | `agent.tool_use` | Agent invokes a pre-built agent tool (bash, file operations, and so on). Carries `evaluated_permission` and, usually, `evaluation` (see [how each call was evaluated](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated)). |
37 | `agent.tool_result` | Result of a pre-built agent tool execution. |
38 | `agent.mcp_tool_use` | Agent invokes an MCP server tool. Carries `evaluated_permission` and, usually, `evaluation` (see [how each call was evaluated](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated)). |
39 | `agent.mcp_tool_result` | Result of an MCP tool execution. |
40 | `agent.custom_tool_use` | Agent invokes one of your custom tools. Respond with a `user.custom_tool_result` event. |
41 | `agent.thread_context_compacted` | Conversation history was compacted to fit the context window. |
42 | `agent.thread_message_received` | In a [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) session, a message from another thread arrived on the thread whose stream carries this event; on the primary thread, an agent sent a report or question to the agent that the session runs. |
43 | `agent.thread_message_sent` | In a [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) session, the thread whose stream carries this event sent a message to another thread; on the primary thread, the agent that the session runs sent a task or follow-up message to another agent. |
32 | Type | Description |
33 | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34 | `agent.message` | Agent response content blocks. |
35 | `agent.thinking` | Signals the agent is making forward progress through extended thinking. This is a progress signal only and does not carry the thinking content. |
36 | `agent.tool_use` | Agent invokes a pre-built agent tool (bash, file operations, and so on). Carries `evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`) and, usually, `evaluation` (java, php; csharp, go: `Evaluation`) (see [how each call was evaluated](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated)). |
37 | `agent.tool_result` | Result of a pre-built agent tool execution. |
38 | `agent.mcp_tool_use` | Agent invokes an MCP server tool. Carries `evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`) and, usually, `evaluation` (java, php; csharp, go: `Evaluation`) (see [how each call was evaluated](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated)). |
39 | `agent.mcp_tool_result` | Result of an MCP tool execution. |
40 | `agent.custom_tool_use` | Agent invokes one of your custom tools. Respond with a `user.custom_tool_result` event. |
41 | `agent.thread_context_compacted` | Conversation history was compacted to fit the context window. |
42 | `agent.thread_message_received` | In a [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) session, a message from another thread arrived on the thread whose stream carries this event; on the primary thread, an agent sent a report or question to the agent that the session runs. |
43 | `agent.thread_message_sent` | In a [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) session, the thread whose stream carries this event sent a message to another thread; on the primary thread, the agent that the session runs sent a task or follow-up message to another agent. |
4444
4545 Message content in these events can include a `redacted` content block, `{"type": "redacted"}`: a placeholder for content withheld by Anthropic model policy. The block carries no other fields. Redacted blocks appear only in content the platform emits; a user event that includes one is rejected with a 400 error.
4646 </Tab>
4747
4848 <Tab title="Session events">
49 | Type | Description |
50 | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
51 | `session.status_running` | Agent is actively processing. |
52 | `session.status_idle` | Agent finished its current task and is waiting for input. Includes a `stop_reason` indicating why the agent stopped. |
53 | `session.status_rescheduled` | A transient error occurred and the session is retrying automatically. |
54 | `session.status_terminated` | Session ended, either because of an unrecoverable error or because it was archived. |
55 | `session.deleted` | Session was deleted. Terminates any active event stream; no further events are emitted for this session. |
56 | `session.updated` | Session update request changed at least one field. Includes only the fields that changed. Updates apply on the next turn. |
57 | `session.error` | An error occurred during processing. Includes a typed `error` object with a `retry_status`. |
58 | `session.usage` | Snapshot of the session's cumulative usage and tracked list cost. Carries the session's usage totals and an echo of the session's [budget](https://platform.claude.com/docs/en/managed-agents/budgets), or `null` when the session has none. |
59 | `session.thread_created` | A [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) thread was created. It includes `workflow_run_id`: the run's ID for a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads)'s thread, and `null` for any other thread. |
60 | `session.thread_status_running` | A session thread began executing. Every session emits this for its primary thread; in [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) sessions, child-thread transitions are also cross-posted to the primary stream. |
61 | `session.thread_status_idle` | A session thread finished its turn and is awaiting input. Includes `stop_reason`. |
62 | `session.thread_status_rescheduled` | A session thread hit a transient error and is retrying automatically. |
63 | `session.thread_status_terminated` | A session thread terminated and accepts no further input, for example because it was archived or hit an unrecoverable error. An advisor thread also terminates when its consultation ends. The server archives a workflow run's threads itself. |
49 | Type | Description |
50 | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51 | `session.status_running` | Agent is actively processing. |
52 | `session.status_idle` | Agent finished its current task and is waiting for input. Includes a `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`) indicating why the agent stopped. |
53 | `session.status_rescheduled` | A transient error occurred and the session is retrying automatically. |
54 | `session.status_terminated` | Session ended, either because of an unrecoverable error or because it was archived. |
55 | `session.deleted` | Session was deleted. Terminates any active event stream; no further events are emitted for this session. |
56 | `session.updated` | Session update request changed at least one field. Includes only the fields that changed. Updates apply on the next turn. |
57 | `session.error` | An error occurred during processing. Includes a typed `error` (java, php; csharp, go: `Error`) object with a `retry_status` (java, php: `retryStatus`; csharp, go: `RetryStatus`). |
58 | `session.usage` | Snapshot of the session's cumulative usage and tracked list cost. Carries the session's usage totals and an echo of the session's [budget](https://platform.claude.com/docs/en/managed-agents/budgets), or `null` when the session has none. |
59 | `session.thread_created` | A [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) thread was created. It includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`): the run's ID for a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#a-runs-threads)'s thread, and `null` for any other thread. |
60 | `session.thread_status_running` | A session thread began executing. Every session emits this for its primary thread; in [multiagent](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration) sessions, child-thread transitions are also cross-posted to the primary stream. |
61 | `session.thread_status_idle` | A session thread finished its turn and is awaiting input. Includes `stop_reason` (java, php: `stopReason`; csharp, go: `StopReason`). |
62 | `session.thread_status_rescheduled` | A session thread hit a transient error and is retrying automatically. |
63 | `session.thread_status_terminated` | A session thread terminated and accepts no further input, for example because it was archived or hit an unrecoverable error. An advisor thread also terminates when its consultation ends. The server archives a workflow run's threads itself. |
6464
6565 In a session whose agent has [dynamic workflows](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#dynamic-workflows) turned on, these `workflow_run.*` events arrive on the session's stream:
6666
67 | Type | Description |
68 | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69 | `workflow_run.created` | A workflow run was created. Includes `workflow_run_id`, the run's `name` and `description`, and `phases`, the phases declared for the run. A status event follows, though after an interrupt it might not. |
70 | `workflow_run.status_running` | A workflow run is running. Sent when the run starts to execute, which can be a while after `workflow_run.created`, and again when it resumes after a pause at the budget. A resume after an interrupt might not send it. A run that is idle from the start might get `workflow_run.status_idle` first. Includes `workflow_run_id`. |
71 | `workflow_run.status_idle` | A workflow run went idle: it was paused, for example at the session's budget. A pause after an interrupt might not send it. Includes `workflow_run_id`. |
72 | `workflow_run.status_ended` | A workflow run ended. Includes `workflow_run_id` and `result`, whose `type` says how the run ended. |
73 | `workflow_run.error` | An error of a workflow run, or a start that the server refused. A run that ends in error gets it, with the same error, before its `workflow_run.status_ended`. Includes `error` and `workflow_run_id`, which is `null` when no run was created. |
74 | `workflow_run.phase_started` | A workflow run entered one of its phases. Includes `workflow_run_id` and `workflow_run_phase_id`. |
75 | `workflow_run.phase_ended` | A workflow run left a phase. Includes `workflow_run_id`, `workflow_run_phase_id`, and `phase_started_id`. |
67 | Type | Description |
68 | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69 | `workflow_run.created` | A workflow run was created. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), 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 declared for the run. A status event follows, though after an interrupt it might not. |
70 | `workflow_run.status_running` | A workflow run is running. Sent when the run starts to execute, which can be a while after `workflow_run.created`, and again when it resumes after a pause at the budget. A resume after an interrupt might not send it. A run that is idle from the start might get `workflow_run.status_idle` first. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`). |
71 | `workflow_run.status_idle` | A workflow run went idle: it was paused, for example at the session's budget. A pause after an interrupt might not send it. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`). |
72 | `workflow_run.status_ended` | A workflow run ended. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) and `result` (java, php; csharp, go: `Result`), whose `type` (java, php; csharp, go: `Type`) says how the run ended. |
73 | `workflow_run.error` | An error of a workflow run, or a start that the server refused. A run that ends in error gets it, with the same error, before its `workflow_run.status_ended`. Includes `error` (java, php; csharp, go: `Error`) and `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), which is `null` when no run was created. |
74 | `workflow_run.phase_started` | A workflow run entered one of its phases. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`) and `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`). |
75 | `workflow_run.phase_ended` | A workflow run left a phase. Includes `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), `workflow_run_phase_id` (java: `workflowRunPhaseId`; php: `workflowRunPhaseID`; csharp, go: `WorkflowRunPhaseID`), and `phase_started_id` (java: `phaseStartedId`; php: `phaseStartedID`; csharp, go: `PhaseStartedID`). |
7676 </Tab>
7777
7878 <Tab title="Span events">
from line 81
8181 | Type | Description |
8282 | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
8383 | `span.model_request_start` | A model inference call has started. |
84 | `span.model_request_end` | A model inference call has completed. Includes `model_usage` with token counts. |
84 | `span.model_request_end` | A model inference call has completed. Includes `model_usage` (java, php: `modelUsage`; csharp, go: `ModelUsage`) with token counts. |
8585 | `span.outcome_evaluation_start` | [Outcome](https://platform.claude.com/docs/en/managed-agents/define-outcomes) evaluation has started. |
8686 | `span.outcome_evaluation_ongoing` | Heartbeat during an ongoing [outcome](https://platform.claude.com/docs/en/managed-agents/define-outcomes) evaluation. |
8787 | `span.outcome_evaluation_end` | An [outcome](https://platform.claude.com/docs/en/managed-agents/define-outcomes) evaluation cycle has completed. A `needs_revision` result means another cycle follows; `satisfied`, `max_iterations_reached`, `failed`, and `interrupted` are terminal. |
from line 94
9494 </Tab>
9595
9696 <Tab title="Event deltas">
97 Event deltas are stream-only preview events. They are emitted on stream connections (session-level or per-thread) that opt in with the `event_deltas[]` parameter, and they are never persisted to the session's event history. See [Preview responses with event deltas](https://platform.claude.com/docs/en/managed-agents/event-deltas) for opting in, accumulating, and reconciling them.
97 Event deltas are stream-only preview events. They are emitted on stream connections (session-level or per-thread) that opt in with the `event_deltas` (java, php: `eventDeltas`; csharp, go: `EventDeltas`) parameter, and they are never persisted to the session's event history. See [Preview responses with event deltas](https://platform.claude.com/docs/en/managed-agents/event-deltas) for opting in, accumulating, and reconciling them.
9898
99 | Type | Description |
100 | ------------- | ------------------------------------------------------------------------------------------------------------------------ |
101 | `event_start` | A previewed event has started generating. Carries the upcoming event's `type` and `id`. Stream-only and never persisted. |
102 | `event_delta` | Incremental content for a previewed event, identified by `event_id`. Stream-only and never persisted. |
99 | Type | Description |
100 | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
101 | `event_start` | A previewed event has started generating. Carries the upcoming event's `type` (java, php; csharp, go: `Type`) and `id` (java, php; csharp, go: `ID`). Stream-only and never persisted. |
102 | `event_delta` | Incremental content for a previewed event, identified by `event_id` (java: `eventId`; php: `eventID`; csharp, go: `EventID`). Stream-only and never persisted. |
103103 </Tab>
104104</Tabs>
105105
managed-agents/scheduled-deployments Changed · +6 / -6 lines
from line 16
1616
1717## Create a scheduled deployment
1818
19When creating a deployment, you pass the [session configurations](https://platform.claude.com/docs/en/managed-agents/sessions) required for execution, in addition to a `schedule`.
19When creating a deployment, you pass the [session configurations](https://platform.claude.com/docs/en/managed-agents/sessions) required for execution, in addition to a `schedule` (java, php; csharp, go: `Schedule`).
2020
2121* Deployments require [agent configuration](https://platform.claude.com/docs/en/managed-agents/agent-setup) and [environment configuration](https://platform.claude.com/docs/en/managed-agents/environments), and optionally accept [files](https://platform.claude.com/docs/en/managed-agents/files), [GitHub](https://platform.claude.com/docs/en/managed-agents/github), [memory stores](https://platform.claude.com/docs/en/managed-agents/memory), and [vaults](https://platform.claude.com/docs/en/managed-agents/vaults). A deployment that targets a [self-hosted environment](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory) can attach memory stores; `file` and `github_repository` resources require a cloud environment. The Claude Console deployment form does not currently offer memory stores for self-hosted environments; attach them through the API or an SDK instead.
2222* Deployments also require at least one initial event, a `user.message` or `user.define_outcome`, that starts each session's work. In a deployment file for `ant apply`, the text below the frontmatter becomes that `user.message`.
23* In the `schedule`, you define a cron `expression` and a `timezone`. Maximum granularity supported is at the minute level.
23* In the `schedule` (java, php; csharp, go: `Schedule`), you define a cron `expression` (java, php; csharp, go: `Expression`) and a `timezone` (java, php; csharp, go: `Timezone`). Maximum granularity supported is at the minute level.
2424
2525<CodeGroup defaultLanguage="CLI">
2626 ```bash cURL
from line 266
266266
267267### Set a budget on each run
268268
269Pass the optional `budget` object when you create or update the deployment. It takes the same shape as a [session budget](https://platform.claude.com/docs/en/managed-agents/budgets). The deployment copies the cap onto each session it starts, so the budget bounds every run separately rather than acting as a cumulative ceiling across runs: a deployment with a `"2000"` cap can spend up to about $20 on every run.
269Pass the optional `budget` (java, php; csharp, go: `Budget`) object when you create or update the deployment. It takes the same shape as a [session budget](https://platform.claude.com/docs/en/managed-agents/budgets). The deployment copies the cap onto each session it starts, so the budget bounds every run separately rather than acting as a cumulative ceiling across runs: a deployment with a `"2000"` cap can spend up to about $20 on every run.
270270
271A session started by the deployment behaves exactly like any other budgeted session: it pauses with `budget_reached` when its own list cost [reaches the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget). Changing the deployment's budget applies to runs started afterward; a session already running keeps the cap it started with, which you can [change through the session itself](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-session-budget). Unlike a session budget, a deployment's budget can be removed with `"budget": null` and set again later.
271A session started by the deployment behaves exactly like any other budgeted session: it pauses with `budget_reached` when its own list cost [reaches the cap](https://platform.claude.com/docs/en/managed-agents/budgets#when-a-session-reaches-its-budget). Changing the deployment's budget applies to runs started afterward; a session already running keeps the cap it started with, which you can [change through the session itself](https://platform.claude.com/docs/en/managed-agents/session-operations#updating-the-session-budget). Unlike a session budget, a deployment's budget can be removed with `"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`) and set again later.
272272
273273The following example sets a budget on an existing deployment:
274274
from line 408
408408
409409Deployments can fail to trigger for a variety of reasons: for example, if the `environment` resource has been archived, or if session creation is rate-limited. Each attempt at executing a deployment generates a **deployment run** record, allowing you to track successes and failures independent of the session lifecycle.
410410
411Successful deployments generate active sessions, and a successful deployment run contains the associated `session_id`. To follow a session's lifecycle, track the session events through the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) or [webhooks](https://platform.claude.com/docs/en/managed-agents/webhooks). Deployment lifecycle changes and the outcome of each scheduled run are also delivered as webhook events, listed in the Deployment events and Deployment run events tabs of [Supported event types](https://platform.claude.com/docs/en/managed-agents/webhooks#supported-event-types).
411Successful deployments generate active sessions, and a successful deployment run contains the associated `session_id` (java: `sessionId`; php: `sessionID`; csharp, go: `SessionID`). To follow a session's lifecycle, track the session events through the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) or [webhooks](https://platform.claude.com/docs/en/managed-agents/webhooks). Deployment lifecycle changes and the outcome of each scheduled run are also delivered as webhook events, listed in the Deployment events and Deployment run events tabs of [Supported event types](https://platform.claude.com/docs/en/managed-agents/webhooks#supported-event-types).
412412
413413List all deployment runs for a deployment as follows:
414414
managed-agents/self-hosted-sandboxes-memory Changed · +4 / -4 lines
from line 10
1010 betaHeader: managed-agents-2026-04-01
1111---
1212
13Sessions on a self-hosted environment attach [memory stores](https://platform.claude.com/docs/en/managed-agents/memory) exactly as sessions on cloud environments do. List them in `resources` when you create the session, as shown in [Attach a memory store to a session](https://platform.claude.com/docs/en/managed-agents/memory#attach-a-memory-store-to-a-session). A session accepts up to 8 memory stores.
13Sessions on a self-hosted environment attach [memory stores](https://platform.claude.com/docs/en/managed-agents/memory) exactly as sessions on cloud environments do. List them in `resources` (java, php; csharp, go: `Resources`) when you create the session, as shown in [Attach a memory store to a session](https://platform.claude.com/docs/en/managed-agents/memory#attach-a-memory-store-to-a-session). A session accepts up to 8 memory stores.
1414
1515The difference is who materializes the store. On a self-hosted environment your worker, rather than Anthropic's infrastructure, downloads each store into the sandbox and syncs the agent's changes back.
1616
from line 33
3333sudo mkdir -p /mnt/memory && sudo chown "$USER" /mnt/memory
3434```
3535
36Do not create the per-store directories yourself. The worker creates each store's `mount_path` directory (for example, `/mnt/memory/user-preferences`) when a session starts and removes it when the session ends. If something already exists at that path, the worker refuses to start the session's work.
36Do not create the per-store directories yourself. The worker creates each store's `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) directory (for example, `/mnt/memory/user-preferences`) when a session starts and removes it when the session ends. If something already exists at that path, the worker refuses to start the session's work.
3737
3838In the [sandbox-per-session pattern](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#run-one-sandbox-per-session), the sandbox image needs a writable `/mnt/memory`. You don't need to bind-mount the memory directories to the host, because the worker uploads their contents to the store before the sandbox exits.
3939
from line 45
4545
4646When the worker claims a work item whose session has memory stores attached, it:
4747
481. **Downloads each store to its `mount_path`.** This is the same directory under `/mnt/memory/` that cloud sessions use, and the session's system prompt describes it to the agent. For example, a store named "User Preferences" lands at `/mnt/memory/user-preferences/`.
481. **Downloads each store to its `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`).** This is the same directory under `/mnt/memory/` that cloud sessions use, and the session's system prompt describes it to the agent. For example, a store named "User Preferences" lands at `/mnt/memory/user-preferences/`.
49492. **Opens those directories to the file tools.** The agent works on memories with the same file tools it uses in the working directory.
50503. **Reconciles changes after tool calls,** at most once per sync interval (15 seconds by default). Memories that changed in the store are written to disk, and files the agent changed are uploaded to the store.
51514. **Runs a final sync when the session ends.** It flushes any uploads still pending for up to 30 seconds, then removes the directories it created.
from line 79
7979
8080Disable memory support only on workers whose sessions attach no memory stores. A disabled worker neither downloads nor syncs stores, so a session with stores attached runs without them even though its system prompt still describes them.
8181
82While memory support is enabled, a work item that arrives without a `secret` for a session with attached stores fails rather than running without memory. See [Memory stores fail to mount](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#memory-stores-fail-to-mount).
82While memory support is enabled, a work item that arrives without a `secret` (java, php; csharp, go: `Secret`) for a session with attached stores fails rather than running without memory. See [Memory stores fail to mount](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#memory-stores-fail-to-mount).
8383
8484### Deletions
8585
managed-agents/self-hosted-sandboxes-operations Changed · +14 / -14 lines
from line 20
2020
2121`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:
2222
23| Field | Meaning | Use it to |
24| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
25| `depth` | Items waiting to be claimed. | Scale your worker fleet or alert on backlog. |
26| `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` | 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` | Workers that have polled in the last 30 seconds. | Alert on liveness. |
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. |
2929
3030<CodeGroup>
3131 ```bash cURL
from line 319
319319
320320### The worker doesn't connect
321321
322If `workers_polling` stays at 0, the worker isn't reaching the queue. Confirm that `ANTHROPIC_ENVIRONMENT_KEY` and `ANTHROPIC_ENVIRONMENT_ID` are set on the worker host.
322If `workers_polling` (java, php: `workersPolling`; csharp, go: `WorkersPolling`) stays at 0, the worker isn't reaching the queue. Confirm that `ANTHROPIC_ENVIRONMENT_KEY` and `ANTHROPIC_ENVIRONMENT_ID` are set on the worker host.
323323
324324### A session stays queued
325325
326No worker is claiming work. A queued session waits rather than failing. Check `workers_polling` and `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` (java, php; 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` 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` (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. |
340340
341341### A custom tool call never returns
342342
managed-agents/self-hosted-sandboxes-reference Changed · +5 / -5 lines
from line 52
5252
5353## Sandbox filesystem
5454
55| Path | Contents |
56| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57| `/workspace` | The system default working directory for tool execution and skill download. If you use a different working directory, update your agent's system prompt so Claude can locate the skill files. |
58| `<workdir>/skills/<name>/` | The agent's downloaded skills. |
59| `/mnt/memory/<store>/` | One directory per attached memory store, at the store's `mount_path` (for example, `/mnt/memory/user-preferences/`). The worker creates these directories when it claims the session and removes them when the session ends. |
55| Path | Contents |
56| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
57| `/workspace` | The system default working directory for tool execution and skill download. If you use a different working directory, update your agent's system prompt so Claude can locate the skill files. |
58| `<workdir>/skills/<name>/` | The agent's downloaded skills. |
59| `/mnt/memory/<store>/` | One directory per attached memory store, at the store's `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) (for example, `/mnt/memory/user-preferences/`). The worker creates these directories when it claims the session and removes them when the session ends. |
6060
6161On self-hosted environments the session's system prompt omits the `/mnt/session/outputs` instruction used on Anthropic-managed sandboxes. Final deliverables land wherever the agent writes them in your sandbox filesystem, typically under the working directory.
6262
managed-agents/session-operations Changed · +12 / -12 lines
from line 16
1616
1717Sessions progress through these statuses. See [Start a session](https://platform.claude.com/docs/en/managed-agents/sessions) for the session lifecycle.
1818
19| Status | Description |
20| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21| `idle` | Agent is waiting for input, including user messages or tool confirmations. Sessions created without `initial_events` start in `idle`. A session can be `idle` while a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#while-a-run-is-open) is still open, so `idle` alone doesn't mean that the work is done. See [Know when the work is done](https://platform.claude.com/docs/en/managed-agents/workflow-runs#know-when-the-work-is-done). |
22| `running` | Agent is actively executing. |
23| `rescheduling` | Transient error occurred, retrying automatically. |
24| `terminated` | Session has ended, either because of an unrecoverable error or because it was archived. A session that finishes its work goes `idle`, not `terminated`. |
19| Status | Description |
20| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21| `idle` | Agent is waiting for input, including user messages or tool confirmations. Sessions created without `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) start in `idle`. A session can be `idle` while a [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs#while-a-run-is-open) is still open, so `idle` alone doesn't mean that the work is done. See [Know when the work is done](https://platform.claude.com/docs/en/managed-agents/workflow-runs#know-when-the-work-is-done). |
22| `running` | Agent is actively executing. |
23| `rescheduling` | Transient error occurred, retrying automatically. |
24| `terminated` | Session has ended, either because of an unrecoverable error or because it was archived. A session that finishes its work goes `idle`, not `terminated`. |
2525
2626## Updating the agent configuration
2727
28You can update a session's `agent.tools` and `agent.mcp_servers`, 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` and `blocked_domains` apply to the rest of the session.
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.
2929
30Only the agent's `tools` and `mcp_servers` can change after a session is created. To run a session with `model`, `system`, or `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` override when you create it. The agent's configured `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` (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).
3131
32The semantics of a `tools` or `mcp_servers` 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` (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.
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`, and removing it by setting `budget` to `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` 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` (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.
219219
220220## Retrieving a session
221221
managed-agents/session-threads Changed · +19 / -19 lines
from line 18
1818
1919**Session threads** are where you drill into a specific agent's activity.
2020
21The session `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` (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).
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` is `null` for the primary thread. Every other thread is a child thread. `workflow_run_id` 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` 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).
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
109109## Interrupt a session thread
110110
111Send `user.interrupt` with `session_thread_id` to stop a specific thread. Omitting `session_thread_id` interrupts every non-archived thread in the session, including the primary. In a session with dynamic workflows, an interrupt ends no run, and one that names a run's thread stops nothing. An interrupt closes other child threads' pending tool calls, but don't rely on it to close a run thread's. See [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open).
111Send `user.interrupt` with `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) to stop a specific thread. Omitting `session_thread_id` (java: `sessionThreadId`; php: `sessionThreadID`; csharp, go: `SessionThreadID`) interrupts every non-archived thread in the session, including the primary. In a session with dynamic workflows, an interrupt ends no run, and one that names a run's thread stops nothing. An interrupt closes other child threads' pending tool calls, but don't rely on it to close a run thread's. See [Interrupt a session with runs open](https://platform.claude.com/docs/en/managed-agents/workflow-runs#interrupt-a-session-with-runs-open).
112112
113113<CodeGroup>
114114 ```bash cURL
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` and `agent_name`. |
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` 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`, `from_agent_name`, and `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`, `to_agent_name`, and `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` (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`). |
397397
398Advisor consultations emit these same thread events under the reserved name `anthropic.advisor` (as `agent_name` on the thread lifecycle events and `from_agent_name` 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.
398Advisor 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
400400A [workflow run](https://platform.claude.com/docs/en/managed-agents/workflow-runs)'s threads show on the primary stream as follows:
401401
402* **Lifecycle events:** Each run thread sends `session.thread_created`, with the run's `workflow_run_id`, and its `session.thread_status_running`, `session.thread_status_idle`, and `session.thread_status_terminated` events.
402* **Lifecycle events:** Each run thread sends `session.thread_created`, with the run's `workflow_run_id` (java: `workflowRunId`; php: `workflowRunID`; csharp, go: `WorkflowRunID`), and its `session.thread_status_running`, `session.thread_status_idle`, and `session.thread_status_terminated` events.
403403* **Message events:** A run thread's prompt, an `agent.thread_message_received` event, stays on its own stream.
404404* **Run events:** `workflow_run.*` events also arrive on this stream; see [Run events](https://platform.claude.com/docs/en/managed-agents/workflow-runs#run-events).
405405* **Tool calls that wait on you:** A run thread's tool calls that need your client are cross-posted to this stream, as for any child thread. See [Tool permissions and custom tools](https://platform.claude.com/docs/en/managed-agents/session-threads#tool-permissions-and-custom-tools).
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` is the primary thread's ID, and it has no `from_agent_name`. 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 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.
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` 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` (java, php; 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`) or `user.custom_tool_result` (with `custom_tool_use_id`); 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` values. To match the two copies, compare `type` and `tool_use_id` (or `custom_tool_use_id`), not `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` (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`).
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
from line 810
810810 ```
811811</CodeGroup>
812812
813The previous pattern answers the calls that an idle event lists. On the primary stream, a subagent's `session.thread_status_idle` event can arrive before the `agent.tool_use` or `agent.mcp_tool_use` events that its `stop_reason.event_ids` lists. A `user.tool_confirmation` for a call whose event hasn't arrived yet can return 400. To avoid that, answer each call whose [`evaluated_permission`](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated) is `ask` when its own event arrives on the primary stream.
813The previous pattern answers the calls that an idle event lists. On the primary stream, a subagent's `session.thread_status_idle` event can arrive before the `agent.tool_use` or `agent.mcp_tool_use` events that its `stop_reason.event_ids` lists. A `user.tool_confirmation` for a call whose event hasn't arrived yet can return 400. To avoid that, answer each call whose [`evaluated_permission` (java, php: `evaluatedPermission`; csharp, go: `EvaluatedPermission`)](https://platform.claude.com/docs/en/managed-agents/permission-policies#see-how-each-call-was-evaluated) is `ask` when its own event arrives on the primary stream.
814814
managed-agents/sessions Changed · +22 / -22 lines
from line 10
1010 betaHeader: managed-agents-2026-04-01
1111---
1212
13A session is an agent instance within an environment. Each session references an [agent](https://platform.claude.com/docs/en/managed-agents/agent-setup) and an [environment](https://platform.claude.com/docs/en/managed-agents/environments) (both created separately), and maintains conversation history across multiple interactions. Sessions follow a two-step lifecycle: first [create the session](https://platform.claude.com/docs/en/managed-agents/sessions#creating-a-session), then [send a user event](https://platform.claude.com/docs/en/managed-agents/sessions#starting-the-session) to start work. You can also collapse both steps into one call with [`initial_events`](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events).
13A session is an agent instance within an environment. Each session references an [agent](https://platform.claude.com/docs/en/managed-agents/agent-setup) and an [environment](https://platform.claude.com/docs/en/managed-agents/environments) (both created separately), and maintains conversation history across multiple interactions. Sessions follow a two-step lifecycle: first [create the session](https://platform.claude.com/docs/en/managed-agents/sessions#creating-a-session), then [send a user event](https://platform.claude.com/docs/en/managed-agents/sessions#starting-the-session) to start work. You can also collapse both steps into one call with [`initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`)](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events).
1414
1515## Creating a session
1616
17A session requires an `agent` ID and an `environment` ID. Agents are versioned resources; passing in the `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` (java, php; csharp, go: `Agent`) ID as a string creates the session with the latest agent version.
1818
1919<CodeGroup>
2020 ```bash cURL
from line 191
191191
192192### Seed the session with initial events
193193
194You can create a session and start its work in one call. `initial_events` is an optional array of initial [events](https://platform.claude.com/docs/en/managed-agents/reference#event-types) to send to the session at creation, processed in order. It supports `user.message` and [`user.define_outcome`](https://platform.claude.com/docs/en/managed-agents/define-outcomes) events, and accepts a maximum of 50 events. A non-empty list starts the agent loop in the same call: the session is created directly in the `running` status, with no further request.
194You can create a session and start its work in one call. `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) is an optional array of initial [events](https://platform.claude.com/docs/en/managed-agents/reference#event-types) to send to the session at creation, processed in order. It supports `user.message` and [`user.define_outcome`](https://platform.claude.com/docs/en/managed-agents/define-outcomes) events, and accepts a maximum of 50 events. A non-empty list starts the agent loop in the same call: the session is created directly in the `running` status, with no further request.
195195
196The following example creates a session with a single `user.message` in `initial_events`:
196The following example creates a session with a single `user.message` in `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`):
197197
198198<CodeGroup>
199199 ```bash cURL
from line 441
441441 ```
442442</CodeGroup>
443443
444No other event type is accepted. Events that respond to an agent turn (`user.tool_confirmation`, `user.tool_result`, and `user.custom_tool_result`) aren't accepted because no agent turn exists yet, and `user.interrupt` isn't accepted because there is no turn to stop. Unlike `initial_events` on a scheduled deployment, a session's `initial_events` don't accept `system.message`.
444No other event type is accepted. Events that respond to an agent turn (`user.tool_confirmation`, `user.tool_result`, and `user.custom_tool_result`) aren't accepted because no agent turn exists yet, and `user.interrupt` isn't accepted because there is no turn to stop. Unlike `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) on a scheduled deployment, a session's `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) don't accept `system.message`.
445445
446Each event in `initial_events` is validated and persisted before the create response returns, in list order, with a server-assigned ID, exactly as if you had posted it to the [send events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#send-events) endpoint immediately after creation. Per-event content rules are also the same as on that endpoint. An empty list is equivalent to omitting the field. Validation is all-or-nothing: if any event fails validation, the whole request is rejected and no session is created.
446Each event in `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) is validated and persisted before the create response returns, in list order, with a server-assigned ID, exactly as if you had posted it to the [send events](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#send-events) endpoint immediately after creation. Per-event content rules are also the same as on that endpoint. An empty list is equivalent to omitting the field. Validation is all-or-nothing: if any event fails validation, the whole request is rejected and no session is created.
447447
448448The create request is rejected in the following cases:
449449
from line 454
454454| More than 100 file-sourced [`document` content blocks](https://platform.claude.com/docs/en/build-with-claude/files#document-blocks) across the whole list | 400 |
455455| A request body over 32 MB | 413 |
456456
457A `user.define_outcome` event in `initial_events` is accepted under the same conditions as sending one to an existing session; see [Define outcomes](https://platform.claude.com/docs/en/managed-agents/define-outcomes).
457A `user.define_outcome` event in `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) is accepted under the same conditions as sending one to an existing session; see [Define outcomes](https://platform.claude.com/docs/en/managed-agents/define-outcomes).
458458
459459### Override agent configuration for a session
460460
461You can pass `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` and optionally a `version` (omit `version` to use the agent's latest version). Then include any of `model`, `system`, `tools`, `mcp_servers`, or `skills` with the values the session should use.
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.
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` and `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` (java, php; csharp, go: `System`; ruby: `system_`) and `skills` (java, php; 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` is non-empty, because skills require the `read` tool. Otherwise, `tools: null` and `tools: []` clear the field.
471 * Clearing `mcp_servers` returns a 400 error when the session's effective `tools` still contains an `mcp_toolset` that references one of the agent's servers. Override `tools` in the same request to remove those `mcp_toolset` entries, then clear `mcp_servers`.
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`).
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` override must list every tool the session should have. Likewise, a `model` override replaces the agent's `model` object in full, so the agent's own `effort` isn't carried over. To run the session at a specific effort level, set `effort` inside the override's `model` object. A level the model doesn't support returns a 400 error, and a `model` override without `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` (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.
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` object reflects the configuration the session runs with after the overrides are applied. Its `id` and `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` (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.
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` override replaces the agent's `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` 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` (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.
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` in the `model` override, and prints the value echoed in the response's `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` (java, php; csharp, go: `Model`) override, and prints the value echoed in the response's `agent.model` (java, php; 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` 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`. Set `type` to `limit` and give `max_list_cost` an `amount` and a `currency`. `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` (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.
804804
805805The following example creates a session with a $1.25 budget:
806806
from line 933
933933
934934## MCP authentication through vaults
935935
936If your agent uses MCP tools that require authentication, pass `vault_ids` at session creation to reference a vault containing stored OAuth credentials. Anthropic manages token refresh on your behalf. See [Authenticate with vaults](https://platform.claude.com/docs/en/managed-agents/vaults) for how to create vaults and register credentials.
936If your agent uses MCP tools that require authentication, pass `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) at session creation to reference a vault containing stored OAuth credentials. Anthropic manages token refresh on your behalf. See [Authenticate with vaults](https://platform.claude.com/docs/en/managed-agents/vaults) for how to create vaults and register credentials.
937937
938938<CodeGroup>
939939 ```bash cURL
from line 1025
10251025
10261026## Starting the session
10271027
1028Creating a session without `initial_events` registers the session but does not start any work; the environment's sandbox begins provisioning as soon as the session is created, so the first tool call does not wait on it. To delegate a task, send events to the session using a [user event](https://platform.claude.com/docs/en/managed-agents/reference#event-types). To supply the first event in the create request instead, see [Seed the session with initial events](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events). The session acts as a state machine that tracks progress while events drive the actual execution.
1028Creating a session without `initial_events` (java, php: `initialEvents`; csharp, go: `InitialEvents`) registers the session but does not start any work; the environment's sandbox begins provisioning as soon as the session is created, so the first tool call does not wait on it. To delegate a task, send events to the session using a [user event](https://platform.claude.com/docs/en/managed-agents/reference#event-types). To supply the first event in the create request instead, see [Seed the session with initial events](https://platform.claude.com/docs/en/managed-agents/sessions#seed-the-session-with-initial-events). The session acts as a state machine that tracks progress while events drive the actual execution.
10291029
10301030<CodeGroup>
10311031 ```bash cURL
managed-agents/skills Changed · +16 / -16 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` 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` (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.
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 23
2323
2424A custom skill is a directory containing a `SKILL.md` file plus any supporting files, uploaded to your workspace as a zip archive or as individual files. Creating the skill returns the `skill_*` ID you reference when attaching it to an agent. Anthropic pre-built skills are already available in every workspace and don't require this step. To use only pre-built skills, skip to [Attach skills to an agent](https://platform.claude.com/docs/en/managed-agents/skills#attach-skills-to-an-agent).
2525
26These examples omit the optional `display_name` field, so the skill's display name is derived from the `name` field in `SKILL.md`. An explicit `display_name` can be up to 255 characters and doesn't need to be unique within your workspace.
26These examples omit the optional `display_name` (java, php: `displayName`; csharp, go: `DisplayName`) field, so the skill's display name is derived from the `name` field in `SKILL.md`. An explicit `display_name` (java, php: `displayName`; csharp, go: `DisplayName`) can be up to 255 characters and doesn't need to be unique within your workspace.
2727
2828<CodeGroup defaultLanguage="CLI">
2929 ```bash cURL
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` array uses the following fields:
211Each entry in the `skills` (java, php; csharp, go: `Skills`) array uses the following fields:
212212
213| Field | Description |
214| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
215| `type` | Either `anthropic` for pre-built skills or `custom` for workspace-authored skills. |
216| `skill_id` | 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` | Pin to a specific version or use `latest`. Optional. Defaults to `latest` when omitted. Applies to both Anthropic and custom skills. |
213| Field | Description |
214| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
215| `type` (java, php; csharp, go: `Type`) | Either `anthropic` for pre-built skills or `custom` for workspace-authored skills. |
216| `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. |
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` 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` (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.
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 429
429429
430430Repository skills use the same `SKILL.md` format as the custom skills you upload. For the format and authoring guidance, see [Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) and [Skill authoring best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices).
431431
432To load skills from a repository, create a session that mounts it. This is the same request shown in [Accessing GitHub](https://platform.claude.com/docs/en/managed-agents/github#token-permissions); `mount_path` is optional and defaults to `/workspace/<repo-name>`:
432To load skills from a repository, create a session that mounts it. This is the same request shown in [Accessing GitHub](https://platform.claude.com/docs/en/managed-agents/github#token-permissions); `mount_path` (java, php: `mountPath`; csharp, go: `MountPath`) is optional and defaults to `/workspace/<repo-name>`:
433433
434434<CodeGroup>
435435 ```bash cURL
from line 581
581581 ```
582582</CodeGroup>
583583
584For private repositories, the resource's `authorization_token` 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).
584For 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` 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` (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.
587587
588Repository skills work alongside skills attached through the agent's `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` (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.
589589
590590## Next steps
591591
managed-agents/tools Changed · +9 / -9 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` array to disable specific tools or override their settings. Each entry is identified by its `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` field with the same value.
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.
3737
38Each config entry can also set a `permission_policy`. 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.
38Each 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
4040The following example enables the toolset and disables `web_fetch`:
4141
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` entry per tool. The type is a union with one member per built-in tool, discriminated by `type`.
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`).
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` 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` (java, php; csharp, go: `Configs`) is the union itself, so build each entry from its per-tool member type.
246246
247You can omit `type` when you construct an entry, because the server infers it from `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` (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`.
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` 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 `subagents.predefined_agents`, or on an agent in `workflows.predefined_agents`. 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` (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.
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 · +26 / -26 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` 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` (java, php; csharp, go: `Configs`) entries takes one of two lists:
1414
15* **`allowed_domains`:** The tool can reach only these hosts.
16* **`blocked_domains`:** The tool can never reach these hosts.
15* **`allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`):** The tool can reach only these hosts.
16* **`blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`):** The tool can never reach these hosts.
1717
1818Each tool carries its own list, so `web_search` and `web_fetch` can have different restrictions.
1919
2020<Note>
21 `web_search` and `web_fetch` run on Anthropic's servers, not in the sandbox. A cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking) also applies its `allowed_hosts` to them; see [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent). `unrestricted` networking and self-hosted environments do not limit them. The per-tool lists restrict these tools further. Organization-level web search and web fetch settings in the Claude Console apply to the Messages API. They do not apply to Managed Agents sessions.
21 `web_search` and `web_fetch` run on Anthropic's servers, not in the sandbox. A cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking) also applies its `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) to them; see [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent). `unrestricted` networking and self-hosted environments do not limit them. The per-tool lists restrict these tools further. Organization-level web search and web fetch settings in the Claude Console apply to the Messages API. They do not apply to Managed Agents sessions.
2222</Note>
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` and `max_content_tokens`, which [Settings](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#settings) describes. The example then prints the `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` (java, php; csharp, go: `Configs`) array from the response.
2727
2828<CodeGroup defaultLanguage="CLI">
2929 ```bash cURL
from line 370
370370 ```
371371</CodeGroup>
372372
373In a cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), the environment's `allowed_hosts` also applies to `web_search` and `web_fetch`. Creating a session fails with a 400 error when an enabled web tool's `allowed_domains` has an entry that is not within `allowed_hosts`. So does a session update that adds such an entry. To fix it, add the host to `allowed_hosts` or remove the entry from `allowed_domains`. At runtime, a `web_fetch` call for a URL on a host that `allowed_hosts` does not match returns a `url_not_allowed` error result. `web_search` omits results from such hosts. The two lists match differently: a tool's entry covers its subdomains, but an `allowed_hosts` entry matches one exact host unless it starts with `*.`. For example, the tool entry `docs.example.com` is not within an `allowed_hosts` of `["example.com"]`, but it is within `["docs.example.com"]` or `["*.example.com"]`.
373In a cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), the environment's `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) also applies to `web_search` and `web_fetch`. Creating a session fails with a 400 error when an enabled web tool's `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) has an entry that is not within `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). So does a session update that adds such an entry. To fix it, add the host to `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) or remove the entry from `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`). At runtime, a `web_fetch` call for a URL on a host that `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) does not match returns a `url_not_allowed` error result. `web_search` omits results from such hosts. The two lists match differently: a tool's entry covers its subdomains, but an `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) entry matches one exact host unless it starts with `*.`. For example, the tool entry `docs.example.com` is not within an `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) of `["example.com"]`, but it is within `["docs.example.com"]` or `["*.example.com"]`.
374374
375375In the Claude Console, set allowed or blocked domains from the `web_search` and `web_fetch` rows of the **Built-in tools** card on the agent form. Set `max_content_tokens` and `user_location` in the **Raw** view of the agent's configuration.
376376
377377## Settings
378378
379In addition to `enabled` and `permission_policy`, the web tool entries accept the following settings:
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:
380380
381| Setting | Applies to | Description |
382| -------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
383| `allowed_domains` | `web_search`, `web_fetch` | The only hosts the tool can reach. See [Domain list rules](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules). |
384| `blocked_domains` | `web_search`, `web_fetch` | Hosts the tool cannot reach. See [Domain list rules](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules). |
385| `max_content_tokens` | `web_fetch` | Caps the amount of fetched page content included in the context. Must be a positive integer. See [content limits](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#content-limits). |
386| `user_location` | `web_search` | Localizes search results. An object with the same fields as the Messages API [`user_location`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool#localization) parameter. |
381| Setting | Applies to | Description |
382| ------------------------------------------------------------------------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
383| `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) | `web_search`, `web_fetch` | The only hosts the tool can reach. See [Domain list rules](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules). |
384| `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) | `web_search`, `web_fetch` | Hosts the tool cannot reach. See [Domain list rules](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#domain-list-rules). |
385| `max_content_tokens` (java, php: `maxContentTokens`; csharp, go: `MaxContentTokens`) | `web_fetch` | Caps the amount of fetched page content included in the context. Must be a positive integer. See [content limits](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#content-limits). |
386| `user_location` (java, php: `userLocation`; csharp, go: `UserLocation`) | `web_search` | Localizes search results. An object with the same fields as the Messages API [`user_location`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool#localization) parameter. |
387387
388388For how the SDKs type these entries, see [Config entry types in the SDKs](https://platform.claude.com/docs/en/managed-agents/tools#config-entry-types-in-the-sdks).
389389
from line 393
393393
394394## Domain list rules
395395
396These rules apply to `allowed_domains` and `blocked_domains` alike. A request that breaks one is rejected, as [Validation errors](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#validation-errors) describes.
396These rules apply to `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) alike. A request that breaks one is rejected, as [Validation errors](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#validation-errors) describes.
397397
398* **One list per entry:** Set either `allowed_domains` or `blocked_domains` on an entry, not both.
398* **One list per entry:** Set either `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) or `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) on an entry, not both.
399399* **List size:** Each list holds 1 to 64 domains, each 1 to 255 characters.
400400* **No empty lists:** To apply no restriction, omit the field or send `null`.
401401* **No duplicates:** A domain can appear only once in a list. `www.example.com` and `example.com` count as different domains.
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`.
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`).
437437
438438Format and limit violations are rejected with a 400 `invalid_request_error`:
439439
from line 445
445445
446446On the same requests, the API also rejects three settings that depend on the search and fetch providers:
447447
448* A domain in `allowed_domains` that Anthropic's crawler is not permitted to access.
448* A domain in `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) that Anthropic's crawler is not permitted to access.
449449* A `user_location.country` that the search provider does not support. The message ends in `user_location.country: not a country the search provider supports`.
450450* A `user_location.timezone` that is not a valid IANA name.
451451
452In a cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), session create and update also check `allowed_domains` against the environment's `allowed_hosts`. See the rule in [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent).
452In a cloud environment with `limited` [networking](https://platform.claude.com/docs/en/managed-agents/environments#networking), session create and update also check `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) against the environment's `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`). See the rule in [Set domain lists on an agent](https://platform.claude.com/docs/en/managed-agents/tools-web-restrictions#set-domain-lists-on-an-agent).
453453
454454### When an accepted setting is no longer valid
455455
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 `subagents.predefined_agents` 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` (java, php; 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 `subagents.predefined_agents` 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` (java, php; 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 `subagents.predefined_agents`, 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` (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.
496496
497497## Differences from the Messages API tools
498498
499These settings use the same `allowed_domains` and `blocked_domains` fields as [domain filtering](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#domain-filtering) on the Messages API server tools. Managed Agents differs in four ways:
499These settings use the same `allowed_domains` (java, php: `allowedDomains`; csharp, go: `AllowedDomains`) and `blocked_domains` (java, php: `blockedDomains`; csharp, go: `BlockedDomains`) fields as [domain filtering](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#domain-filtering) on the Messages API server tools. Managed Agents differs in four ways:
500500
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`, `citations`, and `cache_control` are not available on the toolset.
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.
505505
506506## Next steps
507507
managed-agents/vaults Changed · +23 / -23 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` and optionally tag it with `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` (java, php; csharp, go: `Metadata`) so you can map it back to your own user records.
2424
2525<CodeGroup>
2626 ```bash cURL
from line 133
133133
134134Two credential categories are supported:
135135
136* **MCP credentials** (`mcp_oauth`, `static_bearer`): each credential is keyed by an `mcp_server_url`. When the agent connects to a server at that URL at session runtime, the token is injected automatically.
137* **Environment variables** (`environment_variable`): each credential is keyed by a `secret_name` (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.
136* **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.
137* **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`, `access_token`, `refresh_token`, `client_secret`, `secret_value`) are treated as sensitive, write-only fields and never returned in API responses.
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.
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` 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` (java, php; 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 363
363363 ```
364364 </CodeGroup>
365365
366 Set `refresh.token_endpoint` to the token endpoint of the OAuth flow that issued the refresh token, because Anthropic sends every refresh request to that URL and the field can't be changed after the credential is created.
366 Set `refresh.token_endpoint` (java, php: `refresh.tokenEndpoint`; csharp, go: `Refresh.TokenEndpoint`) to the token endpoint of the OAuth flow that issued the refresh token, because Anthropic sends every refresh request to that URL and the field can't be changed after the credential is created.
367367 </Tab>
368368
369369 <Tab title="MCP static bearer">
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 `networking.allowed_hosts` array 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` (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.
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 `networking.allowed_hosts` 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`) for a secret-substituted request to succeed.
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.
501501 </Note>
502502
503 The optional `injection_location` field scopes where the secret is substituted; the full semantics follow the example.
503 The optional `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) field scopes where the secret is substituted; the full semantics follow the example.
504504
505505 <CodeGroup>
506506 ```bash cURL
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` 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` (java, php; csharp, go: `Header`) is the narrower configuration. It scopes substitution to request header values for that credential.
701701
702 The credential's `injection_location` controls which parts of an outbound request the secret is substituted into. It is an optional object, a sibling of `networking`, with two Boolean fields: `header` (request headers) and `body` (request body). `injection_location` is independent of `networking.allowed_hosts`: `allowed_hosts` scopes which hosts the secret is substituted for, and `injection_location` 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` (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.
703703
704704 `injection_location` behaves differently on create and on update:
705705
from line 708
708708 | Create credential | If you provide the object, any field you omit inside it defaults to `false`: `{"header": true}` creates a header-only credential. Omit the object entirely and both locations are enabled. |
709709 | Update credential | Fields merge individually: `{"body": false}` disables body substitution and leaves `header` unchanged. |
710710
711 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` object or for either field also returns a 400 error ("omit the field instead"). The response always returns both fields with their resolved values.
711 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 credential's `networking.allowed_hosts`.
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`).
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}}`.
717717 </Note>
718718
719 The substitution happens at egress, not inside the sandbox. Anything that processes the credential locally sees the opaque placeholder, not the real value: clients that validate the credential format at startup may reject it, and clients that compute a request signature from the secret (for example, AWS SigV4) produce an invalid signature. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, in a location the credential's `injection_location` enables.
719 The substitution happens at egress, not inside the sandbox. Anything that processes the credential locally sees the opaque placeholder, not the real value: clients that validate the credential format at startup may reject it, and clients that compute a request signature from the secret (for example, AWS SigV4) produce an invalid signature. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, in a location the credential's `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) enables.
720720
721721 Substitution is outbound only. If a client uses the stored secret to fetch a session token (for example, an OAuth client-credentials grant), the returned token arrives in the sandbox unredacted. For exchange-based flows, perform the exchange yourself and store the resulting token in the vault instead.
722722
from line 730
730730
731731Constraints:
732732
733* **Unique key per vault.** `mcp_server_url` (MCP credentials) and `secret_name` (environment variable credentials) must be unique among active credentials in a vault. Creating a duplicate returns a 409.
734* **Keys are immutable.** To change `mcp_server_url` or `secret_name`, archive the credential and create a new one.
733* **Unique key per vault.** `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) (MCP credentials) and `secret_name` (java, php: `secretName`; csharp, go: `SecretName`) (environment variable credentials) must be unique among active credentials in a vault. Creating a duplicate returns a 409.
734* **Keys are immutable.** To change `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) or `secret_name` (java, php: `secretName`; csharp, go: `SecretName`), archive the credential and create a new one.
735735* **Maximum 20 credentials per vault.**
736736
737737## Reference the vault at session creation
738738
739Pass `vault_ids` when creating a session:
739Pass `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) when creating a session:
740740
741741<CodeGroup>
742742 ```bash cURL
from line 835
835835
836836Runtime behavior:
837837
838* When no MCP credential matches by `mcp_server_url`, the connection is attempted unauthenticated and will error if the server requires authentication.
838* When no MCP credential matches by `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`), the connection is attempted unauthenticated and will error if the server requires authentication.
839839* When multiple vaults contain a matching credential, the first vault with a match wins.
840840* In [multiagent sessions](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), vault credentials apply to every thread. An agent whose own definition declares the matching MCP server authenticates with these credentials. See [Connect agents to MCP servers](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#connect-agents-to-mcp-servers).
841841
842842## Rotate a credential
843843
844Secret values, `display_name`, and (on environment variable credentials) `injection_location` can be updated. `injection_location` updates merge per field, as described in the Environment variable tab of [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential). For a running session, an `injection_location` update propagates the same way as a secret rotation: the session's credentials are re-resolved without a restart, as described in [Credential lifecycle](https://platform.claude.com/docs/en/managed-agents/vaults#credential-lifecycle), and the updated locations apply to the session's subsequent outbound requests. Structural fields (`mcp_server_url`, `secret_name`, `token_endpoint`, `client_id`) are locked after creation. To change them, archive the credential and create a new one.
844Secret values, `display_name` (java, php: `displayName`; csharp, go: `DisplayName`), and (on environment variable credentials) `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) can be updated. `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) updates merge per field, as described in the Environment variable tab of [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential). For a running session, an `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) update propagates the same way as a secret rotation: the session's credentials are re-resolved without a restart, as described in [Credential lifecycle](https://platform.claude.com/docs/en/managed-agents/vaults#credential-lifecycle), and the updated locations apply to the session's subsequent outbound requests. Structural fields (`mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`), `secret_name` (java, php: `secretName`; csharp, go: `SecretName`), `token_endpoint` (java, php: `tokenEndpoint`; csharp, go: `TokenEndpoint`), `client_id` (java: `clientId`; php: `clientID`; csharp, go: `ClientID`)) are locked after creation. To change them, archive the credential and create a new one.
845845
846846<CodeGroup>
847847 ```bash cURL
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` tells you what to do next:
1005The top-level `status` (java, php; 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.