Secrets
The tenant secrets vault — write-only credentials, referenced by name.
The vault holds your tenant's credentials — API keys, bearer tokens,
connection strings — so they never sit in a graph definition, a trace, or a
log. Tools reference a secret by name (secret_ref); the material is
resolved only inside a dispatch, at the last moment.
Secrets are managed on the dashboard's Secrets page or the /v1/secrets
API, per tenant.
Write-only
The vault's contract:
- You hand the material over once, at create (or rotate). No read path
ever returns it — listing shows metadata only:
name,kind,display_hint(by default the first 4 characters, so you can tellsk-proj-…fromsk-ant-…), and timestamps. - Rotate replaces the material and stamps
rotated_at; everything referencing the name picks up the new value on its next dispatch. - Delete removes it permanently — and anything referencing it stops working. The dashboard says so on the confirm dialog and means it.
Names are slugs (mcp.github, openrouter-prod); kinds are opaque,
bearer, oauth2_tokens, connection_string — the kind is bookkeeping and
AAD-bound (below), not a behavior switch.
How it's stored
In a persistent deployment, material is encrypted with AES-256-GCM before
it touches Postgres: a random nonce per write, and the (tenant, name, kind)
triple bound as authenticated data — a row transplanted to another tenant or
renamed simply fails to decrypt. The master key comes from the
INLAY_SECRET_MASTER_KEY environment variable (a key_version column
supports rotating the master key itself through a dual-read window).
In the in-memory dev mode there is a plaintext, process-local dev vault, loudly marked at boot — for trying things, not for real credentials. OAuth connectors still require the persistent vault (their state lives in Postgres).
Referencing a secret
Anything that takes credentials takes a secret_ref naming a vault entry —
the MCP connector create form is the canonical example:
{ "alias": "github", "url": "https://mcp.github.example/", "auth_kind": "bearer", "secret_ref": "mcp.github" }Graph JSON, traces, and usage rows only ever carry the name. The OAuth
flow is the one writer that stores on your behalf: completing the dance vaults
the tokens as mcp.<alias> automatically.
Next
Schedules — cron-triggered runs that act as an end user.