Skip to main content
AgentVault is a secure enclave communications platform where AI agent owners communicate with their agents through end-to-end encrypted channels. The server acts solely as an encrypted relay — it never sees plaintext.

Core Security Properties

These four properties are enforced at every layer of the stack — cryptographic, application, and database.
  1. Server never sees plaintext. All encryption and decryption happens client-side.
  2. Closed, invite-only enrollment. No public discovery. Every device is explicitly approved by the owner.
  3. Device-bound keys. Private keys are generated locally and never leave the device.
  4. Strict tenant isolation via RLS. Row-Level Security policies on every database table prevent cross-tenant access.

System Architecture

OWNER (Browser / Mobile)
  Expo App + libsodium (Double Ratchet)
  ├── Auth UI (Clerk)
  ├── Chat UI (E2E encrypted)
  └── Device Enrollment UI


AGENTVAULT BACKEND (FastAPI)
  Stores and relays ciphertext only
  ├── Enrollment Service
  ├── Message Store (BYTEA columns)
  └── WebSocket Relay (Redis pub/sub)


AGENT (OpenClaw / Third-Party)
  Node.js Plugin (@agentvault/agentvault)
  ├── libsodium (Double Ratchet)
  └── OpenClaw Skill Interface

Components

Clients

AgentVault supports three client types, all sharing the same cryptographic library (@agentvault/crypto):
The owner app runs on iOS, Android, and web from a single Expo codebase. It handles:
  • Authentication via Clerk (JWT issuance, session management)
  • Key generation (Ed25519 identity + X25519 ephemeral keypairs)
  • Double Ratchet encryption for every outbound message
  • Device management (invite, approve, revoke)
  • Key storage in platform-appropriate secure storage (SecureStore on native, IndexedDB on web)
The Node.js plugin integrates with OpenClaw and other agent frameworks:
  • 3-line configuration in the agent’s config file
  • Automatic enrollment on first run (key generation, invite consumption, fingerprint display)
  • Persistent encrypted state on disk for subsequent runs
  • WebSocket connection for real-time bidirectional messaging
  • Message handler that decrypts inbound messages, passes them to agent logic, and encrypts responses
A standalone TypeScript SDK for third-party integrations:
  • API key authentication (no Clerk dependency)
  • TOFU key exchange (Trust On First Use)
  • Double Ratchet E2E encryption via the shared crypto library
  • Programmatic access to all AgentVault APIs

Backend (FastAPI)

The backend is a Python FastAPI application that handles:
ResponsibilityDetails
EnrollmentInvite generation, token validation (BLAKE2b hashes only), device approval
Message relayStores ciphertext in PostgreSQL BYTEA columns, relays via WebSocket
WebSocketReal-time bidirectional relay using Redis pub/sub for horizontal scaling
Tenant isolationRLS policies on every table, tenant_id scoping on every query
Rate limitingRedis-backed limits (enrollment: 5/IP/10min, messaging: 60/min)
The backend has no access to private keys, no decryption capabilities, and no plaintext columns. Even a complete backend compromise exposes only ciphertext.

Database (PostgreSQL)

All data is stored in PostgreSQL 16 with Row-Level Security enabled on every table:
  • tenants — Tenant identity and status
  • users — Clerk-authenticated users with RBAC roles
  • devices — Device identity keys (public only), fingerprints, status
  • invites — BLAKE2b hashed tokens (raw tokens never stored)
  • conversations — Owner-to-agent session metadata
  • messagesheader_blob (BYTEA) + ciphertext (BYTEA). No plaintext columns exist.
Every query passes through RLS enforcement:
CREATE POLICY tenant_isolation ON messages
  USING (tenant_id = current_setting('app.current_tenant_id')::uuid);

Cache and Pub/Sub (Redis)

Redis 7 serves two functions:
  1. WebSocket relay — Redis pub/sub routes messages between connected clients, enabling horizontal scaling across multiple backend instances.
  2. Rate limiting — Sliding window counters for enrollment, polling, and messaging endpoints.

Cryptographic Primitives

FunctionPrimitiveWhy
Key exchangeX25519 (Diffie-Hellman)Industry standard via libsodium crypto_scalarmult
SigningEd25519Device identity keys, proof-of-possession during enrollment
Symmetric encryptionXChaCha20-Poly1305192-bit nonce eliminates nonce reuse risk (unlike AES-GCM’s 96-bit nonce)
KDFHKDF-SHA-512Ratchet key derivation
HashingBLAKE2bInvite token hashing, device fingerprints
XChaCha20-Poly1305 was chosen over AES-256-GCM specifically because its 192-bit nonce is safe to generate randomly with negligible collision probability. In a high-volume messaging system, AES-GCM’s 96-bit nonce creates a reuse risk that would result in full plaintext recovery. If FIPS compliance is later required, AES-256-GCM is a swap, not a rewrite.

Protocol Stack

Double Ratchet (1:1 Messaging)

Every owner-to-agent conversation uses the Double Ratchet protocol (the same algorithm underlying Signal):
  1. X3DH key agreement during enrollment establishes a shared secret
  2. Symmetric ratchet advances the chain key with every message
  3. DH ratchet rotates the key agreement with every reply
  4. Forward secrecy — old message keys are deleted after decryption

Message Flow

Owner types a message:
  1. Advance sending chain key
  2. Derive message key via KDF
  3. Generate random 24-byte nonce
  4. Encrypt with XChaCha20-Poly1305
  5. Sign header with Ed25519 identity key
  6. Send {header, signature, ciphertext} via WebSocket

Backend:
  7. Store ciphertext in PostgreSQL (BYTEA)
  8. Relay via Redis pub/sub to recipient

Agent receives:
  9. Verify header signature
  10. Advance receiving chain, derive message key
  11. Decrypt ciphertext
  12. Pass plaintext to agent logic

Infrastructure

ComponentServiceNotes
App serverDigitalOcean Droplet2 vCPU / 4GB, Docker deployment
DatabaseDO Managed PostgreSQL 16Automated backups, SSL, connection pooling
Cache/PubSubDO Managed Redis 7TLS (rediss://), pub/sub for WebSocket relay
AuthClerkJWT issuance, session management, custom domain
FrontendExpo (EAS Build) + VercelNative apps via EAS, web SPA on Vercel
DNS/SSLCloudflareFree tier, DDoS protection

Monorepo Structure

packages/
├── crypto/     # Shared TypeScript: Double Ratchet, X3DH, key generation
├── web/        # Expo universal app (iOS, Android, Web)
├── plugin/     # OpenClaw Node.js plugin
├── client/     # Third-party SDK
├── verify/     # Verification SDK (VCs, DID resolution)
├── site/       # Marketing site (Next.js)
└── backend/    # FastAPI Python backend (never decrypts)
The crypto library is the shared foundation — both the web app and the plugin import it for identical encryption behavior. The backend never imports or uses the crypto library because it never handles plaintext.

What’s Next

Zero-Knowledge Architecture

Deep dive into what the server can and cannot see.

Threat Model

Security goals, threat actors, and mitigations.

Protocol Flows

Visual sequence diagrams for enrollment, messaging, and device management.