Credential Management
Add, edit, and hot-reload credentials on agents without restarting them. Includes direct file injection, encrypted storage, OAuth flows, and subscription token management.
Overview
Trinity uses a direct file injection system. Credentials are written as .env (KEY=VALUE) and .mcp.json (generated from template) directly to the agent container.
A template says which credentials its agent needs in template.yaml: credentials: lists the variable names, and the optional sibling credential_setup: describes each one. The Setup Checklist on the Credentials tab is the per-variable view: what this agent needs, which are already set, and where to get the missing ones.
Credentials can be exported to encrypted .credentials.enc files (AES-256-GCM) for backup and import.
The Setup Checklist
Open the agent detail page and click the Credentials tab. The checklist answers three questions per credential:
| Column | Where it comes from |
|---|---|
| What does this agent need? | The declaration in the agent's live workspace template.yaml — so a forked or hand-edited agent reports its actual requirements, not its original template's |
| Is it set? | A bounded probe of the agent's own .env, reporting key names that have a non-empty value. Values are never read or transmitted. |
| Where do I get it? | The template author's setup_url, rendered with a canonical host so the link's label can never disagree with its destination |
Fill in the values you have and submit — the checklist writes through the same owner-gated injection path as everything else on this tab.
The checklist renders even when the agent is stopped: you can see what an agent will need before starting it, with the live-status column honestly reported as unavailable. If the status probe fails, you are told so — a failed probe is never shown as “nothing configured”.
Reading this checklist is owner-only and human-only: it is an operator surface, and agent-scoped API keys are rejected.

Declaring Credentials in a Template
credentials:
env_file:
- OPENAI_API_KEY
mcp_servers:
slack:
env_vars:
- SLACK_BOT_TOKEN
credential_setup:
- name: OPENAI_API_KEY
title: OpenAI API key
description: Lets the agent call OpenAI models directly.
required: true
secret: true
setup_url: https://platform.openai.com/api-keyscredentials: is names-only and will never accept per-variable objects — that is what keeps older Trinity versions able to read a newer template. All the human-facing detail lives in credential_setup:, where each entry may carry title, description, required, secret, format, setup_url, and a non-secret default.
Two rules make the pair safe:
credential_setup: entry must name a variable that credentials: declares. An entry naming anything else is dropped with a named error; its valid siblings survive.secret defaults to true and setup_url must be https with no embedded userinfo, so a credential is masked until an author says otherwise and a setup link cannot impersonate a vendor domain.
The full contract is published at docs/schemas/trinity-agent-credentials.schema.json.
Adding Credentials
Add credentials using one of four methods:
• Setup checklist — Per-variable inputs, with descriptions and setup links.
• Manual entry — Name, value, and service fields.
• Bulk import — Paste .env-style KEY=VALUE pairs.
• From encrypted backup — Import a .credentials.enc file.
Hot-reload — Paste or edit credentials on a running agent. The .env file is updated and .mcp.json is regenerated immediately. No restart needed.
Credential Pattern
The credential file pattern inside each agent:
.env # Source of truth (KEY=VALUE)
.mcp.json.template # Template with ${VAR} placeholders
.mcp.json # Generated at runtime from template + .envWhich Files Can Be Injected
Injection accepts a curated set of credential file types, not just .env. Anything outside the allow-list — and anything on the deny-list — is rejected with a 400.
Allowed
| Path | Typical use |
|---|---|
| .env, .credentials.enc, .mcp.json | Core credential files (workspace root only) |
| .config/gcloud/** | Google Cloud SDK credentials / service-account JSON |
| .kube/config | Kubernetes kubeconfig |
| *.pem, *.key, *.crt, *.cert, *.p12, *.pfx | TLS certificates and private keys |
| .ssh/id_* | SSH key pairs (keys only — not authorized_keys or config) |
Always blocked (deny takes precedence): anything executed or sourced at startup — shell startup files (.bashrc, .profile, .zshrc, …), agent instruction files (CLAUDE.md, AGENTS.md, .claude/**), .mcp.json.template, .ssh/authorized_keys / .ssh/config, .git/** and .gitconfig, anything under bin/, plus absolute paths and .. traversal. .mcp.json content is structurally validated before it is written.
Binary credentials (certificates, keystores, service-account bundles) round-trip as base64 via the files_b64 field on the inject endpoint.
Export and Import
Export creates an encrypted .credentials.enc file for backup. It captures the full injected credential set — every allow-listed credential file present in the agent (discovered live), text and binary alike — not just .env and .mcp.json. Import decrypts and injects credentials from an encrypted file; the archive is re-validated against the same path policy on the way in. Auto-import runs on agent startup via POST /api/internal/decrypt-and-inject.
Credential values are never logged. All operations use structured logging with values masked.
Rotating the Encryption Key
The platform encryption key (CREDENTIAL_ENCRYPTION_KEY) can be rotated online, with zero downtime and no data loss:
Back up the database (scripts/deploy/backup-database.sh).
Generate a new key: python3 -c "import secrets; print(secrets.token_hex(32))".
In .env, set the new key as CREDENTIAL_ENCRYPTION_KEY and move the previous key to CREDENTIAL_ENCRYPTION_KEY_SECONDARY (a decrypt-only fallback).
Restart the backend — existing secrets keep decrypting via the secondary key; all new writes use the new key.
Re-encrypt persisted secrets onto the new key: docker compose exec backend python scripts/deploy/rotate-credential-key.py (dry-run), then re-run with --apply.
Remove CREDENTIAL_ENCRYPTION_KEY_SECONDARY from .env and restart.
The sweep re-encrypts every database-persisted token (subscriptions, channel bot tokens, GitHub PATs, payment credentials). Per-agent .credentials.enc files re-encrypt onto the new key on their next credential operation; they keep opening via the secondary key until then.
Credential API
| Endpoint | Method | Description |
|---|---|---|
| /api/agents/{name}/credential-requirements | GET | Per-variable checklist: declaration joined against live set/missing status. Owner-only and human-only; rate-limited. Returns a degraded body (not an error) for a stopped agent. |
| /api/agents/{name}/credentials/status | GET | Check credential files |
| /api/agents/{name}/credentials/inject | POST | Inject files directly |
| /api/agents/{name}/credentials/export | POST | Export to .credentials.enc |
| /api/agents/{name}/credentials/import | POST | Import from encrypted file |
OAuth Credentials
OAuth2 authentication flows for connecting agents to external services like Google, Slack, GitHub, and Notion.
Open the agent's Credentials tab.
Click the OAuth provider button (Google, Slack, GitHub, or Notion).
Your browser redirects to the provider's authorization page.
After you approve access, credentials are normalized to MCP-compatible format and injected into the agent.
Supported Providers
• Google — Gmail, Calendar, Drive, and other Google Workspace services
• Slack — Workspace access for messaging and channel operations
• GitHub — Repository access, issues, pull requests
• Notion — Page and database access
OAuth tokens are stored in Redis with AOF persistence. When an OAuth flow completes, Trinity normalizes the token data, regenerates the agent's .mcp.json, and makes the credentials available to all configured MCP servers.
Subscription Credentials
Share Claude Max/Pro subscription tokens across multiple agents, with automatic assignment, health monitoring, and auto-switch on rate limits.
Key Concepts
How It Works
Go to the Settings page.
In the Subscriptions section, click Register Subscription.
Enter a subscription name and token. The subscription is encrypted and stored.
Expand a subscription row to see assigned agents with assign/unassign controls.
Encryption Requirement
CREDENTIAL_ENCRYPTION_KEY must be set in .env. This is auto-generated by start.sh on fresh deployments. If missing, a warning banner appears on the Settings page, the Register button is disabled, and the API returns 503.
Subscription API
| Endpoint | Method | Description |
|---|---|---|
| /api/subscriptions | GET | List all subscriptions |
| /api/subscriptions | POST | Register a subscription |
| /api/subscriptions/{id}/assign | POST | Assign to an agent |
| /api/subscriptions/{id}/unassign | POST | Unassign from an agent |
Security Best Practices
.env or .mcp.jsonto git — only commit templates and encrypted filesCREDENTIAL_ENCRYPTION_KEY separately from encrypted credential files