vaults changedmanaged-agents/vaults
Recorded here
Lines+23added
Lines−23removed
From line
20
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits19to this page, all time
The whole hunk
from line 20, old and new numbered
/
from line 20
2020 Vaults and credentials are workspace-scoped, meaning any API key with workspace access can reference them when creating a session. To revoke access, delete the vault or credential.
2121</Warning>
2222
23A vault is the collection of `credentials` associated with an end user. Give it a `display_name` and optionally tag it with `metadata` so you can map it back to your own user records.
23A vault is the collection of `credentials` associated with an end user. Give it a `display_name` (java, php: `displayName`; csharp, go: `DisplayName`) and optionally tag it with `metadata` (java, php; csharp, go: `Metadata`) so you can map it back to your own user records.
2424
2525<CodeGroup>
2626 ```bash cURL
from line 133
133133
134134Two credential categories are supported:
135135
136* **MCP credentials** (`mcp_oauth`, `static_bearer`): each credential is keyed by an `mcp_server_url`. When the agent connects to a server at that URL at session runtime, the token is injected automatically.
137* **Environment variables** (`environment_variable`): each credential is keyed by a `secret_name` (the environment variable name) and stored in the sandbox as an opaque placeholder. When the agent initiates an outbound request, the opaque placeholder is substituted with the real secret at egress. The agent never sees the secret value. Use this for any service that authenticates through an environment variable, such as CLIs, SDKs, or direct API calls.
136* **MCP credentials** (`mcp_oauth`, `static_bearer`): each credential is keyed by an `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`). When the agent connects to a server at that URL at session runtime, the token is injected automatically.
137* **Environment variables** (`environment_variable`): each credential is keyed by a `secret_name` (java, php: `secretName`; csharp, go: `SecretName`) (the environment variable name) and stored in the sandbox as an opaque placeholder. When the agent initiates an outbound request, the opaque placeholder is substituted with the real secret at egress. The agent never sees the secret value. Use this for any service that authenticates through an environment variable, such as CLIs, SDKs, or direct API calls.
138138
139The actual credential values you supply (`token`, `access_token`, `refresh_token`, `client_secret`, `secret_value`) are treated as sensitive, write-only fields and never returned in API responses.
139The actual credential values you supply (`token` (java, php; csharp, go: `Token`), `access_token` (java, php: `accessToken`; csharp, go: `AccessToken`), `refresh_token` (java, php: `refreshToken`; csharp, go: `RefreshToken`), `client_secret` (java, php: `clientSecret`; csharp, go: `ClientSecret`), `secret_value` (java, php: `secretValue`; csharp, go: `SecretValue`)) are treated as sensitive, write-only fields and never returned in API responses.
140140
141141<Note>
142142 Environment variable credentials (`environment_variable`) are not yet supported with [self-hosted sandboxes](https://platform.claude.com/docs/en/managed-agents/self-hosted-sandboxes).
from line 144
144144
145145<Tabs>
146146 <Tab title="MCP OAuth">
147 Use `mcp_oauth` when the MCP server uses OAuth 2.0. If you supply a `refresh` block, Anthropic refreshes the access token on your behalf when it expires.
147 Use `mcp_oauth` when the MCP server uses OAuth 2.0. If you supply a `refresh` (java, php; csharp, go: `Refresh`) block, Anthropic refreshes the access token on your behalf when it expires.
148148
149149 The `refresh.token_endpoint_auth.type` field indicates how to authenticate the refresh call:
150150
from line 363
363363 ```
364364 </CodeGroup>
365365
366 Set `refresh.token_endpoint` to the token endpoint of the OAuth flow that issued the refresh token, because Anthropic sends every refresh request to that URL and the field can't be changed after the credential is created.
366 Set `refresh.token_endpoint` (java, php: `refresh.tokenEndpoint`; csharp, go: `Refresh.TokenEndpoint`) to the token endpoint of the OAuth flow that issued the refresh token, because Anthropic sends every refresh request to that URL and the field can't be changed after the credential is created.
367367 </Tab>
368368
369369 <Tab title="MCP static bearer">
from line 492
492492 <Tab title="Environment variable">
493493 Use `environment_variable` to authenticate to external services through an environment variable, such as CLIs, SDKs, or direct API calls. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, so check the client eligibility criteria in this tab before configuring one.
494494
495 The `networking.allowed_hosts` array controls which outbound hosts the secret can be substituted for. Use `"type": "limited"` with a specific list, or `"type": "unrestricted"` if the caller reaches domains you can't enumerate in advance.
495 The `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) array in `networking` (java, php; csharp, go: `Networking`) controls which outbound hosts the secret can be substituted for. Use `"type": "limited"` with a specific list, or `"type": "unrestricted"` if the caller reaches domains you can't enumerate in advance.
496496
497497 Limiting domains is strongly recommended for security purposes, and prevents your key from ever being shared with unauthorized hosts.
498498
499499 <Note>
500 `networking.allowed_hosts` on a vault credential controls which requests use the secret, not which requests are allowed. For the agent to actually reach a domain, it must also be allowed at the [environment level](https://platform.claude.com/docs/en/managed-agents/environments). Both levels must include the domain (either through `unrestricted` networking or by explicitly listing the domain in `allowed_hosts`) for a secret-substituted request to succeed.
500 `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (java, php; csharp, go: `Networking`) on a vault credential controls which requests use the secret, not which requests are allowed. For the agent to actually reach a domain, it must also be allowed at the [environment level](https://platform.claude.com/docs/en/managed-agents/environments). Both levels must include the domain (either through `unrestricted` networking or by explicitly listing the domain in `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`)) for a secret-substituted request to succeed.
501501 </Note>
502502
503 The optional `injection_location` field scopes where the secret is substituted; the full semantics follow the example.
503 The optional `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) field scopes where the secret is substituted; the full semantics follow the example.
504504
505505 <CodeGroup>
506506 ```bash cURL
from line 697
697697 ```
698698 </CodeGroup>
699699
700 Request payloads are often assembled from content the agent is working with, so the request body is the broader exposure surface. Most services read an API key from a request header, so enabling only `header` is the narrower configuration. It scopes substitution to request header values for that credential.
700 Request payloads are often assembled from content the agent is working with, so the request body is the broader exposure surface. Most services read an API key from a request header, so enabling only `header` (java, php; csharp, go: `Header`) is the narrower configuration. It scopes substitution to request header values for that credential.
701701
702 The credential's `injection_location` controls which parts of an outbound request the secret is substituted into. It is an optional object, a sibling of `networking`, with two Boolean fields: `header` (request headers) and `body` (request body). `injection_location` is independent of `networking.allowed_hosts`: `allowed_hosts` scopes which hosts the secret is substituted for, and `injection_location` scopes which parts of the request it is substituted into.
702 The credential's `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) controls which parts of an outbound request the secret is substituted into. It is an optional object, a sibling of `networking` (java, php; csharp, go: `Networking`), with two Boolean fields: `header` (java, php; csharp, go: `Header`) (request headers) and `body` (java, php; csharp, go: `Body`) (request body). `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) is independent of `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in `networking` (java, php; csharp, go: `Networking`): `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) scopes which hosts the secret is substituted for, and `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) scopes which parts of the request it is substituted into.
703703
704704 `injection_location` behaves differently on create and on update:
705705
from line 708
708708 | Create credential | If you provide the object, any field you omit inside it defaults to `false`: `{"header": true}` creates a header-only credential. Omit the object entirely and both locations are enabled. |
709709 | Update credential | Fields merge individually: `{"body": false}` disables body substitution and leaves `header` unchanged. |
710710
711 A credential must have at least one location enabled, so a create or update that would disable both locations returns a 400 error. Passing an explicit `null` for the `injection_location` object or for either field also returns a 400 error ("omit the field instead"). The response always returns both fields with their resolved values.
711 A credential must have at least one location enabled, so a create or update that would disable both locations returns a 400 error. Passing an explicit `null` for the `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) object or for either field also returns a 400 error ("omit the field instead"). The response always returns both fields with their resolved values.
712712
713 A placeholder in a disabled location is neither substituted nor stripped. The request is sent to the third party with the literal opaque placeholder string in that location. If a request arrives at the third party containing the literal placeholder string, either that location is disabled for the credential or the destination host is not covered by the credential's `networking.allowed_hosts`.
713 A placeholder in a disabled location is neither substituted nor stripped. The request is sent to the third party with the literal opaque placeholder string in that location. If a request arrives at the third party containing the literal placeholder string, either that location is disabled for the credential or the destination host is not covered by the `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`) in the credential's `networking` (java, php; csharp, go: `Networking`).
714714
715715 <Note>
716716 Credentials created in the Console enable header injection only. If your client sends the secret in the request body, such as a form-encoded token request, the placeholder passes through literally and the service rejects it with its own authentication error. Enable body injection in the Console form when you create the credential, or update the credential with `{"injection_location": {"body": true}}`.
717717 </Note>
718718
719 The substitution happens at egress, not inside the sandbox. Anything that processes the credential locally sees the opaque placeholder, not the real value: clients that validate the credential format at startup may reject it, and clients that compute a request signature from the secret (for example, AWS SigV4) produce an invalid signature. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, in a location the credential's `injection_location` enables.
719 The substitution happens at egress, not inside the sandbox. Anything that processes the credential locally sees the opaque placeholder, not the real value: clients that validate the credential format at startup may reject it, and clients that compute a request signature from the secret (for example, AWS SigV4) produce an invalid signature. Environment variable credentials work for clients that send the secret value verbatim in an outbound request, in a location the credential's `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) enables.
720720
721721 Substitution is outbound only. If a client uses the stored secret to fetch a session token (for example, an OAuth client-credentials grant), the returned token arrives in the sandbox unredacted. For exchange-based flows, perform the exchange yourself and store the resulting token in the vault instead.
722722
from line 730
730730
731731Constraints:
732732
733* **Unique key per vault.** `mcp_server_url` (MCP credentials) and `secret_name` (environment variable credentials) must be unique among active credentials in a vault. Creating a duplicate returns a 409.
734* **Keys are immutable.** To change `mcp_server_url` or `secret_name`, archive the credential and create a new one.
733* **Unique key per vault.** `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) (MCP credentials) and `secret_name` (java, php: `secretName`; csharp, go: `SecretName`) (environment variable credentials) must be unique among active credentials in a vault. Creating a duplicate returns a 409.
734* **Keys are immutable.** To change `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`) or `secret_name` (java, php: `secretName`; csharp, go: `SecretName`), archive the credential and create a new one.
735735* **Maximum 20 credentials per vault.**
736736
737737## Reference the vault at session creation
738738
739Pass `vault_ids` when creating a session:
739Pass `vault_ids` (java: `vaultIds`; php: `vaultIDs`; csharp: `VaultIds`; go: `VaultIDs`) when creating a session:
740740
741741<CodeGroup>
742742 ```bash cURL
from line 835
835835
836836Runtime behavior:
837837
838* When no MCP credential matches by `mcp_server_url`, the connection is attempted unauthenticated and will error if the server requires authentication.
838* When no MCP credential matches by `mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`), the connection is attempted unauthenticated and will error if the server requires authentication.
839839* When multiple vaults contain a matching credential, the first vault with a match wins.
840840* In [multiagent sessions](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration), vault credentials apply to every thread. An agent whose own definition declares the matching MCP server authenticates with these credentials. See [Connect agents to MCP servers](https://platform.claude.com/docs/en/managed-agents/multiagent-orchestration#connect-agents-to-mcp-servers).
841841
842842## Rotate a credential
843843
844Secret values, `display_name`, and (on environment variable credentials) `injection_location` can be updated. `injection_location` updates merge per field, as described in the Environment variable tab of [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential). For a running session, an `injection_location` update propagates the same way as a secret rotation: the session's credentials are re-resolved without a restart, as described in [Credential lifecycle](https://platform.claude.com/docs/en/managed-agents/vaults#credential-lifecycle), and the updated locations apply to the session's subsequent outbound requests. Structural fields (`mcp_server_url`, `secret_name`, `token_endpoint`, `client_id`) are locked after creation. To change them, archive the credential and create a new one.
844Secret values, `display_name` (java, php: `displayName`; csharp, go: `DisplayName`), and (on environment variable credentials) `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) can be updated. `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) updates merge per field, as described in the Environment variable tab of [Add a credential](https://platform.claude.com/docs/en/managed-agents/vaults#add-a-credential). For a running session, an `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`) update propagates the same way as a secret rotation: the session's credentials are re-resolved without a restart, as described in [Credential lifecycle](https://platform.claude.com/docs/en/managed-agents/vaults#credential-lifecycle), and the updated locations apply to the session's subsequent outbound requests. Structural fields (`mcp_server_url` (java: `mcpServerUrl`; php: `mcpServerURL`; csharp: `McpServerUrl`; go: `MCPServerURL`), `secret_name` (java, php: `secretName`; csharp, go: `SecretName`), `token_endpoint` (java, php: `tokenEndpoint`; csharp, go: `TokenEndpoint`), `client_id` (java: `clientId`; php: `clientID`; csharp, go: `ClientID`)) are locked after creation. To change them, archive the credential and create a new one.
845845
846846<CodeGroup>
847847 ```bash cURL
from line 1002
10021002
10031003To diagnose why a refresh failed, call `POST /v1/vaults/{vault_id}/credentials/{credential_id}/mcp_oauth_validate` (or `client.beta.vaults.credentials.mcp_oauth_validate(...)` (typescript: `client.beta.vaults.credentials.mcpOAuthValidate(...)`; csharp: `client.Beta.Vaults.Credentials.McpOAuthValidate(...)`; go: `client.Beta.Vaults.Credentials.MCPOAuthValidate(...)`; java: `client.beta().vaults().credentials().mcpOAuthValidate(...)`; php: `$client->beta->vaults->credentials->mcpOAuthValidate(...)`) in the SDK). This lets you decide how to handle the failure; the right action depends on the error type.
10041004
1005The top-level `status` tells you what to do next:
1005The top-level `status` (java, php; csharp, go: `Status`) tells you what to do next:
10061006
10071007* `valid`: the token works; no action needed.
10081008* `invalid`: the grant is gone or the OAuth server rejected the refresh with a 4xx. Prompt the end user to re-authorize.
No line in this hunk matches that.