Follow Discord
Sweep 02 Oct 2026 · 18:55Z Build v2.1.288 509 read Stable v2.1.285 Latest v2.1.288 Next v2.1.288 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · api

One read of Claude Developer Platformapi-20261002T143715Z

19 pages moved out of 753 read.

Pages moved 19 significant first
Pages read 753 in this capture
Captured 14:37 UTC
Corpus hash 900364e827b1 corpus-hash

What this read moved

1-19 of 19

api/claude-platform-on-aws-iam-actions Changed · +122 / -116 lines

from line 23
2323 
2424## Actions
2525 
26The service defines 71 actions. Actions follow the AWS `VerbNoun` convention and use verb discipline so that `Get*` and `List*` wildcards produce a clean read-only boundary.
26The service defines 72 actions. Actions follow the AWS `VerbNoun` convention and use verb discipline so that `Get*` and `List*` wildcards produce a clean read-only boundary.
2727 
2828### Inference
2929 
from line 192
192192 
193193### User profiles
194194 
195| Action | Routes authorized |
196| ------------------- | ----------------------------- |
197| `CreateUserProfile` | `POST /v1/user_profiles` |
198| `GetUserProfile` | `GET /v1/user_profiles/{id}` |
199| `ListUserProfiles` | `GET /v1/user_profiles` |
200| `UpdateUserProfile` | `POST /v1/user_profiles/{id}` |
195| Action | Routes authorized |
196| -------------------------------- | -------------------------------------------- |
197| `CreateUserProfile` | `POST /v1/user_profiles` |
198| `GetUserProfile` | `GET /v1/user_profiles/{id}` |
199| `ListUserProfiles` | `GET /v1/user_profiles` |
200| `UpdateUserProfile` | `POST /v1/user_profiles/{id}` |
201| `CreateUserProfileEnrollmentUrl` | `POST /v1/user_profiles/{id}/enrollment_url` |
201202 
203<Note>
204 The user profile actions are account-scoped, like `ListWorkspaces`. A statement whose `Resource` is a workspace ARN does not grant them; use `Resource: "*"`.
205</Note>
206 
202207<Warning>
203208 IAM action matching is case-insensitive. The wildcard `aws-external-anthropic:*File` matches `CreateFile`, `GetFile`, and `DeleteFile`, but does not match `ListFiles` (which ends in "files", not "file"). It also over-matches `CreateUserProfile`, `GetUserProfile`, and `UpdateUserProfile` because "Profile" ends in "file". If you intend to grant or deny only Files API actions, enumerate them explicitly (`CreateFile`, `GetFile`, `ListFiles`, `DeleteFile`) rather than using a `*File` suffix pattern.
204209</Warning>
from line 270
265270 
266271The following table lists every route on Claude Platform on AWS and the IAM action required to call it. Each IAM action also authorizes requests that use the `anthropic-beta` header; beta variants of a route do not require a separate IAM action. CloudTrail classifies each action as either a Data event (high-volume, data-plane operations) or a Management event (control-plane operations). Vault and webhook actions are classified as Management events because they hold secrets (vault credentials and webhook signing secrets) and benefit from default-on audit logging. Workspace, external key, and compliance actions are also classified as Management events because they are organization-scoped control-plane operations. All other actions, including inference, batch, model, file, skill, user profile, and the remaining Claude Managed Agents actions, are classified as Data events.
267272 
268| Method | Route | IAM action | CloudTrail event type |
269| -------- | ---------------------------------------------------- | -------------------------- | --------------------- |
270| `POST` | `/v1/messages` | `CreateInference` | Data |
271| `POST` | `/v1/messages/count_tokens` | `CountTokens` | Data |
272| `POST` | `/v1/messages/batches` | `CreateBatchInference` | Data |
273| `GET` | `/v1/messages/batches` | `ListBatchInferences` | Data |
274| `GET` | `/v1/messages/batches/{id}` | `GetBatchInference` | Data |
275| `GET` | `/v1/messages/batches/{id}/results` | `GetBatchInference` | Data |
276| `POST` | `/v1/messages/batches/{id}/cancel` | `CancelBatchInference` | Data |
277| `DELETE` | `/v1/messages/batches/{id}` | `DeleteBatchInference` | Data |
278| `GET` | `/v1/models` | `ListModels` | Data |
279| `GET` | `/v1/models/{id}` | `GetModel` | Data |
280| `POST` | `/v1/files` | `CreateFile` | Data |
281| `GET` | `/v1/files` | `ListFiles` | Data |
282| `GET` | `/v1/files/{id}` | `GetFile` | Data |
283| `GET` | `/v1/files/{id}/content` | `GetFile` | Data |
284| `DELETE` | `/v1/files/{id}` | `DeleteFile` | Data |
285| `POST` | `/v1/skills` | `CreateSkill` | Data |
286| `GET` | `/v1/skills` | `ListSkills` | Data |
287| `GET` | `/v1/skills/{id}` | `GetSkill` | Data |
288| `DELETE` | `/v1/skills/{id}` | `DeleteSkill` | Data |
289| `POST` | `/v1/skills/{id}/versions` | `UpdateSkill` | Data |
290| `GET` | `/v1/skills/{id}/versions` | `GetSkill` | Data |
291| `GET` | `/v1/skills/{id}/versions/{version}` | `GetSkill` | Data |
292| `GET` | `/v1/skills/{id}/versions/{version}/content` | `GetSkill` | Data |
293| `DELETE` | `/v1/skills/{id}/versions/{version}` | `UpdateSkill` | Data |
294| `POST` | `/v1/user_profiles` | `CreateUserProfile` | Data |
295| `GET` | `/v1/user_profiles` | `ListUserProfiles` | Data |
296| `GET` | `/v1/user_profiles/{id}` | `GetUserProfile` | Data |
297| `POST` | `/v1/user_profiles/{id}` | `UpdateUserProfile` | Data |
298| `POST` | `/v1/organizations/workspaces` | `CreateWorkspace` | Management |
299| `GET` | `/v1/organizations/workspaces` | `ListWorkspaces` | Management |
300| `GET` | `/v1/organizations/workspaces/{id}` | `GetWorkspace` | Management |
301| `POST` | `/v1/organizations/workspaces/{id}` | `UpdateWorkspace` | Management |
302| `POST` | `/v1/organizations/workspaces/{id}/archive` | `ArchiveWorkspace` | Management |
303| `POST` | `/v1/organizations/external_keys` | `RegisterKey` | Management |
304| `GET` | `/v1/organizations/external_keys` | `ListKeys` | Management |
305| `GET` | `/v1/organizations/external_keys/{id}` | `GetKey` | Management |
306| `POST` | `/v1/organizations/external_keys/{id}` | `UpdateKey` | Management |
307| `DELETE` | `/v1/organizations/external_keys/{id}` | `DisableKey` | Management |
308| `GET` | `/v1/compliance/activities` | `ListComplianceActivities` | Management |
309| `POST` | `/v1/agents` | `CreateAgent` | Data |
310| `GET` | `/v1/agents` | `ListAgents` | Data |
311| `GET` | `/v1/agents/{id}` | `GetAgent` | Data |
312| `POST` | `/v1/agents/{id}` | `UpdateAgent` | Data |
313| `POST` | `/v1/agents/{id}/archive` | `ArchiveAgent` | Data |
314| `GET` | `/v1/agents/{id}/versions` | `GetAgent` | Data |
315| `POST` | `/v1/sessions` | `CreateSession` | Data |
316| `GET` | `/v1/sessions` | `ListSessions` | Data |
317| `GET` | `/v1/sessions/{id}` | `GetSession` | Data |
318| `POST` | `/v1/sessions/{id}` | `UpdateSession` | Data |
319| `POST` | `/v1/sessions/{id}/archive` | `ArchiveSession` | Data |
320| `DELETE` | `/v1/sessions/{id}` | `DeleteSession` | Data |
321| `GET` | `/v1/sessions/{id}/events` | `GetSession` | Data |
322| `POST` | `/v1/sessions/{id}/events` | `UpdateSession` | Data |
323| `GET` | `/v1/sessions/{id}/events/stream` | `GetSession` | Data |
324| `GET` | `/v1/sessions/{id}/resources` | `GetSession` | Data |
325| `GET` | `/v1/sessions/{id}/resources/{id}` | `GetSession` | Data |
326| `POST` | `/v1/sessions/{id}/resources` | `UpdateSession` | Data |
327| `POST` | `/v1/sessions/{id}/resources/{id}` | `UpdateSession` | Data |
328| `DELETE` | `/v1/sessions/{id}/resources/{id}` | `UpdateSession` | Data |
329| `POST` | `/v1/environments` | `CreateEnvironment` | Data |
330| `GET` | `/v1/environments` | `ListEnvironments` | Data |
331| `GET` | `/v1/environments/{id}` | `GetEnvironment` | Data |
332| `POST` | `/v1/environments/{id}` | `UpdateEnvironment` | Data |
333| `POST` | `/v1/environments/{id}/archive` | `ArchiveEnvironment` | Data |
334| `DELETE` | `/v1/environments/{id}` | `DeleteEnvironment` | Data |
335| `GET` | `/v1/environments/{id}/work` | `GetEnvironment` | Data |
336| `GET` | `/v1/environments/{id}/work/poll` | `ProcessEnvironmentWork` | Data |
337| `GET` | `/v1/environments/{id}/work/{work_id}` | `GetEnvironment` | Data |
338| `GET` | `/v1/environments/{id}/work/stats` | `GetEnvironment` | Data |
339| `POST` | `/v1/environments/{id}/work/{work_id}` | `ProcessEnvironmentWork` | Data |
340| `POST` | `/v1/environments/{id}/work/{work_id}/ack` | `ProcessEnvironmentWork` | Data |
341| `POST` | `/v1/environments/{id}/work/{work_id}/heartbeat` | `ProcessEnvironmentWork` | Data |
342| `POST` | `/v1/environments/{id}/work/{work_id}/stop` | `ProcessEnvironmentWork` | Data |
343| `POST` | `/v1/vaults` | `CreateVault` | Management |
344| `GET` | `/v1/vaults` | `ListVaults` | Management |
345| `GET` | `/v1/vaults/{id}` | `GetVault` | Management |
346| `POST` | `/v1/vaults/{id}` | `UpdateVault` | Management |
347| `POST` | `/v1/vaults/{id}/archive` | `ArchiveVault` | Management |
348| `DELETE` | `/v1/vaults/{id}` | `DeleteVault` | Management |
349| `GET` | `/v1/vaults/{id}/credentials` | `GetVault` | Management |
350| `POST` | `/v1/vaults/{id}/credentials` | `UpdateVault` | Management |
351| `GET` | `/v1/vaults/{id}/credentials/{id}` | `GetVault` | Management |
352| `POST` | `/v1/vaults/{id}/credentials/{id}` | `UpdateVault` | Management |
353| `POST` | `/v1/vaults/{id}/credentials/{id}/archive` | `UpdateVault` | Management |
354| `DELETE` | `/v1/vaults/{id}/credentials/{id}` | `UpdateVault` | Management |
355| `POST` | `/v1/memory_stores` | `CreateMemoryStore` | Data |
356| `GET` | `/v1/memory_stores` | `ListMemoryStores` | Data |
357| `GET` | `/v1/memory_stores/{id}` | `GetMemoryStore` | Data |
358| `POST` | `/v1/memory_stores/{id}` | `UpdateMemoryStore` | Data |
359| `POST` | `/v1/memory_stores/{id}/archive` | `ArchiveMemoryStore` | Data |
360| `DELETE` | `/v1/memory_stores/{id}` | `DeleteMemoryStore` | Data |
361| `POST` | `/v1/memory_stores/{id}/memories` | `UpdateMemoryStore` | Data |
362| `GET` | `/v1/memory_stores/{id}/memories` | `GetMemoryStore` | Data |
363| `GET` | `/v1/memory_stores/{id}/memories/{id}` | `GetMemoryStore` | Data |
364| `POST` | `/v1/memory_stores/{id}/memories/{id}` | `UpdateMemoryStore` | Data |
365| `DELETE` | `/v1/memory_stores/{id}/memories/{id}` | `UpdateMemoryStore` | Data |
366| `GET` | `/v1/memory_stores/{id}/memory_versions` | `GetMemoryStore` | Data |
367| `GET` | `/v1/memory_stores/{id}/memory_versions/{id}` | `GetMemoryStore` | Data |
368| `POST` | `/v1/memory_stores/{id}/memory_versions/{id}/redact` | `UpdateMemoryStore` | Data |
369| `GET` | `/v1/webhooks` | `ListWebhooks` | Management |
370| `GET` | `/v1/webhooks/{id}` | `GetWebhook` | Management |
371| `POST` | `/v1/webhooks` | `CreateWebhook` | Management |
372| `POST` | `/v1/webhooks/{id}` | `UpdateWebhook` | Management |
373| `DELETE` | `/v1/webhooks/{id}` | `DeleteWebhook` | Management |
374| `POST` | `/v1/webhooks/{id}/regenerate_signing_secret` | `RotateWebhookSecret` | Management |
273| Method | Route | IAM action | CloudTrail event type |
274| -------- | ---------------------------------------------------- | -------------------------------- | --------------------- |
275| `POST` | `/v1/messages` | `CreateInference` | Data |
276| `POST` | `/v1/messages/count_tokens` | `CountTokens` | Data |
277| `POST` | `/v1/messages/batches` | `CreateBatchInference` | Data |
278| `GET` | `/v1/messages/batches` | `ListBatchInferences` | Data |
279| `GET` | `/v1/messages/batches/{id}` | `GetBatchInference` | Data |
280| `GET` | `/v1/messages/batches/{id}/results` | `GetBatchInference` | Data |
281| `POST` | `/v1/messages/batches/{id}/cancel` | `CancelBatchInference` | Data |
282| `DELETE` | `/v1/messages/batches/{id}` | `DeleteBatchInference` | Data |
283| `GET` | `/v1/models` | `ListModels` | Data |
284| `GET` | `/v1/models/{id}` | `GetModel` | Data |
285| `POST` | `/v1/files` | `CreateFile` | Data |
286| `GET` | `/v1/files` | `ListFiles` | Data |
287| `GET` | `/v1/files/{id}` | `GetFile` | Data |
288| `GET` | `/v1/files/{id}/content` | `GetFile` | Data |
289| `DELETE` | `/v1/files/{id}` | `DeleteFile` | Data |
290| `POST` | `/v1/skills` | `CreateSkill` | Data |
291| `GET` | `/v1/skills` | `ListSkills` | Data |
292| `GET` | `/v1/skills/{id}` | `GetSkill` | Data |
293| `DELETE` | `/v1/skills/{id}` | `DeleteSkill` | Data |
294| `POST` | `/v1/skills/{id}/versions` | `UpdateSkill` | Data |
295| `GET` | `/v1/skills/{id}/versions` | `GetSkill` | Data |
296| `GET` | `/v1/skills/{id}/versions/{version}` | `GetSkill` | Data |
297| `GET` | `/v1/skills/{id}/versions/{version}/content` | `GetSkill` | Data |
298| `DELETE` | `/v1/skills/{id}/versions/{version}` | `UpdateSkill` | Data |
299| `POST` | `/v1/user_profiles` | `CreateUserProfile` | Data |
300| `GET` | `/v1/user_profiles` | `ListUserProfiles` | Data |
301| `GET` | `/v1/user_profiles/{id}` | `GetUserProfile` | Data |
302| `POST` | `/v1/user_profiles/{id}` | `UpdateUserProfile` | Data |
303| `POST` | `/v1/user_profiles/{id}/enrollment_url` | `CreateUserProfileEnrollmentUrl` | Data |
304| `POST` | `/v1/organizations/workspaces` | `CreateWorkspace` | Management |
305| `GET` | `/v1/organizations/workspaces` | `ListWorkspaces` | Management |
306| `GET` | `/v1/organizations/workspaces/{id}` | `GetWorkspace` | Management |
307| `POST` | `/v1/organizations/workspaces/{id}` | `UpdateWorkspace` | Management |
308| `POST` | `/v1/organizations/workspaces/{id}/archive` | `ArchiveWorkspace` | Management |
309| `POST` | `/v1/organizations/external_keys` | `RegisterKey` | Management |
310| `GET` | `/v1/organizations/external_keys` | `ListKeys` | Management |
311| `GET` | `/v1/organizations/external_keys/{id}` | `GetKey` | Management |
312| `POST` | `/v1/organizations/external_keys/{id}` | `UpdateKey` | Management |
313| `DELETE` | `/v1/organizations/external_keys/{id}` | `DisableKey` | Management |
314| `GET` | `/v1/compliance/activities` | `ListComplianceActivities` | Management |
315| `POST` | `/v1/agents` | `CreateAgent` | Data |
316| `GET` | `/v1/agents` | `ListAgents` | Data |
317| `GET` | `/v1/agents/{id}` | `GetAgent` | Data |
318| `POST` | `/v1/agents/{id}` | `UpdateAgent` | Data |
319| `POST` | `/v1/agents/{id}/archive` | `ArchiveAgent` | Data |
320| `GET` | `/v1/agents/{id}/versions` | `GetAgent` | Data |
321| `POST` | `/v1/sessions` | `CreateSession` | Data |
322| `GET` | `/v1/sessions` | `ListSessions` | Data |
323| `GET` | `/v1/sessions/{id}` | `GetSession` | Data |
324| `POST` | `/v1/sessions/{id}` | `UpdateSession` | Data |
325| `POST` | `/v1/sessions/{id}/archive` | `ArchiveSession` | Data |
326| `DELETE` | `/v1/sessions/{id}` | `DeleteSession` | Data |
327| `GET` | `/v1/sessions/{id}/events` | `GetSession` | Data |
328| `POST` | `/v1/sessions/{id}/events` | `UpdateSession` | Data |
329| `GET` | `/v1/sessions/{id}/events/stream` | `GetSession` | Data |
330| `GET` | `/v1/sessions/{id}/resources` | `GetSession` | Data |
331| `GET` | `/v1/sessions/{id}/resources/{id}` | `GetSession` | Data |
332| `POST` | `/v1/sessions/{id}/resources` | `UpdateSession` | Data |
333| `POST` | `/v1/sessions/{id}/resources/{id}` | `UpdateSession` | Data |
334| `DELETE` | `/v1/sessions/{id}/resources/{id}` | `UpdateSession` | Data |
335| `POST` | `/v1/environments` | `CreateEnvironment` | Data |
336| `GET` | `/v1/environments` | `ListEnvironments` | Data |
337| `GET` | `/v1/environments/{id}` | `GetEnvironment` | Data |
338| `POST` | `/v1/environments/{id}` | `UpdateEnvironment` | Data |
339| `POST` | `/v1/environments/{id}/archive` | `ArchiveEnvironment` | Data |
340| `DELETE` | `/v1/environments/{id}` | `DeleteEnvironment` | Data |
341| `GET` | `/v1/environments/{id}/work` | `GetEnvironment` | Data |
342| `GET` | `/v1/environments/{id}/work/poll` | `ProcessEnvironmentWork` | Data |
343| `GET` | `/v1/environments/{id}/work/{work_id}` | `GetEnvironment` | Data |
344| `GET` | `/v1/environments/{id}/work/stats` | `GetEnvironment` | Data |
345| `POST` | `/v1/environments/{id}/work/{work_id}` | `ProcessEnvironmentWork` | Data |
346| `POST` | `/v1/environments/{id}/work/{work_id}/ack` | `ProcessEnvironmentWork` | Data |
347| `POST` | `/v1/environments/{id}/work/{work_id}/heartbeat` | `ProcessEnvironmentWork` | Data |
348| `POST` | `/v1/environments/{id}/work/{work_id}/stop` | `ProcessEnvironmentWork` | Data |
349| `POST` | `/v1/vaults` | `CreateVault` | Management |
350| `GET` | `/v1/vaults` | `ListVaults` | Management |
351| `GET` | `/v1/vaults/{id}` | `GetVault` | Management |
352| `POST` | `/v1/vaults/{id}` | `UpdateVault` | Management |
353| `POST` | `/v1/vaults/{id}/archive` | `ArchiveVault` | Management |
354| `DELETE` | `/v1/vaults/{id}` | `DeleteVault` | Management |
355| `GET` | `/v1/vaults/{id}/credentials` | `GetVault` | Management |
356| `POST` | `/v1/vaults/{id}/credentials` | `UpdateVault` | Management |
357| `GET` | `/v1/vaults/{id}/credentials/{id}` | `GetVault` | Management |
358| `POST` | `/v1/vaults/{id}/credentials/{id}` | `UpdateVault` | Management |
359| `POST` | `/v1/vaults/{id}/credentials/{id}/archive` | `UpdateVault` | Management |
360| `DELETE` | `/v1/vaults/{id}/credentials/{id}` | `UpdateVault` | Management |
361| `POST` | `/v1/memory_stores` | `CreateMemoryStore` | Data |
362| `GET` | `/v1/memory_stores` | `ListMemoryStores` | Data |
363| `GET` | `/v1/memory_stores/{id}` | `GetMemoryStore` | Data |
364| `POST` | `/v1/memory_stores/{id}` | `UpdateMemoryStore` | Data |
365| `POST` | `/v1/memory_stores/{id}/archive` | `ArchiveMemoryStore` | Data |
366| `DELETE` | `/v1/memory_stores/{id}` | `DeleteMemoryStore` | Data |
367| `POST` | `/v1/memory_stores/{id}/memories` | `UpdateMemoryStore` | Data |
368| `GET` | `/v1/memory_stores/{id}/memories` | `GetMemoryStore` | Data |
369| `GET` | `/v1/memory_stores/{id}/memories/{id}` | `GetMemoryStore` | Data |
370| `POST` | `/v1/memory_stores/{id}/memories/{id}` | `UpdateMemoryStore` | Data |
371| `DELETE` | `/v1/memory_stores/{id}/memories/{id}` | `UpdateMemoryStore` | Data |
372| `GET` | `/v1/memory_stores/{id}/memory_versions` | `GetMemoryStore` | Data |
373| `GET` | `/v1/memory_stores/{id}/memory_versions/{id}` | `GetMemoryStore` | Data |
374| `POST` | `/v1/memory_stores/{id}/memory_versions/{id}/redact` | `UpdateMemoryStore` | Data |
375| `GET` | `/v1/webhooks` | `ListWebhooks` | Management |
376| `GET` | `/v1/webhooks/{id}` | `GetWebhook` | Management |
377| `POST` | `/v1/webhooks` | `CreateWebhook` | Management |
378| `POST` | `/v1/webhooks/{id}` | `UpdateWebhook` | Management |
379| `DELETE` | `/v1/webhooks/{id}` | `DeleteWebhook` | Management |
380| `POST` | `/v1/webhooks/{id}/regenerate_signing_secret` | `RotateWebhookSecret` | Management |
375381 
376382Routes not in this table are not available on Claude Platform on AWS. The gateway denies any route not listed here by default.
377383 
from line 400
394400`AnthropicInferenceAccess` is the narrowest managed policy sufficient to run inference. It covers both synchronous and batch inference and, through the `Get*` and `List*` wildcards, grants read access to every API resource in the namespace, including Claude Managed Agents (CMA) resources (agents, sessions, environments, vaults, memory stores, and webhooks). This includes file content download through `GetFile` (see the [Files](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#files) note), skill content download through `GetSkill` (see the [Skills](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#skills) note), and memory contents through `GetMemoryStore`. Vault credential secrets and webhook signing secrets are not exposed: those fields are write-only and are never returned by `GetVault` or `GetWebhook` (see [Authenticate with vaults](https://platform.claude.com/docs/en/managed-agents/vaults)). `AnthropicInferenceAccess` does not grant file creation or deletion, skill management, user profile management, workspace mutation, encryption key management, or any Claude Managed Agents write action (create, update, archive, delete, process, or rotate). To exclude CMA reads, replace `AnthropicInferenceAccess` with a custom policy that enumerates only the specific non-CMA actions you need.
395401 
396402<Note>
397 `AnthropicReadOnlyAccess`, `AnthropicInferenceAccess`, and `AnthropicLimitedAccess` all carry the `Get*` and `List*` wildcards, which grant read access to all content in the workspace: file bytes, skill content, batch results, session conversation history, and memory contents. The wildcards also grant `GetKey` and `ListKeys`, which read the organization's registered encryption key configurations (key ARNs and metadata, never key material). The `List*` wildcard also grants `ListComplianceActivities`, which reads the organization's compliance [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed) once the Compliance API is enabled for the organization (see [Compliance](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#compliance)). Vault credential secrets and webhook signing secrets are not exposed; those fields are write-only and are never returned by `GetVault` or `GetWebhook`. If your principal should not read existing content, use a custom policy that enumerates only the actions you need.
403 `AnthropicReadOnlyAccess`, `AnthropicInferenceAccess`, and `AnthropicLimitedAccess` all carry the `Get*` and `List*` wildcards, which grant read access to all content in the workspace: file bytes, skill content, batch results, session conversation history, and memory contents. The wildcards also grant `GetKey` and `ListKeys`, which read the organization's registered encryption key configurations (key ARNs and metadata, never key material). They also grant the account-scoped `GetUserProfile` and `ListUserProfiles`, which read user profiles. The `List*` wildcard also grants `ListComplianceActivities`, which reads the organization's compliance [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed) once the Compliance API is enabled for the organization (see [Compliance](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#compliance)). Vault credential secrets and webhook signing secrets are not exposed; those fields are write-only and are never returned by `GetVault` or `GetWebhook`. If your principal should not read existing content, use a custom policy that enumerates only the actions you need.
398404</Note>
399405 
400406`AnthropicLimitedAccess` includes all Claude Managed Agents actions in addition to inference actions.
from line 470
464470```
465471 
466472<Note>
467 The `aws-external-anthropic:*` wildcard in the first statement includes account-scoped actions (`CreateWorkspace`, `ListWorkspaces`, `ListComplianceActivities`, and the external key actions) that the workspace ARN constraint silently filters out. This is consistent with the "isolation" intent (the role cannot create workspaces, enumerate workspaces, manage encryption key registrations, or read the compliance Activity Feed; it can still attach an already-registered key to its own workspace through `UpdateWorkspace`), but the policy contains permissions that have no effect. See [Provisioning automation](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#provisioning-automation) for the account-scoped pattern.
473 The `aws-external-anthropic:*` wildcard in the first statement includes account-scoped actions (`CreateWorkspace`, `ListWorkspaces`, `ListComplianceActivities`, the external key actions, and the user profile actions) that the workspace ARN constraint silently filters out. This is consistent with the "isolation" intent (the role cannot create workspaces, enumerate workspaces, manage encryption key registrations, read the compliance Activity Feed, or read or manage user profiles; it can still attach an already-registered key to its own workspace through `UpdateWorkspace`), but the policy contains permissions that have no effect. If the role needs user profiles, add a separate `Allow` statement for the user profile actions with `Resource: "*"`. See [Provisioning automation](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#provisioning-automation) for the account-scoped pattern.
468474 
469475 `CallWithBearerToken` and `AssumeConsole` are route-less actions that do not bind to a workspace ARN. The second statement grants them on `Resource: "*"` so the role can authenticate with an API key and open the Claude Console. Omit this statement if the role uses SigV4 only and does not need Claude Console access.
470476</Note>

build-with-claude/overview Changed · +14 / -14 lines

from line 38
3838 
3939The ZDR column indicates whether a feature is available under a Zero Data Retention arrangement. For most features this depends only on what the feature mechanism retains; for features tied to specific models, model-level ZDR availability also applies. See [Model-specific data retention requirements](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention#model-specific-data-retention-requirements).
4040 
41| Feature | Description | Zero Data Retention (ZDR) | Availability |
42| --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
43| [Context windows](https://platform.claude.com/docs/en/build-with-claude/context-windows) | Up to 1M tokens for processing large documents, extensive code bases, and long conversations. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
44| [Adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) | Let Claude dynamically decide when and how much to think. The only thinking mode on Claude 4.7 and later models. Use the effort parameter to control thinking depth. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
45| [Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing) | Process large volumes of requests asynchronously for cost savings. Send batches with a large number of queries per batch. Batch API calls cost 50% less than standard API calls. | Not ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws /> |
46| [Citations](https://platform.claude.com/docs/en/build-with-claude/citations) | Ground Claude's responses in source documents. With Citations, Claude can provide detailed references to the exact sentences and passages it uses to generate responses, leading to more verifiable, trustworthy outputs. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
47| [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) | Control where model inference runs using geographic controls. Specify `"global"` or `"us"` routing per request through the `inference_geo` parameter. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws /> |
48| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) | Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
49| [Fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Avoid paying the prompt-cache cost twice when you retry a refused request on another model. The refusal carries a credit token, and echoing it on the retry bills the retry as though the conversation had been on the new model all along. Message Batches results do not include fallback credit tokens. | Not ZDR eligible\* | <PlatformAvailability claudeApiBeta claudePlatformAwsBeta bedrockBeta vertexAiBeta azureAiBeta /> |
50| [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support) | Process and analyze text and visual content from PDF documents. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
51| [Search results](https://platform.claude.com/docs/en/build-with-claude/search-results) | Enable natural citations for RAG applications by providing search results with proper source attribution. Achieve web search-quality citations for custom knowledge bases and tools. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
52| [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback) | Retry a refused request inside a single API call. Use the `"default"` mode to apply Anthropic's recommended fallback models, or name up to three models of your own; when the requested model declines, the API runs the next model in the chain on the same request. The `fallbacks` parameter is not available in the Message Batches API. | Not ZDR eligible\* | <PlatformAvailability claudeApiBeta /> |
53| [Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) | Guarantee schema conformance with two approaches: JSON outputs for structured data responses, and strict tool use for validated tool inputs. | [ZDR eligible (qualified)](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#data-retention)\* | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
54| [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) | Enhanced reasoning capabilities for complex tasks, with an optional summary of Claude's reasoning before its final answer. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
41| Feature | Description | Zero Data Retention (ZDR) | Availability |
42| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
43| [Context windows](https://platform.claude.com/docs/en/build-with-claude/context-windows) | Up to 1M tokens for processing large documents, extensive code bases, and long conversations. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
44| [Adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) | Let Claude dynamically decide when and how much to think. The only thinking mode on Claude 4.7 and later models. Use the effort parameter to control thinking depth. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
45| [Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing) | Process large volumes of requests asynchronously for cost savings. Send batches with a large number of queries per batch. Batch API calls cost 50% less than standard API calls. | Not ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws /> |
46| [Citations](https://platform.claude.com/docs/en/build-with-claude/citations) | Ground Claude's responses in source documents. With Citations, Claude can provide detailed references to the exact sentences and passages it uses to generate responses, leading to more verifiable, trustworthy outputs. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
47| [Data residency](https://platform.claude.com/docs/en/manage-claude/data-residency) | Control where model inference runs using geographic controls. Specify `"global"` or `"us"` routing per request through the `inference_geo` parameter. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws /> |
48| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) | Control how many tokens Claude uses when responding with the effort parameter, trading off between response thoroughness and token efficiency. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
49| [Fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Avoid paying the prompt-cache cost twice when you retry a refused request on another model. The refusal carries a credit token, and echoing it on the retry bills the retry as though the conversation had been on the new model all along. Message Batches results do not include fallback credit tokens. | Not ZDR eligible\* | <PlatformAvailability claudeApiBeta claudePlatformAwsBeta bedrockBeta vertexAiBeta azureAiBeta /> |
50| [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support) | Process and analyze text and visual content from PDF documents. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
51| [Search results](https://platform.claude.com/docs/en/build-with-claude/search-results) | Enable natural citations for RAG applications by providing search results with proper source attribution. Achieve web search-quality citations for custom knowledge bases and tools. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
52| [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback) | Retry a refused request inside a single API call. Use the `"default"` mode to apply Anthropic's recommended fallback models, or name up to three models of your own; when the requested model declines, the API runs the next model in the chain on the same request. The `fallbacks` parameter is not available in the Message Batches API. | Not ZDR eligible\* | <PlatformAvailability claudeApiBeta /> |
53| <Tooltip tooltipContent="On Amazon Bedrock, structured outputs are available only on the legacy InvokeModel integration, for Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.5, and Claude Haiku 4.5. Claude in Amazon Bedrock doesn't support them.">[Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)</Tooltip> | Guarantee schema conformance with two approaches: JSON outputs for structured data responses, and strict tool use for validated tool inputs. | [ZDR eligible (qualified)](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#data-retention)\* | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
54| [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking) | Enhanced reasoning capabilities for complex tasks, with an optional summary of Claude's reasoning before its final answer. | ZDR eligible | <PlatformAvailability claudeApi claudePlatformAws bedrock vertexAi azureAi /> |
5555 
5656## Tools
5757 

manage-claude/workspaces Changed · +4 / -4 lines

from line 14
1414 
1515* **Workspace identifiers** use the `wrkspc_` prefix (for example, `wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ`)
1616* **Maximum 100 workspaces** per organization by default (archived workspaces don't count); contact your account team if you need more
17* **Default Workspace** has a `wrkspc_` ID like any other workspace (returned in the [`anthropic-workspace-id` response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response) and accepted by [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve)), but it doesn't appear in [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) results, and API keys, usage reports, and cost reports show `null` for its `workspace_id`, as do all-workspaces API keys (an API key's `scope` field tells them apart; for a key bound to the Default Workspace it carries the real ID)
17* **Default Workspace** has a `wrkspc_` ID like any other workspace (returned in the [`anthropic-workspace-id` response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response) and accepted by [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve)), but it appears in [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) results only when you pass `include_default=true`, and API keys, usage reports, and cost reports show `null` for its `workspace_id`, as do all-workspaces API keys (an API key's `scope` field tells them apart; for a key bound to the Default Workspace it carries the real ID)
1818* **API keys** can be scoped to a single workspace. In this case, they can only access resources within that workspace. Some API keys can be granted permissions across multiple workspaces, and provide a [workspace ID header](https://platform.claude.com/docs/en/manage-claude/authentication#select-a-workspace) to access resources within that workspace
1919 
2020### Claude Code workspace
from line 836
836836* **[MCP tunnels](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview)** are managed with a `workspace:manage_tunnels` OAuth token obtained through [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation), not an API key. Tunnels are created in a workspace, and the Console **MCP tunnels** list and the Managed Agent server picker show tunnels in the current workspace only; the cap of 10 active tunnels applies organization-wide. Tunnel management requires a role with tunnel management permissions; organization developers can view but not change them.
837837* **Workspaces** themselves and **organization members** are managed at the organization level through the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api), using an Admin API key, an `org:admin` OAuth token, or a personal or service account key that isn't scoped to a specific workspace.
838838 
839To look up your organization's workspace IDs, call the [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) endpoint or find them in the [Claude Console](https://platform.claude.com/settings/workspaces).
839To look up your organization's workspace IDs, call the [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) endpoint (pass `include_default=true` to include the Default Workspace) or find them in the [Claude Console](https://platform.claude.com/settings/workspaces).
840840 
841841<Note>
842842 [Prompt caches](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) are also isolated per workspace on the Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), and [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry). On Amazon Bedrock and Google Cloud, prompt caches are isolated per organization.
from line 1008
10081008 
10091009* Confirm which workspace's usage, cost, and [rate limits](https://platform.claude.com/docs/en/api/rate-limits) the request counted toward
10101010* Match it against the `workspace_id` field in [Usage and Cost API](https://platform.claude.com/docs/en/manage-claude/usage-cost-api) reports and on [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) objects such as API keys (both report `null` for the Default Workspace, as API keys also do for all-workspaces keys; an API key's `scope` field tells the two apart and, for a key bound to one workspace, carries that workspace's real ID)
1011* Check whether it's your Default Workspace's ID by passing it to [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve) with an [Admin API key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys): the Default Workspace comes back with `"name": "Default"`, even though [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) omits it
1011* Check whether it's your Default Workspace's ID by passing it to [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve) with an [Admin API key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys): the Default Workspace comes back with `"name": "Default"`, even though [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) omits it unless you pass `include_default=true`
10121012* Open that workspace in the [Console](https://platform.claude.com/settings/workspaces) to find the request's resources, such as sessions, files, message batches, and skills
10131013 
10141014## Workspace limits
from line 1099
10991099 
11001100<AccordionGroup>
11011101 <Accordion title="What's the Default Workspace?">
1102 Every organization has a "Default Workspace" that cannot be renamed, archived, or deleted. Like every workspace, it has a `wrkspc_` ID: the API returns it in the [`anthropic-workspace-id` response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response), and you can pass it to [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve) and [Update Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/update). It has no member list of its own, because access to it follows each member's organization role. It doesn't appear in [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) results, and API keys, usage reports, and cost reports that belong to it show `null` for `workspace_id`, as do all-workspaces API keys; an API key's `scope` field tells the two apart and, for a key that belongs to the Default Workspace, carries its real ID.
1102 Every organization has a "Default Workspace" that cannot be renamed, archived, or deleted. Like every workspace, it has a `wrkspc_` ID: the API returns it in the [`anthropic-workspace-id` response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response), and you can pass it to [Get Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/retrieve) and [Update Workspace](https://platform.claude.com/docs/en/api/beta/organization/workspaces/update). It has no member list of its own, because access to it follows each member's organization role. It appears in [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) results only when you pass `include_default=true`, and API keys, usage reports, and cost reports that belong to it show `null` for `workspace_id`, as do all-workspaces API keys; an API key's `scope` field tells the two apart and, for a key that belongs to the Default Workspace, carries its real ID.
11031103 </Accordion>
11041104 
11051105 <Accordion title="What's the Claude Code workspace?">

managed-agents/memory Changed · +5 / -5 lines

from line 17
1717 
1818## Overview
1919 
20A **memory store** is a workspace-scoped collection of text documents optimized for Claude. When you attach a store to a session, it is mounted as a directory inside the session's sandbox. The agent reads and writes it with the same file tools it uses for the rest of the filesystem, and a note describing each mount is automatically added to the system prompt, telling the agent where to look. The [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools) is required for these interactions; make sure to enable it during [agent creation](https://platform.claude.com/docs/en/managed-agents/agent-setup). On [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores), that directory is not a live mount. Instead, the SDK's environment worker downloads each attached store into your sandbox before the agent's tools run and keeps that copy in sync with the store.
20A **memory store** is a workspace-scoped collection of text documents optimized for Claude. When you attach a store to a session, it is mounted as a directory inside the session's sandbox. The agent reads and writes it with the same file tools it uses for the rest of the filesystem, and a note describing each mount is automatically added to the system prompt, telling the agent where to look. The [agent toolset](https://platform.claude.com/docs/en/managed-agents/tools) is required for these interactions; make sure to enable it during [agent creation](https://platform.claude.com/docs/en/managed-agents/agent-setup). On [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory), that directory is not a live mount. Instead, your environment worker downloads each attached store into your sandbox before the agent's tools run and keeps that copy in sync with the store.
2121 
2222Each **memory** in a store is addressed by a path and can be read and edited directly through the API or the Claude Console, allowing for tuning, importing, and exporting.
2323 
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#use-memory-stores); self-hosted environments accept only `memory_store` resources.
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.
216216 
217217Optionally 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.
218218 
from line 386
386386`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>
389 On [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores), each store's directory is a local copy that the SDK 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.
389 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.
390390 
391 For a `read_only` store, the worker's `write` and `edit` tools refuse changes under that directory and the worker never uploads anything from it. To learn how the worker resolves write conflicts, and what the `bash` tool can still change in a read-only store's local copy, see [Read-only stores and conflicts](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#read-only-stores-and-conflicts).
391 For a `read_only` store, the worker's `write` and `edit` tools refuse changes under that directory and the worker never uploads anything from it. To learn how the worker resolves write conflicts, and what the `bash` tool can still change in a read-only store's local copy, see [Read-only stores and conflicts](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#read-only-stores-and-conflicts).
392392</Note>
393393 
394394The agent's reads and writes appear in the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) as ordinary `agent.tool_use` and `agent.tool_result` events for whichever tool touched the mount.

managed-agents/reference Changed · +1 / -13 lines

from line 93
9393 
9494## Self-hosted worker
9595 
96These are the `ant beta:worker` CLI flags for the pre-built worker that drives a `self_hosted` environment. See [Self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes) for setting up the environment, running a worker, and the SDK helper options.
97 
98| Flag | Description |
99| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100| `--environment-id` | The environment to poll for work. Also reads from `ANTHROPIC_ENVIRONMENT_ID`. |
101| `--environment-key` | Authenticates the worker with this environment. Also reads from `ANTHROPIC_ENVIRONMENT_KEY`. |
102| `--workdir` | Directory where skills are downloaded and tools read and write files. Defaults to `.` (the current directory); the system default working directory is `/workspace`. |
103| `--on-work` | Script to call for each claimed work item instead of running tools in-process. Receives session details as environment variables. |
104| `--unrestricted-paths` | Allow the file tools to read and write paths outside `--workdir`. The workdir check is a guardrail for the file tools only, not a sandbox; it does not constrain bash. |
105| `--max-idle` | How long to wait after the session goes idle with an `end_turn` [stop reason](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons) before shutting down. Defaults to `60s`. |
106| `--log-format` | Log output format. Use `json` for structured log ingestion. Defaults to `text`. |
107 
108The CLI worker does not mount [memory stores](https://platform.claude.com/docs/en/managed-agents/memory): a session that attaches one still runs, but the agent finds nothing at the store's `mount_path` and no changes sync back to the store. To use memory stores in sessions on a self-hosted environment, run the SDK worker instead; see [Use memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores).
96See [Self-hosted worker reference](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference) for the `ant beta:worker` CLI flags, environment variables, filesystem paths, and SDK helper options of the pre-built workers that drive a `self_hosted` environment.
10997 
11098## Supported MCP server types
11199 

managed-agents/self-hosted-sandboxes-custom-tools New page · 640 lines, new page

## Serve a custom tool ## Wrap an MCP server as custom tools ### Install an MCP SDK ### Declare and serve the tools ## Limits and behavior ### Tools are declared, not discovered at runtime ### Declarations must fit the Managed Agents API ### Tool failures surface as error tool results ### Wrap only servers you operate or trust ### Permission policies do not apply

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Custom tools in self-hosted sandboxes
url: https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-custom-tools
description: Serve custom tools from a self-hosted sandbox worker, and wrap an MCP server inside your network as custom tools without running a tunnel.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

[Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools) are tools your own code executes: the agent emits an `agent.custom_tool_use` event and waits for a matching `user.custom_tool_result`. Your worker can be that code. Because it runs inside your sandbox, the tool reaches the internal services, credentials, and network egress you configured for the sandbox, and nothing more.

The environment key authorizes posting custom tool results, so your Claude API key stays off the worker host.

<Note>
  Serving custom tools requires the SDK worker. The `ant` CLI worker has no way to register a custom tool implementation. In the sandbox-per-session pattern, [run the SDK worker inside the sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#run-the-sdk-worker-inside-the-sandbox).
</Note>

## Serve a custom tool

<Steps>
  <Step title="Declare the tool on the agent">
    Add a `custom` entry to the agent's `tools` whose `name` matches the tool your worker registers. See [Custom tools](https://platform.claude.com/docs/en/managed-agents/tools#custom-tools) for the full declaration shape.

    ```json
    {
      "type": "custom",
      "name": "get_order_status",
      "description": "Look up an order in the internal fulfillment system by order ID.",
      "input_schema": {
        "type": "object",
        "properties": {
          "order_id": { "type": "string", "description": "The order ID" }
        },
        "required": ["order_id"]
      }
    }
    ```
  </Step>

  <Step title="Register the implementation with the worker">
    Pass the tool through the worker's `tools` (go: `ToolsFunc`) factory (see [`EnvironmentWorker`](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#environment-worker)), alongside the built-in toolset:

    <CodeGroup exclude="shell">
      ```python Python
      import asyncio
      import os
      from anthropic import AsyncAnthropic, beta_async_tool
      from anthropic.lib.environments import EnvironmentWorker
      from anthropic.lib.tools.agent_toolset import beta_agent_toolset_20260401


      @beta_async_tool
      async def get_order_status(order_id: str) -> str:
          """Look up an order in the internal fulfillment system by order ID."""
          # Runs on the worker host: call anything the sandbox can reach.
          return f"Order {order_id}: shipped"


      async def main() -> None:
          environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
          environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
          async with AsyncAnthropic(auth_token=environment_key) as client:
              await EnvironmentWorker(
                  client,
                  environment_id=environment_id,
                  environment_key=environment_key,
                  workdir="/workspace",
                  tools=lambda env: [*beta_agent_toolset_20260401(env), get_order_status],
              ).run()


      asyncio.run(main())
      ```

      ```typescript TypeScript
      import Anthropic from "@anthropic-ai/sdk";
      import { EnvironmentWorker } from "@anthropic-ai/sdk/helpers/beta/environments";
      import { betaTool } from "@anthropic-ai/sdk/helpers/beta/json-schema";
      import { betaAgentToolset20260401 } from "@anthropic-ai/sdk/tools/agent-toolset/node";

      const getOrderStatus = betaTool({
        name: "get_order_status",
        description: "Look up an order in the internal fulfillment system by order ID.",
        inputSchema: {
          type: "object",
          properties: { order_id: { type: "string", description: "The order ID" } },
          required: ["order_id"]
        },
        // Runs on the worker host: call anything the sandbox can reach.
        run: async ({ order_id }) => `Order ${order_id}: shipped`
      });

      const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
      const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
      const client = new Anthropic({ authToken: environmentKey });
      const controller = new AbortController();
      process.once("SIGTERM", () => controller.abort());

      await new EnvironmentWorker({
        client,
        environmentId,
        environmentKey,
        workdir: "/workspace",
        signal: controller.signal,
        tools: (ctx) => [...betaAgentToolset20260401(ctx), getOrderStatus]
      }).run();
      ```

      ```csharp C#
      // EnvironmentWorker is not currently available in the C# SDK.
      // To answer custom tool calls directly, see the session event stream.
      ```

      ```go Go
      package main

      import (
      	"context"
      	"log"
      	"os"
      	"os/signal"
      	"syscall"

      	"github.com/anthropics/anthropic-sdk-go"
      	"github.com/anthropics/anthropic-sdk-go/lib/environments"
      	"github.com/anthropics/anthropic-sdk-go/option"
      	"github.com/anthropics/anthropic-sdk-go/toolrunner"
      	"github.com/anthropics/anthropic-sdk-go/tools/agenttoolset"
      )

      type orderStatusInput struct {
      	OrderID string `json:"order_id"`
      }

      func main() {
      	environmentKey := os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")
      	environmentID := os.Getenv("ANTHROPIC_ENVIRONMENT_ID")

      	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
      	defer stop()

      	getOrderStatus := toolrunner.NewBetaTool(
      		"get_order_status",
      		"Look up an order in the internal fulfillment system by order ID.",
      		anthropic.BetaToolInputSchemaParam{
      			Properties: map[string]any{
      				"order_id": map[string]any{"type": "string", "description": "The order ID"},
      			},
      			Required: []string{"order_id"},
      		},
      		// Runs on the worker host: call anything the sandbox can reach.
      		func(ctx context.Context, input orderStatusInput) (anthropic.BetaToolResultBlockParamContentUnion, error) {
      			return anthropic.BetaToolResultBlockParamContentUnion{
      				OfText: &anthropic.BetaTextBlockParam{Text: "Order " + input.OrderID + ": shipped"},
      			}, nil
      		},
      	)

      	client := anthropic.NewClient(option.WithAuthToken(environmentKey))

      	worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
      		EnvironmentID:  environmentID,
      		EnvironmentKey: environmentKey,
      		Workdir:        "/workspace",
      		ToolsFunc: func(env *agenttoolset.AgentToolContext) []anthropic.BetaTool {
      			return append(agenttoolset.BetaAgentToolset20260401(env), getOrderStatus)
      		},
      	})
      	if err := worker.Run(ctx); err != nil {
      		log.Fatalf("worker: %v", err)
      	}
      }

      ```

      ```java Java
      // EnvironmentWorker is not currently available in the Java SDK.
      // To answer custom tool calls directly, see the session event stream.
      ```

      ```php PHP
      // EnvironmentWorker is not currently available in the PHP SDK.
      // To answer custom tool calls directly, see the session event stream.
      ```

      ```ruby Ruby
      # EnvironmentWorker is not currently available in the Ruby SDK.
      # To answer custom tool calls directly, see the session event stream.
      ```
    </CodeGroup>
  </Step>
</Steps>

The worker answers only the tools registered with it. If a tool is declared on the agent but no worker or client serves it, the session pauses with a `requires_action` stop reason. It stays paused until something posts the result. See [Handling custom tool calls](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#handling-custom-tool-calls) for the event flow.

## Wrap an MCP server as custom tools

The [MCP connector](https://platform.claude.com/docs/en/managed-agents/mcp-connector) connects to MCP servers from Anthropic's side. A server must therefore expose an HTTP endpoint that Anthropic can reach, directly or through an [MCP tunnel](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview).

To use a server that only your network can reach, make the worker the MCP client instead and declare the server's tools as custom tools. The MCP server needs no inbound connectivity from outside your network. Anthropic receives the tool definitions you declare on the agent, each call's input, and the result your worker posts back.

At runtime the model calls a wrapped tool like any other custom tool:

1. The agent emits an `agent.custom_tool_use` event.
2. The worker, inside your sandbox, forwards the call over its open MCP session to the server on your network.
3. The worker posts the server's response as the `user.custom_tool_result`.

### Install an MCP SDK

The SDK's [Client-side MCP helpers](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector#client-side-mcp-helpers) convert the server's tools into the runnable tools the worker accepts. Install an MCP SDK alongside the Anthropic SDK: `pip install "anthropic[mcp]" "mcp>=1.24"` (python; typescript: `npm install @modelcontextprotocol/sdk`; go: `go get github.com/modelcontextprotocol/go-sdk`).

The examples connect without authentication. To send credentials, configure the `http_client` (typescript: `requestInit`; go: `HTTPClient`) you hand to the MCP transport.

### Declare and serve the tools

<Steps>
  <Step title="Declare the server's tools on the agent">
    List the MCP server's tools and declare each one as a `custom` tool. The MCP `name`, `description`, and `inputSchema` map one to one onto the custom tool's fields. If the server paginates its tool list, declare every page; the worker must list the same pages.

    <CodeGroup exclude="shell">
      ```python Python
      import asyncio
      from typing import Any, cast
      from anthropic import AsyncAnthropic
      from anthropic.types.beta import BetaManagedAgentsCustomToolParams
      from mcp import ClientSession, types
      # Requires mcp >= 1.24, which renamed streamablehttp_client to streamable_http_client.
      from mcp.client.streamable_http import streamable_http_client

      MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp"


      def to_custom_tool(tool: types.Tool) -> BetaManagedAgentsCustomToolParams:
          # The MCP fields map one to one onto a custom tool declaration. The cast
          # hands the schema dictionary to the SDK's typed parameter unchanged.
          return {
              "type": "custom",
              "name": tool.name,
              "description": tool.description or tool.name,
              "input_schema": cast(Any, tool.inputSchema),
          }


      async def main() -> None:
          # Run this wherever you create agents, not on the worker host: it
          # authenticates with your Claude API key (ANTHROPIC_API_KEY).
          async with (
              streamable_http_client(MCP_SERVER_URL) as (read, write, _),
              ClientSession(read, write) as mcp_session,
              AsyncAnthropic() as client,
          ):
              await mcp_session.initialize()
              listed = await mcp_session.list_tools()
              agent = await client.beta.agents.create(
                  name="Internal tools agent",
                  model="claude-opus-5-5",
                  tools=[
                      {"type": "agent_toolset_20260401"},
                      *[to_custom_tool(tool) for tool in listed.tools],
                  ],
              )
              print(agent.id)


      asyncio.run(main())
      ```

      ```typescript TypeScript
      import Anthropic from "@anthropic-ai/sdk";
      import { Client } from "@modelcontextprotocol/sdk/client/index.js";
      import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

      const MCP_SERVER_URL = "http://mcp.internal.example.com:8000/mcp";

      // Run this wherever you create agents, not on the worker host: it
      // authenticates with your Claude API key (ANTHROPIC_API_KEY).
      const client = new Anthropic();

      const mcpClient = new Client({ name: "declare-agent-tools", version: "1.0.0" });
      await mcpClient.connect(new StreamableHTTPClientTransport(new URL(MCP_SERVER_URL)));
      const { tools } = await mcpClient.listTools();

      const agent = await client.beta.agents.create({
        name: "Internal tools agent",
        model: "claude-opus-5-5",
        tools: [
          { type: "agent_toolset_20260401" },
          // The MCP fields map one to one onto a custom tool declaration.
          ...tools.map((tool) => ({
            type: "custom" as const,
            name: tool.name,
            description: tool.description || tool.name,
            input_schema: tool.inputSchema
          }))
        ]
      });
      console.log(agent.id);

Cut at 300 lines. The page has the rest.

managed-agents/self-hosted-sandboxes-memory New page · 159 lines, new page

## Requirements ## Prepare the host ### Isolate sessions that share a store ## How the worker handles memory ## Configure sync ### Sync interval ### Deletions ## Read-only stores and conflicts ## Troubleshooting

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Memory stores in self-hosted sandboxes
url: https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory
description: "Attach memory stores to Claude Managed Agents sessions that run in self-hosted sandboxes: prepare the host, configure sync, and handle read-only stores and conflicts."
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

Sessions 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.

The 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.

## Requirements

* **A worker that mounts memory stores:** Use `ant` CLI 1.33.0 or later, or `EnvironmentWorker` from the Python, TypeScript, or Go SDK.
* **A POSIX filesystem:** Windows hosts are not supported, because the worker requires `O_NOFOLLOW` when it opens memory files. A case-sensitive filesystem is recommended, so that memory paths that differ only in case do not collide.
* **A writable `/mnt/memory` directory:** See [Prepare the host](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#prepare-the-host).
* **The work item's secret:** If your own code launches the worker, [forward the work item's secret](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret) to it.

<Note>
  Memory stores cannot be attached to sessions on self-hosted environments on [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws).
</Note>

## Prepare the host

Before you start the worker, create the parent directory and make it writable by the user the worker runs as:

```bash
sudo mkdir -p /mnt/memory && sudo chown "$USER" /mnt/memory
```

Do 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.

In 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.

### Isolate sessions that share a store

Two sessions cannot mount the same store on one host at the same time, because both need the same path. If your sessions attach the same store, run one session per filesystem. Giving each session [its own sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#run-one-sandbox-per-session) satisfies this rule.

## How the worker handles memory

When the worker claims a work item whose session has memory stores attached, it:

1. **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/`.
2. **Opens those directories to the file tools.** The agent works on memories with the same file tools it uses in the working directory.
3. **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.
4. **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.

The memory store on Anthropic's side remains the source of truth. [Memory versions](https://platform.claude.com/docs/en/managed-agents/memory#audit-memory-changes), redaction, and viewing or editing memories in the Console work as they do for cloud sessions. The agent's memory reads and writes appear in the [event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming) as ordinary tool events.

Because each worker syncs on an interval, a change written in one session becomes visible to another running session only after both have synced. That is typically well under a minute at the default interval. Sessions on cloud sandboxes see each other's changes almost immediately.

Each store directory contains a marker file named `.anthropic-memory-store` that ties the directory to its store. Leave it in place: the worker does not sync a directory whose marker is missing or altered.

<Warning>
  A worker that is killed rather than stopped runs no teardown, so unsynced edits are lost and the store directories stay behind. See [Stop workers gracefully](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#stop-workers-gracefully).
</Warning>

## Configure sync

Two `EnvironmentWorker` options control memory behavior. Set them wherever you construct the worker, including in a webhook handler. The `ant` CLI worker always uses the defaults.

### Sync interval

`memory_sync_interval` (typescript: `memorySyncIntervalMs`; go: `MemorySyncInterval`) sets how often attached stores reconcile with the server while the session runs.

| Setting                | Value                                                       |
| ---------------------- | ----------------------------------------------------------- |
| Default                | 15 seconds                                                  |
| Minimum                | 5 seconds                                                   |
| Example (10 seconds)   | `10` (python; typescript: `10_000`; go: `10 * time.Second`) |
| Disable memory support | `None` (python; typescript: `null`; go: `-1`)               |

A shorter interval narrows the window in which another session sees stale memories, at the cost of more memory store requests.

Disable 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.

While 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).

### Deletions

`memory_sync_deletions` (typescript: `memorySyncDeletions`; go: `MemorySyncDeletions`) sets whether a file the agent deletes locally is also deleted from the store. Uploads and downloads are unaffected.

| Value                                                                 | Behavior                                                                                                                                         |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `"enabled"` (go: `environments.MemorySyncDeletionsEnabled`) (default) | Deletes the memory from the store once a later sync confirms the file is still gone.                                                             |
| `"log_only"` (go: `environments.MemorySyncDeletionsLogOnly`)          | Runs the same checks but only logs what it would have deleted. Use it to watch what your workers would delete before you trust the enabled mode. |
| `"disabled"` (go: `environments.MemorySyncDeletionsDisabled`)         | Never deletes from the store.                                                                                                                    |

For example, to sync every 10 seconds and only log the deletes the worker would have made:

<CodeGroup exclude="shell">
  ```python Python
  worker = EnvironmentWorker(
      client,
      environment_id=environment_id,
      environment_key=environment_key,
      workdir="/workspace",
      memory_sync_interval=10,  # seconds
      memory_sync_deletions="log_only",
  )
  ```

  ```typescript TypeScript
  const worker = new EnvironmentWorker({
    client,
    environmentId,
    environmentKey,
    workdir: "/workspace",
    memorySyncIntervalMs: 10_000,
    memorySyncDeletions: "log_only"
  });
  ```

  ```csharp C#
  // EnvironmentWorker is not currently available in the C# SDK.
  ```

  ```go Go
  worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
  	EnvironmentID:       environmentID,
  	EnvironmentKey:      environmentKey,
  	Workdir:             "/workspace",
  	MemorySyncInterval:  10 * time.Second,
  	MemorySyncDeletions: environments.MemorySyncDeletionsLogOnly,
  })
  ```

  ```java Java
  // EnvironmentWorker is not currently available in the Java SDK.
  ```

  ```php PHP
  // EnvironmentWorker is not currently available in the PHP SDK.
  ```

  ```ruby Ruby
  # EnvironmentWorker is not currently available in the Ruby SDK.
  ```
</CodeGroup>

## Read-only stores and conflicts

For a store attached with `access: "read_only"`, the `write` and `edit` tools refuse to change files inside its directory. The worker never uploads anything from it.

Changes made through `bash`, or through a custom tool or MCP server you serve from the sandbox, are not blocked locally. They are never synced to the store, and the next remote change to that memory overwrites them. If the local copy itself must stay unchanged during the session:

* Disable the `bash` tool for that agent, and give it no custom tool that writes to the sandbox's filesystem.
* Do not mount the store path read-only. The worker itself must create the directory and write the downloaded memories into it.

Conflicts resolve in favor of the store. Suppose the agent changes a memory file that also changed in the store since the session last synced it. At the next sync, the worker keeps the store's version, overwrites the local file with it, and logs a warning. The `write` and `edit` tools themselves succeed and no error reaches the agent. If the agent's change still applies, it can re-read the file after the sync and make the change again.

## Troubleshooting

See [Memory stores fail to mount](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations#memory-stores-fail-to-mount) for the worker's log messages and their fixes.

managed-agents/self-hosted-sandboxes-operations New page · 353 lines, new page

## Read queue depth ## Stop a session gracefully ## Stop workers gracefully ## Troubleshooting ### The worker doesn't connect ### A session stays queued ### Memory stores fail to mount ### A custom tool call never returns ### A wrapped MCP tool call hangs

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Monitor and troubleshoot self-hosted workers
url: https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-operations
description: Read queue depth, stop sessions and workers without losing work, and fix common self-hosted sandbox failures.
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

The monitoring calls on this page run from your monitoring or operations tooling, authenticated with your Claude API key. The worker helpers handle the claim and keep-alive loop, so you don't call those endpoints directly.

<Warning>
  These endpoints accept either your organization API key or the environment key. Call them from outside the worker host with your organization API key. Setting `ANTHROPIC_API_KEY` on the worker host exposes an organization-scoped credential to agent tool calls.
</Warning>

## Read queue depth

`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:

| Field              | Meaning                                                                                                                                                         | Use it to                                                                                             |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `depth`            | Items waiting to be claimed.                                                                                                                                    | Scale your worker fleet or alert on backlog.                                                          |
| `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. |
| `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.                                                              |
| `workers_polling`  | Workers that have polled in the last 30 seconds.                                                                                                                | Alert on liveness.                                                                                    |

<CodeGroup>
  ```bash cURL
  curl -sS "https://api.anthropic.com/v1/environments/$ANTHROPIC_ENVIRONMENT_ID/work/stats" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "anthropic-version: 2023-06-01"
  ```

  ```bash CLI
  ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"
  ```

  ```python Python
  import os

  import anthropic

  client = anthropic.Anthropic()

  stats = client.beta.environments.work.stats(os.environ["ANTHROPIC_ENVIRONMENT_ID"])
  print(f"depth={stats.depth} pending={stats.pending}")
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  const client = new Anthropic();

  const stats = await client.beta.environments.work.stats(process.env.ANTHROPIC_ENVIRONMENT_ID!);

  console.log(`depth=${stats.depth} pending=${stats.pending}`);
  ```

  ```csharp C#
  using Anthropic;

  var client = new AnthropicClient();

  var environmentId = Environment.GetEnvironmentVariable("ANTHROPIC_ENVIRONMENT_ID")!;

  var stats = await client.Beta.Environments.Work.Stats(environmentId);

  Console.WriteLine($"depth={stats.Depth} pending={stats.Pending}");
  ```

  ```go Go
  package main

  import (
  	"context"
  	"fmt"
  	"os"

  	"github.com/anthropics/anthropic-sdk-go"
  )

  func main() {
  	client := anthropic.NewClient()
  	environmentID := os.Getenv("ANTHROPIC_ENVIRONMENT_ID")

  	stats, err := client.Beta.Environments.Work.Stats(
  		context.Background(),
  		environmentID,
  		anthropic.BetaEnvironmentWorkStatsParams{},
  	)
  	if err != nil {
  		panic(err)
  	}

  	fmt.Printf("depth=%d pending=%d\n", stats.Depth, stats.Pending)
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.models.beta.environments.work.BetaSelfHostedWorkQueueStats;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      BetaSelfHostedWorkQueueStats stats = client.beta()
          .environments()
          .work()
          .stats(System.getenv("ANTHROPIC_ENVIRONMENT_ID"));

      IO.println("depth=" + stats.depth() + " pending=" + stats.pending());
  }
  ```

  ```php PHP
  <?php

  use Anthropic\Client;

  $client = new Client();

  $stats = $client->beta->environments->work->stats(getenv('ANTHROPIC_ENVIRONMENT_ID'));

  printf("depth=%d pending=%d\n", $stats->depth, $stats->pending);
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::Client.new

  stats = client.beta.environments.work.stats(ENV.fetch("ANTHROPIC_ENVIRONMENT_ID"))

  puts "depth=#{stats.depth} pending=#{stats.pending}"
  ```
</CodeGroup>

```text wrap
{
  "type": "work_queue_stats",
  "depth": 0,
  "pending": 0,
  "oldest_queued_at": null,
  "workers_polling": 0
}
```

## Stop a session gracefully

Use `POST /v1/environments/{environment_id}/work/{work_id}/stop` (curl; python, typescript, ruby: `client.beta.environments.work.stop()`; go, csharp: `client.Beta.Environments.Work.Stop()`; java: `client.beta().environments().work().stop()`; php: `$client->beta->environments->work->stop()`; cli: `ant beta:environments:work stop`) to ask the worker handling a specific session to shut it down.

By default the work item moves to `stopping`. The worker notices on its next lease heartbeat, cancels the session's in-flight tool call, and confirms the shutdown. The work item then becomes `stopped`.

Pass `force: true` (python: `force=True`; cli: `--force`) to mark the work item `stopped` immediately instead of waiting for the worker's confirmation.

Because these calls run from your operations tooling rather than the worker host, `ANTHROPIC_WORK_ID` isn't set automatically. Set it to the target work item's ID before running the following examples. To find a work item's ID, list the environment's work items through the [Environments Work endpoints](https://platform.claude.com/docs/en/api/beta/environments/work).

<CodeGroup>
  ```bash cURL
  curl -sS "https://api.anthropic.com/v1/environments/$ANTHROPIC_ENVIRONMENT_ID/work/$ANTHROPIC_WORK_ID/stop" \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-beta: managed-agents-2026-04-01" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d '{}'
  ```

  ```bash CLI
  ant beta:environments:work stop \
    --environment-id "$ANTHROPIC_ENVIRONMENT_ID" \
    --work-id "$ANTHROPIC_WORK_ID"
  ```

  ```python Python
  import os

  import anthropic

  client = anthropic.Anthropic()

  work = client.beta.environments.work.stop(
      os.environ["ANTHROPIC_WORK_ID"],
      environment_id=os.environ["ANTHROPIC_ENVIRONMENT_ID"],
  )
  print(work.state)
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";

  const client = new Anthropic();

  const work = await client.beta.environments.work.stop(process.env.ANTHROPIC_WORK_ID!, {
    environment_id: process.env.ANTHROPIC_ENVIRONMENT_ID!
  });

  console.log(work.state);
  ```

  ```csharp C#
  using Anthropic;

  var client = new AnthropicClient();

  var work = await client.Beta.Environments.Work.Stop(
      Environment.GetEnvironmentVariable("ANTHROPIC_WORK_ID")!,
      new()
      {
          EnvironmentID = Environment.GetEnvironmentVariable("ANTHROPIC_ENVIRONMENT_ID")!
      }
  );

  Console.WriteLine(work.State);
  ```

  ```go Go
  package main

  import (
  	"context"
  	"fmt"
  	"os"

  	"github.com/anthropics/anthropic-sdk-go"
  )

  func main() {
  	client := anthropic.NewClient()

  	work, err := client.Beta.Environments.Work.Stop(
  		context.Background(),
  		os.Getenv("ANTHROPIC_WORK_ID"),
  		anthropic.BetaEnvironmentWorkStopParams{
  			EnvironmentID: os.Getenv("ANTHROPIC_ENVIRONMENT_ID"),
  		},
  	)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(work.State)
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.models.beta.environments.work.BetaSelfHostedWork;
  import com.anthropic.models.beta.environments.work.BetaSelfHostedWorkStopRequest;
  import com.anthropic.models.beta.environments.work.WorkStopParams;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      BetaSelfHostedWork work = client.beta().environments().work().stop(
          WorkStopParams.builder()
              .environmentId(System.getenv("ANTHROPIC_ENVIRONMENT_ID"))
              .workId(System.getenv("ANTHROPIC_WORK_ID"))
              .betaSelfHostedWorkStopRequest(BetaSelfHostedWorkStopRequest.builder().build())
              .build()
      );

      IO.println(work.state());
  }
  ```

  ```php PHP
  <?php

  use Anthropic\Client;

  $client = new Client();

  $work = $client->beta->environments->work->stop(
      getenv('ANTHROPIC_WORK_ID'),
      environmentID: getenv('ANTHROPIC_ENVIRONMENT_ID'),
  );

  echo $work->state . "\n";
  ```

  ```ruby Ruby
  require "anthropic"

  client = Anthropic::Client.new

  work = client.beta.environments.work.stop(
    ENV.fetch("ANTHROPIC_WORK_ID"),
    environment_id: ENV.fetch("ANTHROPIC_ENVIRONMENT_ID")
  )

  puts work.state
  ```
</CodeGroup>

## Stop workers gracefully

Cut at 300 lines. The page has the rest.

managed-agents/self-hosted-sandboxes-reference New page · 214 lines, new page

## CLI commands and flags ## Environment variables ## Host requirements ## Sandbox filesystem ## SDK helpers ### EnvironmentWorker ### Work poller ### Session tool runner ### AgentToolContext and the agent toolset

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Self-hosted worker reference
url: https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference
description: "Reference for self-hosted sandbox workers: ant CLI flags, environment variables, host requirements, filesystem paths, and SDK helper options."
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

This page documents the pre-built workers that serve a `self_hosted` environment. For task-oriented guides, start with [Self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes) and [Deploy self-hosted workers](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers).

## CLI commands and flags

| Command                | Description                                                                                                                                      |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ant beta:worker poll` | Claims work items from the environment's queue and runs each session in process. With `--on-work`, calls your script for each work item instead. |
| `ant beta:worker run`  | Handles one claimed session and exits. Use it as the entrypoint of a per-session sandbox.                                                        |

| Flag                | Description                                                                                                                                                                                         |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--environment-id`  | The environment to poll for work. Also reads from `ANTHROPIC_ENVIRONMENT_ID`.                                                                                                                       |
| `--environment-key` | Authenticates the worker with this environment. Also reads from `ANTHROPIC_ENVIRONMENT_KEY`.                                                                                                        |
| `--workdir`         | Directory where skills are downloaded and tools read and write files. Defaults to `.` (the current directory).                                                                                      |
| `--on-work`         | Script to call for each claimed work item instead of running tools in-process. Receives session details as environment variables and the work item as JSON on standard input.                       |
| `--max-idle`        | How long to wait after the session goes idle with an `end_turn` [stop reason](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons) before shutting down. Defaults to `60s`. |
| `--log-format`      | Log output format. Use `json` for structured log ingestion. Defaults to `text`.                                                                                                                     |

## Environment variables

| Variable                        | Description                                      | Set by                                                                                                                                                                                 |
| ------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ANTHROPIC_ENVIRONMENT_ID`      | The environment whose queue the worker serves.   | You, on the worker host. The poller passes it to the `--on-work` script.                                                                                                               |
| `ANTHROPIC_ENVIRONMENT_KEY`     | Authenticates the worker to its queue.           | You, on the worker host. The poller passes it to the `--on-work` script.                                                                                                               |
| `ANTHROPIC_SESSION_ID`          | The session that a claimed work item represents. | The poller, for the `--on-work` script.                                                                                                                                                |
| `ANTHROPIC_WORK_ID`             | The claimed work item.                           | The poller, for the `--on-work` script.                                                                                                                                                |
| `ANTHROPIC_WORK_SECRET`         | The work item's per-session secret.              | You. The poller does not set it. See [Forward the work item's secret](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret). |
| `ANTHROPIC_BASE_URL`            | Overrides the default API endpoint. Optional.    | You, on the worker host.                                                                                                                                                               |
| `ANTHROPIC_WEBHOOK_SIGNING_KEY` | Verifies incoming webhook payloads.              | You, on a webhook handler host.                                                                                                                                                        |

## Host requirements

| Worker             | Requirement                                                                                                              |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| All workers        | A Linux host with `/bin/bash` at that exact path. The worker's bash tool invokes it directly, without consulting `PATH`. |
| TypeScript SDK     | `unzip` and `tar` on the `PATH`, and Node.js 22 or later.                                                                |
| Python and Go SDKs | No additional binaries. These SDKs use their standard libraries for archive extraction.                                  |

[Memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#requirements) add their own requirements.

## Sandbox filesystem

| Path                       | Contents                                                                                                                                                                                                                     |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/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.                                |
| `<workdir>/skills/<name>/` | The agent's downloaded skills.                                                                                                                                                                                               |
| `/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. |

On 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.

Skills can include executables that the agent may run directly. The CLI and SDK workers preserve the executable permissions recorded in the skill bundle when they extract it. If you implement skills download manually, you are responsible for setting executable permissions.

## SDK helpers

The Python, TypeScript, and Go SDKs provide three helpers at different levels of control:

| Helper                                                                                                                                                                                                                                                            | What it does                                                                | Use it when                                                                                                        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [`EnvironmentWorker`](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#environment-worker)                                                                                                                                      | Handles polling, setup, and execution end to end.                           | Most cases.                                                                                                        |
| [`work.poller()` (go: `environments.NewWorkPoller()`)](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#work-poller)                                                                                                            | Polls the work queue and gives you each claimed session.                    | You determine what happens for each session, for example launching a sandbox rather than running tools in-process. |
| [`client.beta.sessions.events.tool_runner()` (typescript: `client.beta.sessions.events.toolRunner()`; go: `client.Beta.Sessions.Events.NewToolRunner()`)](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#session-tool-runner) | Runs tool calls for a single session, given the session ID and a tool list. | You've already claimed the work and only need the execution layer.                                                 |

### EnvironmentWorker

| Method                                                           | Description                                                                                                                                                                                                                                                                                                                                |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `run()` (go: `Run()`)                                            | Runs indefinitely, picking up sessions as they arrive.                                                                                                                                                                                                                                                                                     |
| `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`) | Handles a single claimed work item and returns. Pass the work, session, and environment identifiers and the `work_secret` (typescript: `workSecret`; go: `WorkSecret`) explicitly, or let it read the [`ANTHROPIC_*` variables](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference#environment-variables). |

| Option                                                                                 | Description                                                                                                                                                                                            |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tools` (go: `ToolsFunc`)                                                              | A factory that receives the session's `AgentToolContext` and returns the tool list. Defaults to the standard agent toolset.                                                                            |
| `memory_sync_interval` (typescript: `memorySyncIntervalMs`; go: `MemorySyncInterval`)  | How often attached memory stores reconcile with the server while the session runs. See [Sync interval](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#sync-interval). |
| `memory_sync_deletions` (typescript: `memorySyncDeletions`; go: `MemorySyncDeletions`) | Whether files the agent deletes locally are also deleted from the store. See [Deletions](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory#deletions).                   |

`EnvironmentWorker` manages the `AgentToolContext` and the toolset automatically. Pass a `tools` (go: `ToolsFunc`) factory to customize the tool list:

<CodeGroup exclude="shell">
  ```python Python
  EnvironmentWorker(client, ..., tools=lambda env: [beta_bash_tool(env), my_custom_tool])
  ```

  ```typescript TypeScript
  new EnvironmentWorker({
    client,
    environmentId,
    environmentKey,
    tools: (ctx) => [betaBashTool(ctx), myCustomTool]
  });
  ```

  ```csharp C#
  // EnvironmentWorker is not currently available in the C# SDK.
  // To answer custom tool calls directly, see the session event stream.
  ```

  ```go Go
  worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
  	EnvironmentID:  environmentID,
  	EnvironmentKey: environmentKey,
  	ToolsFunc: func(env *agenttoolset.AgentToolContext) []anthropic.BetaTool {
  		return []anthropic.BetaTool{agenttoolset.BetaBashTool(env), myCustomTool}
  	},
  })
  ```

  ```java Java
  // EnvironmentWorker is not currently available in the Java SDK.
  // To answer custom tool calls directly, see the session event stream.
  ```

  ```php PHP
  // EnvironmentWorker is not currently available in the PHP SDK.
  // To answer custom tool calls directly, see the session event stream.
  ```

  ```ruby Ruby
  # EnvironmentWorker is not currently available in the Ruby SDK.
  # To answer custom tool calls directly, see the session event stream.
  ```
</CodeGroup>

### Work poller

| Option                                                                               | Description                                                                                                                                                                                                                                                                                                                                    |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `drain` (go: `Drain`)                                                                | Whether to stop polling once the queue is empty rather than waiting for new work.                                                                                                                                                                                                                                                              |
| `block_ms` (python; typescript: `blockMs`; go: `BlockMs`)                            | How long each poll waits for work to arrive before returning, in milliseconds. Must be between 1 and 999; the helper re-polls automatically. Pass `null` (typescript; python: `None`; go: `param.Null[int64]()`) for a non-blocking check. Defaults to a 999 ms long-poll.                                                                     |
| `reclaim_older_than_ms` (typescript: `reclaimOlderThanMs`; go: `ReclaimOlderThanMs`) | Re-claims work items that were claimed but never acknowledged within this many milliseconds.                                                                                                                                                                                                                                                   |
| `auto_stop` (typescript: `autoStop`; go: `AutoStop`)                                 | Whether to post a stop signal for each work item once your loop body finishes with it. Set it to `false` (python: `False`; go: `param.NewOpt(false)`) when whatever runs the work item posts the stop itself. `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`) does, and so does a sandbox you launch that owns the stop call. |

For a complete example, see [Launch sandboxes from the SDK poller](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#launch-sandboxes-from-the-sdk-poller).

### Session tool runner

`client.beta.sessions.events.tool_runner()` (typescript: `client.beta.sessions.events.toolRunner()`; go: `client.Beta.Sessions.Events.NewToolRunner()`) takes a tool list as `tools` (go: `Tools`). To build that list, set up `AgentToolContext` yourself and call `beta_agent_toolset_20260401(env)` (typescript: `betaAgentToolset20260401(ctx)`; go: `agenttoolset.BetaAgentToolset20260401(env)`):

<CodeGroup exclude="shell">
  ```python Python
  from anthropic.lib.tools.agent_toolset import (
      AgentToolContext,
      beta_agent_toolset_20260401,
  )

  async with AgentToolContext(
      workdir="/workspace", client=client, session_id=work.data.id
  ) as env:
      # skills downloaded to /workspace/skills/<name>/
      tools = beta_agent_toolset_20260401(env)
  ```

  ```typescript TypeScript
  import {
    setupSkills,
    betaAgentToolset20260401
  } from "@anthropic-ai/sdk/tools/agent-toolset/node";

  const ctx = { workdir: "/workspace", client, sessionId: work.data.id };
  await setupSkills(ctx);
  const tools = betaAgentToolset20260401(ctx);
  ```

  ```csharp C#
  // AgentToolContext is not currently available in the C# SDK.
  ```

  ```go Go
  env := &agenttoolset.AgentToolContext{Workdir: "/workspace"}
  if err := env.SetupSkills(ctx, client, work.Data.ID); err != nil {
  	panic(err)
  }
  // skills downloaded to /workspace/skills/<name>/
  tools := agenttoolset.BetaAgentToolset20260401(env)
  ```

  ```java Java
  // AgentToolContext is not currently available in the Java SDK.
  ```

  ```php PHP
  // AgentToolContext is not currently available in the PHP SDK.
  ```

  ```ruby Ruby
  # AgentToolContext is not currently available in the Ruby SDK.
  ```
</CodeGroup>

### AgentToolContext and the agent toolset

`AgentToolContext` is the execution context for tool calls. It defines the working directory and path policy, and can download the session's skills.

| Option                                                               | Description                                                                                                                 |
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `allowed_roots` (typescript: `allowedRoots`; go: `AllowedRoots`)     | Directories, in addition to the working directory, that the file tools (`read`, `write`, `edit`, `glob`, `grep`) can reach. |
| `read_only_roots` (typescript: `readOnlyRoots`; go: `ReadOnlyRoots`) | Directories under which `write` and `edit` refuse paths.                                                                    |

`EnvironmentWorker` adds the session's memory store directories to `allowed_roots` (typescript: `allowedRoots`; go: `AllowedRoots`) itself, and the directories of stores attached with `access: "read_only"` to `read_only_roots` (typescript: `readOnlyRoots`; go: `ReadOnlyRoots`).

The confinement is a guardrail for the file tools only, not a sandbox. It does not constrain `bash`.

`beta_agent_toolset_20260401(env)` (typescript: `betaAgentToolset20260401(ctx)`; go: `agenttoolset.BetaAgentToolset20260401(env)`) takes an `AgentToolContext` and returns the standard tool implementations (`bash`, `read`, `write`, `edit`, `glob`, `grep`).

managed-agents/self-hosted-sandboxes-workers New page · 919 lines, new page

## Choose a deployment pattern ## Run an always-on worker ## Trigger workers from webhooks ## Run one sandbox per session ### Forward the work item's secret ### Launch sandboxes from the SDK poller ### Run the SDK worker inside the sandbox ## Stage files for a session ## Next steps

A whole new page. There's nothing to diff it against, so here is what it says.

---
title: Deploy self-hosted workers
url: https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers
description: "Choose how self-hosted sandbox workers claim work and where sessions run: always-on or webhook-triggered, in one process or one sandbox per session."
featureMetadata:
  topic:
    title: Managed Agents
    url: https://platform.claude.com/docs/en/managed-agents/overview
  status: beta
  betaHeader: managed-agents-2026-04-01
---

The [quickstart](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#quickstart) runs one `ant` CLI worker that polls continuously and runs every session in one process. This page covers the other ways to run a worker and how to choose between them.

## Choose a deployment pattern

When deploying workers, you need to make two choices: how the worker claims work, and where each session runs.

**How the worker claims work:**

* **Always-on:** A long-running process polls the queue continuously and needs only outbound HTTPS. This is the simplest setup.
* **Webhook-triggered:** A handler wakes on `session.status_run_started` and starts polling. This avoids an idle poller, but requires a [webhook](https://platform.claude.com/docs/en/managed-agents/webhooks) endpoint that Anthropic can reach.

**Where each session runs:**

* **In process:** The worker that claims a session also runs its tool calls, in one shared working directory.
* **Sandbox per session:** A poller launches a fresh sandbox for each claimed session. Choose this for stronger isolation: a fresh filesystem, resource limits, or per-session network controls.

The CLI and SDK workers support different combinations:

| Capability                                                                                            | `ant` CLI                       | SDK (Python, TypeScript, Go) |
| ----------------------------------------------------------------------------------------------------- | ------------------------------- | ---------------------------- |
| Always-on polling                                                                                     | Yes                             | Yes                          |
| Webhook-triggered                                                                                     | No                              | Yes                          |
| Sandbox per session                                                                                   | Yes                             | Yes                          |
| [Memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory)      | Yes, with default sync settings | Yes, with configurable sync  |
| [Custom tools](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-custom-tools) | No                              | Yes                          |

See [Self-hosted worker reference](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-reference) for every CLI flag and SDK option. For more control, call the [Environments Work endpoints](https://platform.claude.com/docs/en/api/beta/environments/work) directly and implement your own worker.

## Run an always-on worker

Both workers authenticate with the [environment key](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#run-your-first-session) from the quickstart.

With the `ant` CLI:

```bash
ant beta:worker poll --workdir /workspace
```

With the SDK, `EnvironmentWorker` does the same work:

<CodeGroup exclude="shell">
  ```python Python
  import asyncio
  import contextlib
  import os
  import signal
  from anthropic import AsyncAnthropic
  from anthropic.lib.environments import EnvironmentWorker


  async def main() -> None:
      environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
      environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
      async with AsyncAnthropic(auth_token=environment_key) as client:
          worker = EnvironmentWorker(
              client,
              environment_id=environment_id,
              environment_key=environment_key,
              workdir="/workspace",
          )
          task = asyncio.create_task(worker.run())
          # Cancelling the task, rather than killing the process, lets the worker stop its
          # in-flight work item and upload changed memory files before it exits.
          loop = asyncio.get_running_loop()
          for signum in (signal.SIGINT, signal.SIGTERM):
              loop.add_signal_handler(signum, task.cancel)
          with contextlib.suppress(asyncio.CancelledError):
              await task


  asyncio.run(main())
  ```

  ```typescript TypeScript
  import Anthropic from "@anthropic-ai/sdk";
  import { EnvironmentWorker } from "@anthropic-ai/sdk/helpers/beta/environments";

  const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
  const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
  const client = new Anthropic({ authToken: environmentKey });
  const controller = new AbortController();
  // Aborting on either signal lets the worker upload changed memory files and remove its
  // store directories before the process exits.
  process.once("SIGINT", () => controller.abort());
  process.once("SIGTERM", () => controller.abort());

  await new EnvironmentWorker({
    client,
    environmentId,
    environmentKey,
    workdir: "/workspace",
    signal: controller.signal
  }).run();
  ```

  ```csharp C#
  // EnvironmentWorker is not currently available in the C# SDK. Use the ant CLI worker instead.
  ```

  ```go Go
  package main

  import (
  	"context"
  	"log"
  	"os"
  	"os/signal"
  	"syscall"

  	"github.com/anthropics/anthropic-sdk-go"
  	"github.com/anthropics/anthropic-sdk-go/lib/environments"
  	"github.com/anthropics/anthropic-sdk-go/option"
  )

  func main() {
  	environmentKey := os.Getenv("ANTHROPIC_ENVIRONMENT_KEY")
  	environmentID := os.Getenv("ANTHROPIC_ENVIRONMENT_ID")

  	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
  	defer stop()

  	client := anthropic.NewClient(option.WithAuthToken(environmentKey))

  	worker := environments.NewEnvironmentWorker(client, environments.EnvironmentWorkerOptions{
  		EnvironmentID:  environmentID,
  		EnvironmentKey: environmentKey,
  		Workdir:        "/workspace",
  	})
  	if err := worker.Run(ctx); err != nil {
  		log.Fatalf("worker: %v", err)
  	}
  }

  ```

  ```java Java
  // EnvironmentWorker is not currently available in the Java SDK. Use the ant CLI worker instead.
  ```

  ```php PHP
  // EnvironmentWorker is not currently available in the PHP SDK. Use the ant CLI worker instead.
  ```

  ```ruby Ruby
  # EnvironmentWorker is not currently available in the Ruby SDK. Use the ant CLI worker instead.
  ```
</CodeGroup>

## Trigger workers from webhooks

<Steps>
  <Step title="Subscribe to session webhooks">
    In the [Console](https://platform.claude.com/settings/workspaces/default/webhooks), define a webhook endpoint that listens for `session.status_run_started` events. See [Webhooks](https://platform.claude.com/docs/en/managed-agents/webhooks) for details.
  </Step>

  <Step title="Export the webhook signing key">
    Along with the environment ID and key from the [quickstart](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#run-your-first-session), export the webhook signing key on your handler host. The handler uses it to verify incoming payloads.

    ```bash
    export ANTHROPIC_WEBHOOK_SIGNING_KEY="whsec_..."
    ```
  </Step>

  <Step title="Implement the webhook handler">
    Invoke the worker when `session.status_run_started` fires. The handler drains the queue and hands each claimed work item to `handle_item()` (typescript: `handleItem()`; go: `HandleItem()`), which downloads skills, executes tool calls, posts results back, and returns.

    <CodeGroup exclude="shell">
      <CodeGroupItem>
        To verify webhook signatures, install the webhooks extra: `pip install "anthropic[webhooks]"`.

        ```python Python
        import asyncio
        import os
        import anthropic
        import standardwebhooks  # installed by the anthropic[webhooks] extra

        environment_key = os.environ["ANTHROPIC_ENVIRONMENT_KEY"]
        environment_id = os.environ["ANTHROPIC_ENVIRONMENT_ID"]
        client = anthropic.AsyncAnthropic(
            auth_token=environment_key,
        )
        # Cancelled by shutdown() so an in-flight work item can upload changed memory files and
        # remove its store directories before the process exits.
        inflight: set[asyncio.Task[None]] = set()


        # Await this from the host's shutdown hook, such as an ASGI lifespan shutdown (the code after
        # `yield` in a FastAPI lifespan), which uvicorn runs on SIGTERM. uvicorn lets open requests
        # finish before that hook runs, so set --timeout-graceful-shutdown to bound the wait.
        async def shutdown() -> None:
            for task in inflight:
                task.cancel()
            await asyncio.gather(*inflight, return_exceptions=True)


        async def handle(raw: bytes, headers: dict[str, str]) -> tuple[dict[str, str], int]:
            try:
                event = client.beta.webhooks.unwrap(raw.decode(), headers=headers)
            except standardwebhooks.WebhookVerificationError:
                return {"error": "signature verification failed"}, 401
            if event.data.type != "session.status_run_started":
                return {"status": "ignored"}, 200
            task = asyncio.create_task(run_queued_work())
            inflight.add(task)
            task.add_done_callback(inflight.discard)
            try:
                # Shielded: a dropped or timed-out delivery must not cancel the item; shutdown() does.
                await asyncio.shield(task)
            except asyncio.CancelledError:
                return {"status": "shutting down"}, 503
            return {"status": "ok"}, 200


        async def run_queued_work() -> None:
            async for work in client.beta.environments.work.poller(
                environment_id=environment_id,
                environment_key=environment_key,
                block_ms=None,
                reclaim_older_than_ms=2000,
                drain=True,
                auto_stop=False,
            ):
                await client.beta.environments.work.worker(workdir="/workspace").handle_item(
                    work_id=work.id,
                    environment_id=environment_id,
                    session_id=work.data.id,
                    environment_key=environment_key,
                    # The per-session secret is what lets the worker mount the session's memory stores.
                    work_secret=work.secret,
                )
        ```
      </CodeGroupItem>

      ```typescript TypeScript
      import Anthropic from "@anthropic-ai/sdk";

      const environmentKey = process.env.ANTHROPIC_ENVIRONMENT_KEY!;
      const environmentId = process.env.ANTHROPIC_ENVIRONMENT_ID!;
      const client = new Anthropic({
        authToken: environmentKey
      });
      // Call shutdown.abort() from the host's SIGTERM/SIGINT handler, alongside closing the server,
      // then wait for in-flight handle() calls before exiting: the abort lets a running work item
      // upload changed memory files and remove its store directories first.
      export const shutdown = new AbortController();

      export async function handle(req: Request): Promise<Response> {
        // Never acknowledge a delivery whose work will not run here; a 503 makes the sender retry.
        if (shutdown.signal.aborted) {
          return Response.json({ status: "shutting down" }, { status: 503 });
        }
        const body = await req.text();
        let event;
        try {
          event = client.beta.webhooks.unwrap(body, { headers: Object.fromEntries(req.headers) });
        } catch {
          return new Response("signature verification failed", { status: 401 });
        }
        if (event.data.type !== "session.status_run_started") {
          return Response.json({ status: "ignored" });
        }

        for await (const work of client.beta.environments.work.poller({
          environmentId,
          environmentKey,
          blockMs: null,
          reclaimOlderThanMs: 2000,
          drain: true,
          autoStop: false,
          signal: shutdown.signal
        })) {
          await client.beta.environments.work.worker({ workdir: "/workspace" }).handleItem({
            workId: work.id,
            environmentId,
            sessionId: work.data.id,
            environmentKey,
            // The per-session secret is what lets the worker mount the session's memory stores.
            workSecret: work.secret ?? undefined,
            signal: shutdown.signal
          });
        }
        // The poller and handleItem return quietly on abort, so a drain cut short lands here.
        if (shutdown.signal.aborted) {
          return Response.json({ status: "shutting down" }, { status: 503 });
        }
        return Response.json({ status: "ok" });
      }
      ```

Cut at 300 lines. The page has the rest.

build-with-claude/claude-on-amazon-bedrock-legacy Changed · +1 / -1 lines

from line 731
731731* [Thinking](https://platform.claude.com/docs/en/build-with-claude/thinking)
732732* [Tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview), including the [Bash tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool), [Computer use tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool), [Memory tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool), and [Text editor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/text-editor-tool)
733733* [Citations](https://platform.claude.com/docs/en/build-with-claude/citations)
734* [Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)
734* [Structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs), for the models in the Amazon Bedrock note under its [Compatibility](https://platform.claude.com/docs/en/build-with-claude/structured-outputs#compatibility) section
735735 
736736### Features not supported
737737 

build-with-claude/claude-platform-on-aws Changed · +1 / -1 lines

from line 563
563563Session behavior on Claude Platform on AWS differs from first-party Claude Managed Agents in two ways:
564564 
565565* **Autonomous-session reauthentication:** A session can run autonomously, without any [user events](https://platform.claude.com/docs/en/managed-agents/reference#event-types), for up to 6 hours. After 6 hours, the session requires reauthentication before it continues. To reauthenticate, send any user-role event to the session (see [Events and streaming](https://platform.claude.com/docs/en/managed-agents/events-and-streaming)). First-party Claude Managed Agents has no autonomous-session runtime limit.
566* **[Memory stores on self-hosted environments](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores):** A session that runs on a self-hosted environment cannot attach memory stores; a session that includes one is rejected at creation. Sessions on cloud environments attach memory stores as usual. On first-party Claude Managed Agents, sessions on both cloud and self-hosted environments can attach memory stores.
566* **[Memory stores on self-hosted environments](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory):** A session that runs on a self-hosted environment cannot attach memory stores; a session that includes one is rejected at creation. Sessions on cloud environments attach memory stores as usual. On first-party Claude Managed Agents, sessions on both cloud and self-hosted environments can attach memory stores.
567567 
568568### Features not supported
569569 

build-with-claude/structured-outputs Changed · +1 / -1 lines

from line 29
2929 Claude Platform on AWS: ga
3030 Amazon Bedrock:
3131 availability: ga
32 note: On Amazon Bedrock, structured outputs are available for Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.5, and Claude Haiku 4.5.
32 note: On Amazon Bedrock, structured outputs are available on the legacy [Amazon Bedrock (Opus 4.6 and earlier)](https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy) integration for Claude Opus 4.6, Claude Sonnet 4.6, Claude Sonnet 4.5, Claude Opus 4.5, and Claude Haiku 4.5, and not on [Claude in Amazon Bedrock](https://platform.claude.com/docs/en/build-with-claude/claude-in-amazon-bedrock).
3333 Google Cloud: ga
3434 Microsoft Foundry: ga
3535---

manage-claude/authentication Changed · +1 / -1 lines

from line 129
129129 
130130The [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) accepts a personal key or service account key only if the key isn't scoped to a specific workspace.
131131 
132You can find a workspace's ID in the **ID** column of [Settings → Workspaces](https://platform.claude.com/settings/workspaces) in the Claude Console, or by calling the [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) endpoint. List Workspaces omits the Default Workspace; its ID is in the `anthropic-workspace-id` [response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response) of any request that runs there.
132You can find a workspace's ID in the **ID** column of [Settings → Workspaces](https://platform.claude.com/settings/workspaces) in the Claude Console, or by calling the [List Workspaces](https://platform.claude.com/docs/en/api/beta/organization/workspaces/list) endpoint. List Workspaces includes the Default Workspace only when you pass `include_default=true`; its ID is also in the `anthropic-workspace-id` [response header](https://platform.claude.com/docs/en/manage-claude/workspaces#identify-the-workspace-behind-an-api-response) of any request that runs there.
133133 
134134<CodeGroup>
135135 ```bash cURL

manage-claude/data-residency Changed · +1 / -1 lines

from line 10
1010* **Workspace geo:** Controls where data is stored at rest and where endpoint processing (such as image transcoding and code execution) happens. Configured at the workspace level in the [Claude Console](https://platform.claude.com).
1111 
1212<Note>
13 [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) supports geographic pinning at the agent level: `inference_geo` on an [agent's model configuration](https://platform.claude.com/docs/en/managed-agents/agent-setup#pin-the-inference-geo) pins the geography that serves model requests for sessions running that agent, with [per-session overrides](https://platform.claude.com/docs/en/managed-agents/sessions#pin-the-inference-geo-for-a-session) at session create. Agents without a pin follow the workspace's default inference geo on each request. Managed Agents also respects the Workspace geo configured in Console, and with [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes), tool execution and the sandbox filesystem stay on infrastructure you control; the contents of attached [memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores) remain stored by Anthropic and are copied to your sandbox for the session.
13 [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) supports geographic pinning at the agent level: `inference_geo` on an [agent's model configuration](https://platform.claude.com/docs/en/managed-agents/agent-setup#pin-the-inference-geo) pins the geography that serves model requests for sessions running that agent, with [per-session overrides](https://platform.claude.com/docs/en/managed-agents/sessions#pin-the-inference-geo-for-a-session) at session create. Agents without a pin follow the workspace's default inference geo on each request. Managed Agents also respects the Workspace geo configured in Console, and with [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes), tool execution and the sandbox filesystem stay on infrastructure you control; the contents of attached [memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory) remain stored by Anthropic and are copied to your sandbox for the session.
1414</Note>
1515 
1616## Inference geo

managed-agents/scheduled-deployments Changed · +1 / -1 lines

from line 18
1818 
1919When 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`.
2020 
21* 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#use-memory-stores) 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.
21* 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`.
2323* In the `schedule`, you define a cron `expression` and a `timezone`. Maximum granularity supported is at the minute level.
2424 

managed-agents/self-hosted-sandboxes-security Changed · +2 / -2 lines

from line 18
1818* **Network egress controls.** Your sandbox's network access is determined by your VPC and firewall rules. Without egress restrictions, a compromised tool execution can reach arbitrary external hosts. Restrict outbound traffic to only the endpoints your tools require.
1919* **Service key storage and rotation.** The environment service key (`ANTHROPIC_ENVIRONMENT_KEY`) authorizes polling your environment's work queue and submitting results back to sessions. Store it in a secrets manager, not in environment files or sandbox images. Rotate it immediately if you suspect exposure.
2020* **Isolating untrusted workloads.** The environment service key is scoped to one environment's work queue. If you run untrusted code inside your sandbox, consider provisioning a separate workspace and environment for each trust boundary. This limits each key to a single user's sessions instead of a shared pool.
21* **Per-session credentials.** Each work item your worker claims can carry a per-session `secret`, which the SDK worker uses in place of the environment service key. Access to [memory stores](https://platform.claude.com/docs/en/managed-agents/memory) requires the `secret`: the memory store endpoints reject the environment key (see [Use memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores)). Pass the `secret` only into the sandbox that serves that session, keep it out of images and shared volumes, and never log it.
21* **Per-session credentials.** Each work item your worker claims can carry a per-session `secret`, which the worker uses in place of the environment service key. Access to [memory stores](https://platform.claude.com/docs/en/managed-agents/memory) requires the `secret`: the memory store endpoints reject the environment key (see [Forward the work item's secret](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-workers#forward-the-work-items-secret)). Pass the `secret` only into the sandbox that serves that session, keep it out of images and shared volumes, and never log it.
2222* **Tool-execution blast radius.** Tools run inside your sandbox with whatever permissions your process has. Apply least privilege to the process user and mount only the directories your tools require.
2323* **Log retention and session content.** Conversation content and tool outputs pass through your worker and stay in your environment. You are responsible for retaining, redacting, or deleting that data in compliance with your own policies. Anthropic has no visibility into what your worker does with session content once delivered.
2424* **Memory store contents.** [Memory stores](https://platform.claude.com/docs/en/managed-agents/memory) remain hosted by Anthropic, including their version history. When a session attaches one, the worker keeps a working copy under `/mnt/memory/` in your sandbox for the session's duration and syncs changes back. The worker deletes that copy when the session ends, but a worker that exits without running its teardown leaves it behind. Cleaning up leftover copies, the permissions on that path, and isolation between sessions that share a filesystem are your responsibility.
25* **Read-only memory stores.** A store attached with `read_only` access is protected from upload, not from local modification. The worker's `write` and `edit` tools refuse to write under its directory, nothing there syncs back, and the memory store endpoints reject writes to it made with the session's `secret`. Other processes in the sandbox can still change the local copy: commands the agent runs through the `bash` tool, and [custom tools](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#serve-custom-tools-from-your-sandbox) or MCP servers you serve from the sandbox, which run with the worker's permissions. Later tool calls in that session read the changed copy until that memory next changes in the store. If the agent must not be able to alter even its local view of such a store, disable the `bash` tool for that agent and give it no custom tool that writes to the sandbox's filesystem.
25* **Read-only memory stores.** A store attached with `read_only` access is protected from upload, not from local modification. The worker's `write` and `edit` tools refuse to write under its directory, nothing there syncs back, and the memory store endpoints reject writes to it made with the session's `secret`. Other processes in the sandbox can still change the local copy: commands the agent runs through the `bash` tool, and [custom tools](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-custom-tools) or MCP servers you serve from the sandbox, which run with the worker's permissions. Later tool calls in that session read the changed copy until that memory next changes in the store. If the agent must not be able to alter even its local view of such a store, disable the `bash` tool for that agent and give it no custom tool that writes to the sandbox's filesystem.
2626 
2727## What Anthropic cannot do for you
2828 

managed-agents/tools Changed · +1 / -1 lines

from line 677
677677 
678678Each custom tool defines a contract: you specify what operations are available and what they return, and Claude determines when and how to call them. The model never executes anything on its own. It emits a structured request, your code runs the operation, and the result flows back into the conversation. See [Session event stream](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#handling-custom-tool-calls) for how to receive custom tool calls and return results during a session.
679679 
680If your sessions run in a self-hosted sandbox, the environment worker can [serve custom tools from your sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#serve-custom-tools-from-your-sandbox), including tools that wrap an MCP server inside your network.
680If your sessions run in a self-hosted sandbox, the environment worker can [serve custom tools from your sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-custom-tools), including tools that wrap an MCP server inside your network.
681681 
682682<CodeGroup defaultLanguage="CLI">
683683 ```bash cURL

release-notes/overview Changed · +1 / -1 lines

from line 102
102102* [Agent Skills](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) and the Skills API (`/v1/skills`) are out of beta on the Claude API. Requests no longer require the `skills-2025-10-02` beta header, including Messages API requests that load Skills through the `container` parameter. Requests that still send the header continue to work unchanged. See [Using Agent Skills with the API](https://platform.claude.com/docs/en/build-with-claude/skills-guide). To move an existing integration off the header, see [Migrate from `skills-2025-10-02`](https://platform.claude.com/docs/en/build-with-claude/skills-guide#migrate-from-skills-2025-10-02).
103103* The [Admin API](https://platform.claude.com/docs/en/api/beta/organization) user-management endpoints for **Claude Enterprise** (claude.ai) organizations (members, invites, groups, and custom roles) are out of beta. The `anthropic-beta: ce-user-management-2026-07-13` header is no longer required on group and custom-role requests; requests that still send it are accepted unchanged. See [User management](https://platform.claude.com/docs/en/manage-claude/user-management).
104104* You can now restrict which sites a Claude Managed Agents agent's `web_search` and `web_fetch` tools can reach. Set `allowed_domains` or `blocked_domains` on the tool's entry in the `agent_toolset_20260401` `configs` array; `web_fetch` also accepts `max_content_tokens` and `web_search` accepts `user_location`. Each `configs` entry is identified by its `name` and typed by an optional `type`, and requests that pass only `name`, `enabled`, and `permission_policy` continue to work; in the typed SDKs, `configs` entries become per-tool types. See [Restrict web search and web fetch domains](https://platform.claude.com/docs/en/managed-agents/tools#restrict-web-search-and-web-fetch-domains).
105* Claude Managed Agents sessions that run in a [self-hosted sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes) can now attach [memory stores](https://platform.claude.com/docs/en/managed-agents/memory). The Python, TypeScript, and Go SDK workers download each attached store into the sandbox at its `mount_path` and sync the agent's changes back to the store. See [Use memory stores](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes#use-memory-stores).
105* Claude Managed Agents sessions that run in a [self-hosted sandbox](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes) can now attach [memory stores](https://platform.claude.com/docs/en/managed-agents/memory). The Python, TypeScript, and Go SDK workers download each attached store into the sandbox at its `mount_path` and sync the agent's changes back to the store. See [Memory stores in self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes-memory).
106106* The session viewer in the Claude Console has been redesigned with a timeline minimap, a transcript grouped by model request, and an Inspector panel for session details and cost, raw events, per-tool statistics, mounted resources, and per-thread activity. See [Console observability](https://platform.claude.com/docs/en/managed-agents/events-and-streaming#console-observability).
107107 
108108### August 18, 2026
Feedback