Skip to Content
GuideCredential Vault
View .md

Credential Vault

The credential vault provides encrypted storage for external service credentials (GitHub, AWS, Slack, etc.). Credentials are encrypted with a key derived from the agent’s Ed25519 private key — only that specific agent instance can decrypt its own vault.

Why a Vault

AI agents need credentials to interact with external services. Without a vault, humans end up pasting API keys into chat, hardcoding secrets in configs, or giving agents unrestricted access. The vault solves this:

  • Store once, use forever — Human provides the credential once; the agent retrieves it in any future session
  • Encrypted at rest — AES-256-GCM encryption, key never leaves the agent’s machine
  • Agent-scoped — Only the agent that stored the credential can decrypt it
  • Irrecoverable by design — If the agent’s keypair is deleted, the credentials are gone

Encryption Model

Agent's Ed25519 private key (PKCS8 DER) ▼ HKDF-SHA256 (salt: "agent-id-vault-v1", info: "vault-encryption") ▼ 256-bit symmetric key ▼ AES-256-GCM (random 96-bit IV per credential) ▼ Ciphertext + 128-bit authentication tag ▼ Stored as JSON: { iv, data, tag } (hex-encoded, mode 0600)

Storing Credentials

There are three secure methods to provide credentials to the vault, listed from most to least secure:

Option A: From File (Most Secure)

The secret never appears on the command line or in chat logs:

echo 'ghp_xxx' > /tmp/tok && chmod 600 /tmp/tok node cli.mjs vault-store --service github --type api-key --credential-file /tmp/tok rm /tmp/tok

Option B: From Environment Variable

export GITHUB_TOKEN=ghp_xxx node cli.mjs vault-store --service github --type api-key --credential-env GITHUB_TOKEN

Option C: Via Stdin Pipe

echo 'ghp_xxx' | node cli.mjs vault-store --service github --type api-key

Security Comparison

MethodSecret in ps?In shell history?In chat log?
--credential-fileNoNoNo
--credential-envNoDepends on shellNo
stdin pipeNoThe echo line, yesNo
--credential flagYesYesNo
Paste in chatNoNoYes

Prefer --credential-file or --credential-env. The --credential flag puts the secret in the process argument list, visible via ps.

Credential Types

Use --type to tag what kind of credential it is:

TypeDescriptionNotes
api-keyAPI key / personal access tokenDefault
passwordUsername + password pairUse with --username
oauthOAuth access/refresh token
bearerBearer token
customAnything else

Store Examples

# GitHub personal access token (from file) echo 'ghp_abc123' > /tmp/cred && chmod 600 /tmp/cred node cli.mjs vault-store --service github --type api-key --credential-file /tmp/cred rm /tmp/cred # AWS credentials (from env) node cli.mjs vault-store --service aws --type api-key \ --credential-env AWS_SECRET_ACCESS_KEY \ --username "$AWS_ACCESS_KEY_ID" \ --url "https://aws.amazon.com" # Service with username + password (piped) echo 'mypassword' | node cli.mjs vault-store --service docker-hub \ --type password --username "myuser" --url "https://hub.docker.com" # OAuth token node cli.mjs vault-store --service slack --type oauth --credential-env SLACK_BOT_TOKEN

Retrieving Credentials

node cli.mjs vault-get --service github

Returns:

{ "ok": true, "service": "github", "type": "api-key", "credential": "ghp_xxx..." }

Use the credential value in API calls:

TOKEN=$(node cli.mjs vault-get --service github | jq -r .credential) curl -H "Authorization: Bearer $TOKEN" https://api.github.com/user

The credential is decrypted in memory and never written to disk in plaintext.

Listing Credentials

node cli.mjs vault-list

Returns a list of services with metadata (type, URL, username) without decrypting the credential values.

Removing Credentials

node cli.mjs vault-remove --service github

Updating Credentials

Run vault-store again with the same --service name. The existing credential is replaced; the original creation timestamp is preserved.

Next Steps

Last updated on