The master key
The master key is a 32-byte AES-256 key. Everything else is encrypted with it. Default location:0600.
You can move the key elsewhere:
file://path/to/key(default)env://VAR_NAME(for dev only; env vars leak into logs)vault://...(HashiCorp Vault)aws-secretsmanager://arn(AWS Secrets Manager)gcp-secretmanager://projects/.../secrets/...(GCP Secret Manager)azure-keyvault://vault/secret(Azure Key Vault)
The encrypted secret store
Secrets live in thesecrets table in the database. Each row is:
value column is encrypted with the master key, using a
fresh nonce per write. Decryption happens in the orchestrator
process, in memory, at the moment of use. The plain value never
hits disk and never leaves the process.
Secrets are scoped to a company, not global. Two companies on the
same install cannot read each other’s secrets.
Integration credentials
When you connect an integration (Slack, GitHub, Stripe, whatever), the OAuth or API-token flow ends in a call to the secret store. The resulting secret is indexed by the integration ID so the adapter can fetch it on demand. You do not touch the encrypted table by hand. The integrations page at Company → Integrations is the only normal way to create, view the status of, or delete an integration credential. “View” shows metadata (created at, last used at, scopes) but never the value.Agent tokens
Each agent also gets its own identity token, used when the agent’s adapter talks to the MCP server. Agent tokens are stored the same way: encrypted with the master key, indexed by agent ID, rotated on demand. Agent tokens are scoped: a token issued for agent A cannot be used to read memory or call tools on behalf of agent B. The MCP server checks the token on every call.Rotation
Rotating an integration credential
From the dashboard: Integrations → (integration) → Rotate. This kicks off the provider’s rotation flow (a new OAuth refresh, or prompting you to paste a new API key) and swaps the stored value. Any in-flight runs continue to use the old value until they finish; new runs use the new value. From the CLI:Rotating an agent token
Rotating the master key
This is the most sensitive rotation and the one you want to get right. The procedure:- Generates a new 32-byte key
- Decrypts every row in the secrets table with the old key
- Re-encrypts every row with the new key
- Writes the new key to the configured source
- Marks the old key as archived (kept for a grace period so backups taken before the rotation can still be restored)
Secrets in backups
Encrypted secrets are included in backups. The master key is not automatically included. This is on purpose: a backup that includes both the encrypted data and the key is only as secure as the place you put the backup. If you want self-contained backups, you have two options:- Export with
--with-master-key --passphrase <passphrase>, which re-encrypts the master key with a passphrase you provide. Restores require the passphrase. - Back up the master key separately, to a different location, with a different access control, so that losing the backup archive does not mean losing the secrets.
What is not encrypted
The database itself (tables other thansecrets) is not
encrypted by Company Agents. Task contents, comments, memory,
cost entries, and audit events are stored in plain text.
If you need at-rest encryption for the whole database, enable it
at the Postgres layer (Postgres transparent data encryption, or
full-disk encryption underneath). The application layer does not
try to double-encrypt.
Next
- Database for the table the encrypted store lives in
- Storage for the on-disk layout of master keys and backups
- Environment variables for the full set of secret-related env vars