Skip to content

Secret vaults

A secret vault is an app-scoped, envelope-encrypted bucket of named credentials. Each app designates one vault; platform-side tools (the LLM provider router, the Brave search primitive, MCP servers via auth.tokenRef) resolve credentials from it at call time. The agent’s JS sandbox cannot read secrets directly — they’re tool-internal.

The vault’s storage is envelope encryption: a per-row DEK (AES-256-GCM) wrapped with the platform KEK (TAVORA_SECRET_KEK today; KMS adapter on roadmap).

vault, _ := client.CreateSecretVault(ctx, tavora.CreateSecretVaultInput{
Name: "stripe-prod",
})
_, _ = client.PutSecret(ctx, vault.ID, "stripe_secret_key", "sk_live_...")
view, _ := client.ListSecrets(ctx, vault.ID)
// view = []RedactedSecret{ {Name: "stripe_secret_key", KEKID: "..."} ... }
_ = client.DeleteSecret(ctx, vault.ID, "stripe_secret_key")
_ = client.DeleteSecretVault(ctx, vault.ID)

Each app picks one vault as its designated source. The LLM resolver, Brave search, and MCP auth.tokenRef lookups all read from this vault. Set it via PUT /api/sdk/app/vault (or in the admin UI’s Secrets page):

Terminal window
curl -X PUT https://api.tavora.ai/api/sdk/app/vault \
-H "X-API-Key: tvr_..." \
-H "Content-Type: application/json" \
-d '{"vault_id":"<vault-id>"}'

Pass null to clear the designation; lookups then return “app has no vault designated” errors at the tool boundary.

ToolSecret name (convention)
LLM provider router (Gemini / OpenAI / OpenRouter / Eden / Ollama)gemini_api_key, openai_api_key, openrouter_api_key, edenai_api_key, ollama_base_url
Brave search primitivebrave_api_key
MCP server bearer / header authwhatever name your agent.jsonc → mcp.auth.tokenRef points at

Tools that need a secret but find the app has none designated surface a clear error at call time rather than running with a silently empty credential.

  • Endpoints return 503 when TAVORA_SECRET_KEK is unset on the server.
  • Self-hosted deployments are responsible for rotating TAVORA_SECRET_KEK and updating the wrapped DEKs (a re-wrap CLI ships in tavora-tools).
  • The agent’s JS sandbox has no secret(name) primitive. If you need an agent to drive a credentialed call, expose it via an MCP tool that resolves the secret server-side.