Skip to main content

Secrets

Encrypted storage for sensitive values such as API keys and credentials.

Overview

Secrets are associated with a project. Values are encrypted at rest using AES-256-GCM and are never returned by any API response. Once stored, a secret's value can only be replaced. All operations return a has_value boolean to indicate whether an encrypted value is on file.

Secrets can be linked to AI Providers to supply credentials at inference time. See it end to end in Connect Third-Party LLMs - Step 3 (Store provider credentials as secrets) and Step 4 (Create provider records).

See the Permissions Reference for the IAM action strings for this module.

Data Model

FieldTypeDescription
idstringPublic identifier (e.g. sec_…)
project_idstringID of the owning project
namestringHuman-readable label
has_valuebooleantrue when an encrypted value is stored
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-updated timestamp

Key Concepts

Secret References ({{secret:...}})

Any string field that supports secret references can embed a token of the form:

{{secret:sec_01HXYZ...}}

The token — not the raw value — is what gets stored and echoed back by GET/LIST endpoints. The server resolves the token to the decrypted value at the point of use only, e.g. right before an outbound HTTP request. The referenced secret must belong to the same project as the resource that uses it; otherwise the API fails fast with 400 SECRET_NOT_FOUND at create/update time.

Currently supported fields:

ResourceFieldResolved when
Tool (http)execute.url, execute.headers valuesThe tool is called
Tool (mcp)mcp.url, mcp.headers valuesThe MCP server is contacted (tool listing and calls)
{
"execute": {
"url": "https://api.example.com/convert",
"headers": { "Authorization": "Bearer {{secret:sec_01HXYZ}}" }
}
}

To rotate a credential, update the secret's value — every tool referencing it picks up the new value on its next call.

For referencing a secret created in the same Formation template, see Sub Expressions.

Deletion

By default, deleting a secret that is still referenced by one or more AI providers returns 409 Conflict. Pass ?force=true to cascade-delete the dependent AI providers along with the secret.

Configuration

Environment VariableRequiredDescription
SECRETS_ENCRYPTION_KEYYes64-character hex string (32 bytes). Used for AES-256-GCM encryption of all stored secret values.

Generate a key with:

openssl rand -hex 32

Examples

Create a secret

soat create-secret --project-id proj_ABC --name "OpenAI Key" --value "sk-abc123..."

Update secret value

soat update-secret --secret-id sec_01 --value sk-abc123...