Agent Vault Protocol
An open standard for controlling how AI agents access credentials, memory, and environment variables.
Abstract
AVP defines a protocol for controlling how AI agents access credentials, environment variables, and encrypted memory. It specifies a profile-based permission model, a three-state access decision system (allow, deny, redact), an encrypted vault format for credentials and agent memory, a keyword-based memory search algorithm, a portable vault interchange format, a memory bank licensing model, an immutable audit trail, and a session management lifecycle. AVP enables any tool, framework, or platform to implement consistent, auditable, and revocable credential and memory access for AI agents.
Introduction
Why AVP exists and the problem it solves.
The Problem
AI agents — including coding assistants (Cursor, Claude Code, GitHub Copilot), orchestration frameworks (LangChain, CrewAI, AutoGPT), and autonomous systems — routinely execute with full access to the host environment's credentials. There is no standard mechanism to scope, audit, or revoke this access.
Design Principles
Architecture
Components and execution flow of an AVP-compliant implementation.
| Component | Responsibility |
|---|---|
| Vault | Encrypted storage of credentials (secrets) at rest |
| Profiles | Declarative permission rules controlling access |
| Sandbox | Runtime environment filtering based on profile evaluation |
| Audit | Immutable log of all access decisions |
| Sessions | Lifecycle tracking and revocation of agent access |
| Memory | Encrypted storage and keyword-based retrieval of agent knowledge |
| Portable | Import/export of self-contained encrypted vault files |
| License | Enforcement of access terms for purchased memory banks |
| MCP Server | Tool interface for agents to interact with vault, memory, and audit |
1. User invokes agent with a profile
2. Create session (UUID, agent ID, profile name, PID, timestamp)
3. Load credentials from vault + host environment
4. For each credential:
a. Check if system variable → passthrough
b. Evaluate profile rules (last-match-wins)
c. Log access decision to audit trail
d. Apply decision: allow | deny | redact
5. Inject session metadata into environment
6. Spawn agent process with filtered environment
7. On exit: mark session inactiveArchitecture Diagram
Permission Profiles
Declarative YAML-based rules that control credential access.
name: moderate # REQUIRED. Lowercase alphanumeric + hyphens.
description: "Balanced..." # REQUIRED. Human-readable purpose.
trustLevel: 50 # REQUIRED. 0-100 inclusive.
ttlSeconds: 3600 # REQUIRED. Max session duration. 0 = unlimited.
rules: # REQUIRED. Ordered array of rules.
- pattern: "*" # Wildcard — match all
access: deny # One of: allow, deny, redact
- pattern: NODE_ENV # Exact match
access: allow
- pattern: AWS_* # Prefix match
access: redactPattern Matching
| Pattern | Type | Matches |
|---|---|---|
| * | Wildcard | All variable names |
| PREFIX_* | Prefix | Names starting with PREFIX_ |
| EXACT | Exact | Only the exact variable name |
function matchRule(varName, pattern):
if pattern == "*":
return true
if pattern ends with "*":
return varName starts with pattern[0..length-1]
return varName == patternRule Evaluation: Last-Match-Wins
Rules are evaluated in order. The last matching rule determines the access decision. This allows profiles to start with a broad default and layer specific overrides.
function checkAccess(profile, varName):
result = "deny" # Default if no rules match
for each rule in profile.rules: # Iterate in order
if matchRule(varName, rule.pattern):
result = rule.access # Overwrite with latest match
return resultTrust Levels
| Range | Label | Typical Use |
|---|---|---|
| 0–25 | Restrictive | Untrusted or unknown agents. Minimal access. |
| 26–50 | Moderate | Known agents with limited access. Redact sensitive credentials. |
| 51–75 | Elevated | Trusted agents with broad access. |
| 76–100 | Permissive | Fully trusted agents. Allow everything, audit all. |
Access Decision Model
The four-state decision model applied to every credential.
| Decision | Meaning | Behavior |
|---|---|---|
| allow | Credential is permitted | Pass the original value to the agent |
| deny | Credential is forbidden | Exclude the variable entirely |
| redact | Credential is masked | Pass the name with a redaction token as value |
| system | System variable bypass | Pass unconditionally (not logged) |
System Variables
These variables MUST always pass through sandboxing. They are essential for process execution.
PATH HOME USER SHELL TERM LANG LC_ALL TMPDIR NODE_PATHRedaction Format
VAULT_REDACTED_<hex>
# Example:
AWS_SECRET_KEY=VAULT_REDACTED_a1b2c3d4
DATABASE_URL=VAULT_REDACTED_e5f6a7b8
# <hex> = cryptographically random, at least 8 hex chars (4 bytes)
# Each redaction generates a unique tokenVault Encryption
AES-256-GCM encrypted credential storage at rest.
| Parameter | Value |
|---|---|
| Algorithm | AES-256-GCM (authenticated encryption) |
| Key Derivation | scrypt (N=16384, r=8, p=1, output 32 bytes) |
| Salt | Random, 32 bytes per file via CSPRNG. MUST NOT be hardcoded. |
| IV | Random, 16 bytes. New IV per write. |
| Auth Tag | GCM authentication tag (prevents tampering) |
{
"salt": "<hex-encoded random salt (32 bytes)>",
"iv": "<hex-encoded initialization vector>",
"tag": "<hex-encoded authentication tag>",
"data": "<hex-encoded ciphertext>"
}[
{
"key": "AWS_SECRET_KEY",
"value": "sk-abc123...",
"addedAt": "2026-03-03T10:30:00Z"
}
]Encrypted Agent Memory
Encrypted, queryable storage for agent knowledge, cached results, and operational data.
| Field | Type | Required | Description |
|---|---|---|---|
| key | string | Yes | Unique identifier for this entry |
| vaultType | string ("memory") | Yes | MUST be "memory" |
| memoryType | string (enum) | Yes | "knowledge", "query_cache", or "operational" |
| tags | string[] | Yes | Classification tags (MAY be empty) |
| queryHash | string | No | SHA-256 hex digest for exact cache lookup |
| keywords | string[] | Yes | Auto-extracted + user-provided search tokens (max 40) |
| content | string | Yes | The memory content (plaintext when decrypted) |
| confidence | number | Yes | Confidence score [0.0, 1.0] |
| source | string | No | Origin identifier (tool name, URL, agent ID) |
| expiresAt | string (ISO 8601) | No | Expiry timestamp. Entries past this are stale. |
| accessCount | integer | Yes | Times returned in search results |
| addedAt | string (ISO 8601) | Yes | Timestamp of creation or last overwrite |
Memory Types
| Type | Purpose | Typical TTL |
|---|---|---|
| knowledge | Learned facts, documentation, reference material | Long or none |
| query_cache | Cached results of previous queries | Short (hours to days) |
| operational | Runtime state, preferences, configuration | Medium |
Limits & Concurrency
| Constraint | Value | Behavior |
|---|---|---|
| Max entries | 10,000 | MUST reject new entries when reached |
| Max file size | 50 MB | MUST reject new entries when reached |
| Warning threshold | 80% | SHOULD warn when approaching limits |
Memory Search Algorithm
Keyword extraction, SHA-256 cache hits, and ranked scoring.
Keyword Extraction
function extractKeywords(content):
lower = content.toLowerCase()
tokens = split on whitespace + punctuation
tokens = filter(t => t.length >= 3)
tokens = filter(t => t not in STOPWORDS)
tokens = deduplicate(tokens)
return tokens[0..40] # max 40 keywords
# CJK text: extract unigrams + bigrams instead
# No partial matching: "web" does NOT match "webhook"Scoring Algorithm
score = matchRatio × confidence × freshnessMultiplier × recencyBoost
matchRatio = matchingKeywords / queryTokens.length
confidence = entry.confidence (0.0 to 1.0)
freshnessMultiplier = max(0, 1 - ageHours / ttlHours) — 1.0 if no TTL
recencyBoost = 1 + (0.1 × min(accessCount, 10) / 10) — max 1.1
Minimum score threshold: 0.1 (entries below are excluded)
Ties broken by addedAt descending (newer wins)Query Hash (O(1) Cache Hit)
Before keyword ranking, compute SHA-256(query.trim().toLowerCase()). If any entry has a matching queryHash, return it immediately with score 1.0, bypassing the ranking algorithm.
Audit Trail
Immutable log of every credential access decision.
| Field | Type | Description |
|---|---|---|
| id | integer | Auto-incremented sequential identifier |
| sessionId | string (UUID) | Links to the active session |
| agentId | string | Identifies the agent |
| profileName | string | Profile used for evaluation |
| varName | string | Credential name evaluated |
| action | string (enum) | "allow", "deny", or "redact" |
| timestamp | string (ISO 8601) | When the decision was made |
CREATE TABLE audit (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sessionId TEXT NOT NULL,
agentId TEXT NOT NULL,
profileName TEXT NOT NULL,
varName TEXT NOT NULL,
action TEXT NOT NULL,
timestamp TEXT NOT NULL
);Session Management
Lifecycle tracking, metadata injection, and revocation.
| Field | Type | Description |
|---|---|---|
| id | string (UUID v4) | Unique session identifier |
| agentId | string | Agent running in this session |
| profileName | string | Profile applied |
| pid | integer | OS process ID of the agent |
| startedAt | string (ISO 8601) | Session creation time |
| active | boolean | False when revoked or expired |
Created ──▸ Active ──▸ Revoked / Expired
│ │ │
session ID audit logging PID signaled
assigned in progress (SIGTERM)Runtime Metadata Injection
| Variable | Value | Purpose |
|---|---|---|
| AGENTVAULT_SESSION | Session UUID | Agent can identify its session |
| AGENTVAULT_PROFILE | Profile name | Agent knows which profile is active |
| AGENTVAULT_TRUST | Trust level (string) | Agent knows its trust level |
Portable Vault Format
Encrypted interchange format (.avault) for transferring vaults and memories.
{
"schema": "agentvault-portable/1.0",
"exportedAt": "2026-03-09T10:00:00Z",
"entries": [{ "key": "...", "value": "...", "addedAt": "..." }],
"memories": [{ "key": "...", "content": "...", ... }]
}{
"schema": "agentvault-memory/1.0",
"exportedAt": "2026-03-09T10:00:00Z",
"memories": [{ "key": "...", "content": "...", ... }]
}Memory Banks & Licensing
Distributable memory collections with access restrictions.
.agentvault/purchased-banks/<bank-name>/
├── descriptor.json # Bank metadata (plaintext)
├── license.json # Access terms (plaintext)
└── bank.encrypted # Memory entries (encrypted)Access Types
| Type | Time-limited | Access-limited | Description |
|---|---|---|---|
| unlimited | No | No | Perpetual, unrestricted access |
| time_locked | Yes | No | Access until expiry date |
| access_limited | No | Yes | Fixed number of accesses |
| time_and_access | Yes | Yes | Both time and access restrictions |
| subscription | Yes | No | Recurring subscription with renewal |
Directory Structure
Standard layout for AVP data on the filesystem.
.agentvault/
├── profiles/ # Permission profile YAML files
│ ├── restrictive.yml
│ ├── moderate.yml
│ └── permissive.yml
├── vault.json # AES-256-GCM encrypted credentials
├── memory.json # AES-256-GCM encrypted agent memory
├── sessions.json # Active session tracking
├── audit.db # SQLite audit trail
├── mcp-budget.json # MCP rate limit budget tracking
├── purchased-banks/ # Purchased memory banks
│ └── <bank-name>/
│ ├── descriptor.json
│ ├── license.json
│ └── bank.encrypted
├── .passphrase # Encryption passphrase (mode 0600)
└── .gitignore # Contains: * !.gitignore| File | Format | Description |
|---|---|---|
| profiles/*.yml | YAML | Permission profiles |
| vault.json | JSON (encrypted) | Encrypted credentials |
| memory.json | JSON (encrypted) | Encrypted agent memory |
| sessions.json | JSON | Array of Session objects |
| audit.db | SQLite | Audit trail database |
| mcp-budget.json | JSON | MCP rate limit budget |
| purchased-banks/ | Directory | Purchased memory banks |
| .passphrase | Plain text | Encryption passphrase (mode 0600) |
| .gitignore | Text | Prevents accidental commits |
MCP Server Interface
Model Context Protocol tools for agent interaction with vault and memory.
| Tool | Description |
|---|---|
| vault.secret.get | Retrieve a credential by key |
| vault.secret.list | List all credential keys |
| vault.memory.store | Store a memory entry |
| vault.memory.query | Search memories by keyword |
| vault.memory.list | List memory entry metadata |
| vault.memory.remove | Remove a memory entry by key |
| vault.audit.show | Query audit trail entries |
| vault.status | Show vault status (counts, sizes, health) |
| vault.profile.show | Show active profile details |
| vault.preview | Preview access decisions without enforcement |
| vault.export | Export vault/memories to portable format |
Error Contract
// Success
{ "success": true, "data": { ... } }
// Failure
{ "success": false, "error": "Human-readable message", "code": "ERROR_CODE" }| Error Code | Meaning |
|---|---|
| KEY_NOT_FOUND | Requested key does not exist |
| VAULT_LOCKED | Vault cannot be decrypted |
| VAULT_FULL | Entry or size limit reached |
| RATE_LIMITED | Rate limit exceeded (60 calls/min) |
| UNAUTHORIZED | Missing or invalid MCP token |
| INVALID_INPUT | Malformed request parameters |
| DECRYPTION_FAILED | Wrong passphrase or corrupted data |
| LICENSE_EXPIRED | Bank license has expired |
| ACCESS_LIMIT_REACHED | Bank access count exhausted |
Security Considerations
Requirements for secure AVP implementations.
Encryption at Rest
All credentials MUST be encrypted using AES-256-GCM. Decrypted values MUST only exist in memory during sandbox evaluation.
Passphrase Management
The .passphrase file MUST have mode 0600. Implementations SHOULD validate minimum 8 characters.
Process Isolation
The agent MUST run as a child process. Denied variables MUST NOT be present in the child environment. Redaction tokens MUST be cryptographically random.
Audit Integrity
Entries MUST be written before enforcement. The trail MUST be append-only. Individual entry deletion SHOULD NOT be permitted.
.gitignore Protection
The .agentvault/.gitignore MUST prevent accidental commit of sensitive data.
Memory Encryption
All memory entries MUST be encrypted at rest using AES-256-GCM. Decrypted content MUST only exist in memory during search/query operations.
Memory Search Privacy
Query strings are not stored unless explicitly cached via queryHash. Keywords are normalized tokens — original content is not exposed through the index.
Portable Vault Security
Portable files use independent passphrases. Users MUST be warned that .avault files are only as secure as the export passphrase.
License Integrity
License files are plaintext JSON. Implementations SHOULD consider signing license descriptors. The txHash field supports on-chain verification.
Conformance Levels
What implementations must and should support.
Required
- Profile schema and rule matching
- Three-state access model
- System variable passthrough
- Audit trail logging
Recommended
- Everything in Level 1
- Encrypted vault (random salt)
- Session management + revocation
- Encrypted agent memory
- Memory search algorithm
- Standard directory structure
- TTL enforcement
Optional
- Everything in Level 2
- Portable vault format
- Memory banks + licensing
- MCP server interface
- Graceful shutdown
JSON Schemas
encrypted-envelope.schema.jsonEncrypted Envelope
memory-entry.schema.jsonMemory Entry
portable-vault.schema.jsonPortable Vault
memory-portable.schema.jsonMemory Portable
bank-descriptor.schema.jsonBank Descriptor
license-descriptor.schema.jsonLicense Descriptor
mcp-response.schema.jsonMCP Response
profile.schema.jsonProfile + PermissionRule
audit-entry.schema.jsonAudit Entry
vault-entry.schema.jsonVault Entry
session.schema.jsonSession
Additional Resources
Reference inputs/outputs for conformance testing
What AVP protects against and responsible disclosure
Reference Implementation
AgentVault is the reference implementation of AVP Level 3 (Extended conformance).