agent-vault
Zero-trust credential manager for AI agents.
Give your AI agents access to API keys, database passwords, and other secrets — without ever exposing the raw credentials in plaintext. Secrets are encrypted locally using age encryption and synced via Git. No server, no SaaS, no third-party trust. The Git repo is just an encrypted blob store.
Why agent-vault?
AI agents need credentials to call APIs, connect to databases, and interact with services. But giving an agent a raw API key is risky:
- Keys leak into logs, prompts, and error messages. Even well-designed agents can accidentally expose credentials.
- Revoking access is hard. If you share one key across agents, you can't cut off a single agent without rotating for everyone.
- There's no audit trail. You don't know which agent used which key, or when.
agent-vault solves this with a simple model:
- Each agent gets its own key. Grant and revoke access per-agent, per-secret-group.
- Secrets stay encrypted at rest. The Git repo only ever contains ciphertext. Decryption happens in memory, never touching disk.
- The owner controls everything. One master key to rule them all — add agents, manage access, recover from compromise.
- Git is the sync layer. Push, pull, branch, merge — use the Git workflows you already know.
Quick Start
Install
# From source
# Or from crates.io
# macOS (Homebrew)
Set up a vault
# Store a secret
# Grant the agent access to the "stripe" group
# Retrieve as owner
# Retrieve as agent
That's it. The agent can now decrypt stripe/api-key using its own key. If you revoke access later, the secret is re-encrypted without the agent's key — they lose access immediately.
How It Works
Trust Model
There are two types of keys:
| Key | Location | Purpose |
|---|---|---|
| Owner key | ~/.agent-vault/owner.key |
Master key. Can decrypt everything. Never committed to Git. Back this up. |
| Agent keys | ~/.agent-vault/agents/<name>.key |
Per-agent keys. Can only decrypt secrets in groups they've been granted access to. |
Each agent also has an escrow file committed to the repo — the agent's private key encrypted to the owner's public key. If an agent key is lost, the owner can recover it.
Encryption
Every secret is encrypted using age multi-recipient encryption. The recipient list includes:
- The owner's public key (always)
- Every agent that has been granted access to the secret's group
When you grant or revoke access, agent-vault re-encrypts all affected secrets with the updated recipient list. When you remove-agent, all their secrets are re-encrypted without their key.
Repository Layout
All vault data lives under .agent-vault/ in your Git repo:
.agent-vault/
├── config.yaml # Vault configuration
├── owner.pub # Owner's public key (plaintext, safe to commit)
├── manifest.yaml # Access control: agents → groups → secrets
├── agents/
│ └── my-agent/
│ ├── public.key # Agent's public key
│ └── private.key.escrow # Agent's private key, encrypted to owner
└── secrets/
└── stripe/
├── api-key.enc # Encrypted secret
└── api-key.meta # Plaintext metadata (name, group, timestamps)
Security Guarantees
- Decrypted material is never written to disk — memory or stdout only
- A pre-commit hook blocks commits containing age private keys, PEM keys, RSA keys, EC keys, and OpenSSH keys
.gitignoreblocks*.key,*.pem,**/private.*(but allows*.escrow)- Revocation re-encrypts affected secrets and warns about credential rotation
- Private key files get
chmod 600on Unix
CLI Reference
Vault Management
| Command | Description |
|---|---|
agent-vault init [dir] |
Initialize vault, generate owner keypair, install pre-commit hook |
agent-vault check [--json] |
Audit for expiring credentials, orphaned secrets, manifest inconsistencies |
Agent Management
| Command | Description |
|---|---|
agent-vault add-agent <name> |
Create agent keypair with escrow backup |
agent-vault remove-agent <name> |
Remove agent, re-encrypt all their secrets, warn about rotation |
agent-vault list-agents [--json] |
List agents and their group memberships |
agent-vault recover-agent <name> |
Generate new keypair from escrow, re-encrypt secrets |
agent-vault restore-agent <name> --to <path> |
Restore original key from escrow to a file |
Secret Management
| Command | Description |
|---|---|
agent-vault set <path> <value> [--agents a,b] |
Encrypt and store a secret |
agent-vault set <path> --from-file <file> |
Store secret from file |
agent-vault get <path> [--key <path>] |
Pull latest, decrypt, output to stdout |
agent-vault list [--group <name>] [--json] |
List secrets with metadata |
Access Control
| Command | Description |
|---|---|
agent-vault grant <agent> <group> |
Grant access, re-encrypt group secrets for the agent |
agent-vault revoke <agent> <group> |
Revoke access, re-encrypt group secrets without the agent |
Utilities
| Command | Description |
|---|---|
agent-vault completions <shell> |
Generate shell completions (bash, zsh, fish, powershell) |
Key Resolution
The get command resolves identity keys in this order:
--key <path>flagAGENT_VAULT_KEYenvironment variable (file path or rawAGE-SECRET-KEY-...string)~/.agent-vault/owner.key(default)
SDKs
Python SDK
Read-only SDK for agents to retrieve secrets programmatically. Uses pyrage for age decryption.
=
# Get a secret
=
# List secrets
# Works as a context manager
=
Supports local paths and remote Git URLs:
=
Node.js / TypeScript SDK
Read-only SDK using the age-encryption package.
import { Vault } from "agent-vault";
const vault = new Vault({
repoPath: "/path/to/vault",
keyPath: "~/.agent-vault/agents/my-agent.key",
});
const apiKey = await vault.get("stripe/api-key");
const secrets = vault.listSecrets("stripe");
Environment Variable
All SDKs (and the CLI) support the AGENT_VAULT_KEY environment variable:
# Now no key path needed
MCP Server
agent-vault ships an MCP server so any MCP-compatible AI agent (Claude, etc.) can retrieve credentials through the standard tool-use protocol. The server holds the agent's private key in memory — the agent process never touches key material.
Tools Exposed
| Tool | Description |
|---|---|
agent_vault_get(secret) |
Decrypt and return a secret |
agent_vault_list(group?) |
List available secrets with metadata |
Claude Desktop Configuration
Add to your claude_desktop_config.json:
Claude Code Configuration
Add to your .mcp.json project config:
For AI Agents: Getting Started
If you're an AI agent (or a developer setting up an agent), here's what to do after installation:
1. Get your key
Your operator should have run agent-vault add-agent <your-name> and given you a key file. Store it at:
~/.agent-vault/agents/<your-name>.key
Or set the environment variable:
2. Access secrets
Python:
=
=
TypeScript:
import { Vault } from "agent-vault";
const vault = new Vault({ repoPath: "/path/to/vault" });
const apiKey = await vault.get("stripe/api-key");
CLI:
MCP (no code needed): If your operator configured the MCP server, just call the agent_vault_get tool with the secret path.
3. Handle errors
| Error | Meaning | What to do |
|---|---|---|
SecretNotFoundError |
Secret path doesn't exist | Check the path, ask operator to create the secret |
NotAuthorizedError |
Your key can't decrypt this secret | Ask operator to grant you access to the group |
VaultNotFoundError |
No vault at the repo path, or no key configured | Check repo path and key configuration |
4. Best practices
- Never log or print decrypted secrets. Access them, use them, discard them.
- Don't cache secrets in files. Re-read from the vault each time.
- Use
auto_pull=True(the default) to get the latest secrets on each access. - Handle
NotAuthorizedErrorgracefully. Your access may be revoked at any time.
Deployment Examples
Docker
FROM python:3.12-slim
RUN pip install agent-vault
COPY . /app
WORKDIR /app
CMD ["python", "agent.py"]
# agent.py
=
=
GitHub Actions
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install agent-vault
- run: |
SECRET=$(python -c "
from agent_vault import Vault
v = Vault(repo_path='.', auto_pull=False)
print(v.get('deploy/token'))
")
echo "::add-mask::$SECRET"
echo "DEPLOY_TOKEN=$SECRET" >> "$GITHUB_ENV"
env:
AGENT_VAULT_KEY: ${{ secrets.AGENT_VAULT_KEY }}
CI/CD with CLI
DB_PASSWORD=
API_KEY=
Development
Building from source
# Rust CLI
# Python SDK
# Node.js SDK
Running all tests
# Build the CLI first (Python tests use it)
# Run everything
&& ( && )
Shell Completions
# Bash
# Zsh
# Fish