Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.agentvault.chat/llms.txt

Use this file to discover all available pages before exploring further.

AgentVault provides end-to-end encryption for all agent-owner communications. The server never sees plaintext — all encryption and decryption happens client-side. MLS (RFC 9420) is the primary encryption protocol for all conversation types, with Double Ratchet + X3DH retained as a fallback for legacy 1:1 sessions. This guide covers the cryptographic primitives, key handling requirements, and forward secrecy guarantees that every integration must follow.
AgentVault’s crypto library (@agentvault/crypto) implements all of these requirements. If you are building a custom integration, follow this guide to ensure compatibility.

Cryptographic Primitives

AgentVault uses a carefully chosen set of modern primitives via libsodium.
PurposeAlgorithmNotes
Group key agreementMLS (RFC 9420)Primary protocol — scalable ratchet tree with per-epoch forward secrecy
Symmetric encryptionXChaCha20-Poly1305AEAD cipher with 192-bit nonce (used by both MLS and Double Ratchet)
Key exchangeX25519 (Curve25519 ECDH)Used in X3DH handshake (Double Ratchet fallback)
Digital signaturesEd25519Identity keys, MLS credentials, message authentication
HashingBLAKE2bInvite token hashing, KDF inputs
Key derivationHKDF-SHA-256Ratchet chain key derivation
AgentVault does not use AES-GCM. The 192-bit nonce in XChaCha20-Poly1305 eliminates nonce reuse risk that plagues AES-GCM’s 96-bit nonce, which is critical for high-throughput messaging where random nonce collisions become statistically significant.

Key Exchange: X3DH (Double Ratchet Fallback)

For legacy 1:1 sessions that have not migrated to MLS, AgentVault uses the Extended Triple Diffie-Hellman (X3DH) protocol to establish shared secrets between an owner and an agent device. New sessions use MLS group creation instead.
1

Identity key generation

Each device generates a long-term Ed25519 identity key pair stored in OS secure storage (Keychain on iOS, Keystore on Android, expo-secure-store cross-platform).
2

Ephemeral key generation

The initiating device generates a one-time X25519 ephemeral key pair for the handshake.
3

Triple DH computation

Three DH computations produce the shared secret:
  • DH(identity_A, ephemeral_B)
  • DH(ephemeral_A, identity_B)
  • DH(ephemeral_A, ephemeral_B)
The results are concatenated and passed through HKDF to derive the initial root key.
4

Double Ratchet initialization

The shared secret seeds the Double Ratchet algorithm for ongoing message encryption.
AgentVault’s X3DH implementation uses synchronous enrollment (both parties are online), so signed prekeys and one-time prekeys are not required. This is acceptable for the agent use case where devices enroll in real-time.

Double Ratchet Protocol (Fallback)

For legacy 1:1 sessions, the Double Ratchet algorithm provides forward secrecy and break-in recovery after the X3DH handshake. New conversations use MLS as the primary protocol.

How It Works

The Double Ratchet combines two ratcheting mechanisms:
  1. Symmetric-key ratchet (chain keys) — Derives a new message key for each message using HKDF. Old keys are deleted after use, providing forward secrecy.
  2. Diffie-Hellman ratchet — Periodically performs a new DH key exchange to provide break-in recovery. If a key is compromised, future messages remain secure after the next DH ratchet step.

Ratchet Advancement

Root Key ──► DH Ratchet Step ──► New Chain Key

                                      ├──► Message Key 1 (deleted after use)
                                      ├──► Message Key 2 (deleted after use)
                                      └──► Message Key 3 (deleted after use)
The ratchet must advance on every message. Reusing a message key breaks forward secrecy and exposes all messages encrypted under that key.

Device Key Handling

Proper key storage is critical to the security model.

Requirements

RequirementImplementation
Private key storageOS secure storage (Keychain, Keystore, expo-secure-store)
Key loggingNever log private key material under any circumstances
Session stateEncrypt local ratchet state at rest
Key deletionDelete message keys immediately after decryption
Debug loggingDisable all crypto debug logs in production builds

Key Types and Lifecycle

  • Generated once per device during enrollment
  • Stored permanently in OS secure storage
  • Used to sign messages and derive DH shared secrets
  • Survives app updates; lost only on device wipe or explicit revocation
  • Generated during X3DH handshake
  • Used once to establish the initial shared secret
  • Deleted after the Double Ratchet is initialized
  • Derived from the root key via HKDF after each DH ratchet step
  • Used to derive individual message keys
  • Advanced (replaced) after each message
  • Derived from the current chain key
  • Used to encrypt/decrypt exactly one message
  • Deleted immediately after use to ensure forward secrecy

Library Choices

The @agentvault/crypto npm package provides a complete implementation of AgentVault’s cryptographic protocols (MLS and Double Ratchet fallback).
npm install @agentvault/crypto
The examples below show the Double Ratchet fallback API. For new integrations, the MLS group API is used automatically by the SecureChannel and AgentVaultClient classes. These lower-level APIs are relevant for custom implementations or legacy session support.
import { DoubleRatchet } from "@agentvault/crypto";

// After X3DH handshake, initialize the ratchet
const ratchet = DoubleRatchet.initSender(sharedSecret, remotePublicKey);

// Encrypt a message
const { header, ciphertext } = await ratchet.encrypt(
  new TextEncoder().encode("Hello, agent!")
);

// Send header + ciphertext to the server (server sees only ciphertext)

Custom Implementations

If you are building a custom integration in a language other than TypeScript, use any libsodium binding that provides:
  • crypto_aead_xchacha20poly1305_ietf_encrypt / decrypt
  • crypto_scalarmult (X25519)
  • crypto_sign_ed25519 keypair generation and signing
  • crypto_generichash (BLAKE2b)
  • crypto_kdf_hkdf_sha256_extract / expand (or equivalent HKDF)
from nacl.public import PrivateKey, Box
from nacl.signing import SigningKey
from nacl.utils import random

# Generate identity key pair
signing_key = SigningKey.generate()
verify_key = signing_key.verify_key

# Generate X25519 key pair for DH
private_key = PrivateKey.generate()
public_key = private_key.public_key

# XChaCha20-Poly1305 encryption via Box
box = Box(private_key, remote_public_key)
ciphertext = box.encrypt(plaintext)

Forward Secrecy Guarantees

AgentVault’s protocols provide multiple levels of forward secrecy:
PropertyMechanismGuarantee
Epoch forward secrecy (MLS)Ratchet tree update on every CommitCompromising an epoch key does not reveal messages from other epochs
Per-message forward secrecy (DR fallback)Symmetric ratchet (chain key advancement)Compromising a message key does not reveal past messages
Break-in recoveryMLS tree update / DH ratchet (periodic re-keying)Compromising a long-term key does not reveal future messages after the next key rotation

Ensuring Forward Secrecy in Your Integration

  1. Delete message keys after use. Never cache or persist decrypted message keys.
  2. Advance the ratchet on every message. Skipping ratchet steps weakens forward secrecy.
  3. Re-key on member removal. When a device is revoked, all remaining sessions must re-key.
  4. Verify epoch consistency. Ensure both parties agree on the current ratchet state.

Validation Tests

Any custom cryptographic integration should pass these test categories before deployment.
CategoryTest
Replay attacksReject messages with previously seen nonces or sequence numbers
Out-of-order deliveryCorrectly decrypt messages received out of order (within the skip window)
Corrupt ciphertextReject tampered ciphertext (Poly1305 MAC verification failure)
Device revocationRefuse to encrypt/decrypt after a device has been revoked
Key deletionVerify that message keys are not recoverable after decryption
Ratchet advancementConfirm that each message produces a unique ciphertext even for identical plaintext

Operational Safeguards

These safeguards are mandatory for production deployments.
SafeguardRationale
Disable debug logs in productionCrypto debug logs may leak key material or plaintext
Validate JWT before any DB accessPrevents unauthorized access to encrypted message store
Rate limit enrollment endpointsPrevents brute-force attacks on the X3DH handshake (5 attempts per IP per 10 minutes)
Use BYTEA columns for crypto materialNever store keys or ciphertext as TEXT — binary storage prevents encoding issues
Generic error messagesAuth and enrollment failures must not leak information about valid identities