.env files. The vault is the single source of truth for secrets; skills read from it through a scoped accessor, and the LLM never sees a value.
How it works
Secrets are encrypted with AES-256-GCM and stored in asecrets table in Postgres. Each row holds the ciphertext and its initialization vector, never the plaintext. The key that encrypts and decrypts them — SECRET_ENCRYPTION_KEY — is the one secret that has to live outside the vault, in .env.
At runtime a skill calls ctx.secret("nylas_api_key"); the execution layer checks that the skill declared that key, decrypts the value, and hands it to the handler. Every access is audit-logged (which skill, which task, when, and whether the value came from the vault or an env fallback), but the value itself is never written to a log.
What stays in .env
Only the four values needed to reach and unlock the vault, plus non-secret deployment config:
| Variable | Purpose |
|---|---|
DB_USER | PostgreSQL user. |
DB_PASSWORD | PostgreSQL password. |
DATABASE_URL | Postgres connection string (where the vault lives). |
SECRET_ENCRYPTION_KEY | Base64-encoded 32-byte AES-256 master key that decrypts the vault. |
pnpm run setup generates the database password and the master key, writes them to .env, and seeds the rest into the vault.
Seeding secrets
To add or update a secret, set it transiently on the command line and run the seed script. The value is read from the process environment, encrypted, and stored under its canonical vault key:Canonical vault keys
The seed script maps each environment variable to a lowercase snake_case vault key:| Env var (transient) | Vault key |
|---|---|
ANTHROPIC_API_KEY | anthropic_api_key |
OPENAI_API_KEY | openai_api_key |
OPENROUTER_API_KEY | openrouter_api_key |
API_TOKEN | api_token |
WEB_APP_BOOTSTRAP_SECRET | web_app_bootstrap_secret |
NYLAS_API_KEY | nylas_api_key |
NYLAS_GRANT_ID | nylas_grant_id |
NYLAS_SELF_EMAIL | nylas_self_email |
SIGNAL_PHONE_NUMBER | signal_phone_number |
TAVILY_API_KEY | tavily_api_key |
channel.<name>.<field> (e.g. channel.email.nylas_api_key).
Rotating the master key
RotatingSECRET_ENCRYPTION_KEY re-encrypts every stored secret under a new key. Supply both the old and new keys and the database connection:
openssl rand -base64 32. After rotation, replace SECRET_ENCRYPTION_KEY in .env with the new value and recreate the container. Keep the old key until you have confirmed the instance comes up cleanly with the new one.
Skills that require a secret
A skill can declare that a secret must be present before it can be used. Declaring a vault key in the skill manifest’sinstall.requires_secrets makes the registry refuse to install or enable the skill until that key is in the vault. The bundled web-search skill uses this for tavily_api_key — it stays disabled until you provision a Tavily key.
Related pages
Managing skills, agents, and channels
Install and enable capabilities, and how required-secret gates work.
Configuration reference
Every configurable setting, plus the vault and key-rotation commands.