Vault resolution
Every run ends up with an ordered array of vault_ids baked into its JWT. The relay walks five layers top-down; the first non-empty layer wins.
For the concept of a vault and how credentials are injected, see Credential vaults.

Stacking vaults
When more than one vault is attached, the proxy walks them in the order you pass. Common pattern: a user's personal vault first, the team's shared vault as fallback.
server.ts
await client.threads.run({
agent: "my-agent",
sandboxId: "sbx_123",
vaultIds: [userVaultId, teamVaultId],
messages,
})
// First-match-wins by host pattern:
// userVaultId is checked first for every outbound host
// teamVaultId fills any gaps the user vault doesn't cover![Multi-vault resolution: when vaultIds contains [aliceVault, teamVault], api.github.com and mcp.notion.com resolve to Alice's credentials; mcp.linear.app (no match in Alice's vault) falls through to the team vault.](/_next/image?url=https%3A%2F%2F21st-agents.vercel.app%2F_next%2Fstatic%2Fmedia%2Fcredential-multi-vault-first-match-wins.99db58c8.png&w=3840&q=75)
Multi-tenant agents
For agents that serve multiple end users, tag each user's vault with metadata.external_user_id and pass externalUserId on the run. The relay finds the matching vault automatically.
server.ts
await client.threads.run({
agent: "support-agent",
sandboxId: "sbx_123",
externalUserId: "usr_123",
messages,
})
// Relay looks up vaults where:
// metadata.external_user_id === "usr_123"
⚠️ Warning — Metadata is returned in clear on GET responses. Do not store tokens, passwords, API keys, or client secrets in metadata.
More resources
- Credential vaults — concept, 3-slot model, runtime flow.
- Security & limits — JWT, host matching, TLS, quotas.
- Vaults API reference — REST endpoints for vault + credential CRUD.