Architecture

How Recondo captures, verifies, and persists agent traffic

A Rust gateway terminating TLS in the middle of the agent-to-LLM connection, a content-addressable object store, an append-only PostgreSQL schema, and an operator-controlled control plane.

Stack at a glance

Gateway + CLI Rust
API TypeScript · Fastify · Apollo GraphQL
Dashboard React · Vite · TypeScript
Database SQLite (dev) · PostgreSQL 17 (prod)
Object store Local FS (dev) · S3 with Object Lock (prod)
Encryption KMS customer-managed keys
Infrastructure Terraform (AWS) · Docker Compose (local dev)

Data flow

One request from a coding agent passes through the following pipeline. Steps 2–6 happen inside the gateway process; steps 7+ happen in the persistence layer.

1

Agent issues CONNECT

Agent sends CONNECT api.anthropic.com:443 to the gateway with HTTPS_PROXY set.

2

TLS MITM

Gateway generates a per-host leaf cert signed by its CA. Agent trusts it via NODE_EXTRA_CA_CERTS. TLS terminates inside the gateway.

3

Capture bytes

Request bytes copied into a buffer. Response bytes streamed and accumulated; SSE frames decoded by the stream/ module, WebSocket frames by websocket/.

4

Hash & compress

Each body SHA-256 hashed, gzipped, and written to the content-addressable store at objects/req/<hash> and objects/resp/<hash>.

5

Provider parse

The providers/ module detects the upstream API and extracts model, token counts, cost, tool-call structure, intent metadata.

6

Session detection

session/ bucket-sorts turns into sessions using time gaps, prompt-hash changes, and sequence cues.

7

Persist

One row inserted into sessions (or merged), one into turns, n rows into tool_calls. The capture metadata file is written under captures/{timestamp}_{uuid}.json.

8

Re-encrypt & forward

Gateway opens its own TLS connection upstream, replays the request, streams the response back to the agent.

Gateway modules

The Rust gateway is sliced into focused modules. Each is independently tested and the inter-module boundaries are enforced by an architecture lint (just lint-arch).

tls/

CA generation, per-host leaf certificates, system trust store management

capture/

Request/response interception, capture pipeline orchestration

stream/

SSE stream accumulator for streaming LLM responses

websocket/

WebSocket frame parsing, encoding, masking, and relay

providers/

LLM provider detection and parsing — Anthropic, OpenAI, Gemini

schema/

Core capture data type — CaptureRecord

db/

Session/turn record types and DB ops — SQLite + PostgreSQL

session/

Session boundary detection — time gaps, prompt hash changes, sequences

store/

Content-addressable object storage — local filesystem, S3

storage/

Storage backend abstractions, graph store, pipeline

hash/

SHA-256 content hashing

wal/

Write-ahead log for crash-safe capture persistence

gateway/

Main gateway server — TCP listener, TLS handshake, request routing

operator/

Operator sidecar — runtime control and reporting

Plus operational subsystems: config/, health/, status/, metrics/, alerts/, drift/, artifacts/.

Database schema

Capture-critical tables are append-only — a PostgreSQL trigger refuses any UPDATE or DELETE. What was captured stays captured.

Table Purpose Mutability
sessions Session metadata: provider, model, token/cost totals, intent, git context mutable
turns Turn records with content hashes, token counts, object store refs append-only
tool_calls Tool invocations within a turn append-only
anomaly_events Detected anomalies — prompt injection, secret exposure, drift mutable
access_audit_log Log of API-key access events append-only

Operational tables — alerts, GDPR deletion requests, agent baselines, session risk, export schedules, attachments, heartbeats, policies, registered keys, compliance frameworks — live in api/migrations/.

Storage hardening

  • Append-only capture. turns and tool_calls are write-once. A PostgreSQL trigger blocks UPDATE/DELETE — captures cannot be silently rewritten.
  • Hash-verified bytes. Every body is SHA-256 hashed and stored content-addressed. Run recondo verify <session-id> to re-hash and compare.
  • Encryption at rest. KMS customer-managed keys, S3 server-side encryption. The cloud provider can't read your captures.
  • Encryption in transit. TLS to and from the gateway. The gateway terminates the agent leg only to capture plaintext, then re-encrypts upstream.
  • Object Lock. S3 bucket runs in Object Lock COMPLIANCE mode (365-day retention by default). Deleting from the database is not the same as deleting from the object store.
  • Lifecycle policies. Standard → Infrequent Access at 90 days → Glacier at 365 days.

Read the source

The Recondo repository is the source of truth. The gateway/ directory holds the Rust gateway and CLI; api/ the GraphQL server; dashboard/ the React UI.

Open the repo on GitHub