System architecture
Covenant is a single long-running daemon — covenantd — plus a thin set of clients (the CLI, the web UI, third-party tooling over HTTP) and a number of agent processes. The daemon is the only component that holds state; everything else is replaceable.
Component map
┌──────────────────────────────────────────────────────────────┐
│ covenantd │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌────────────┐ │
│ │ IPC │ │ HTTP │ │ MCP │ │ A2A │ │
│ │ socket │ │ gateway │ │ adapter │ │ adapter │ │
│ └────┬─────┘ └────┬─────┘ └─────┬──────┘ └─────┬──────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Server::respond │ │
│ │ (intent dispatch, capability checks, audit, ignore set) │ │
│ └────────┬─────────┬─────────┬─────────┬─────────┬─────────┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ │
│ │Router│ │Runtime│ │Memory│ │ Audit│ │Settlement│ │
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───────┘ │
│ │ │ │ │ │ │
└─────────┼────────┼────────┼────────┼────────┼────────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
cards spawned SQLite JSONL JSONL ← on-chain
on disk processes + audit/ receipts settlement
embeds events programProcess model
covenantd runs as a single process per machine, owned by the operator's user account. It owns:
- a Unix socket at
$COVENANT_HOME/sockfor local clients, - an HTTP listener on
127.0.0.1:8421for browser- facing UIs and third-party tooling (loopback only), - the SQLite memory database at
$COVENANT_HOME/memory.db, - append-only JSONL stores at
audit/events.jsonl,capabilities/granted.jsonl,capabilities/revoked.jsonl, andreceipts/working.jsonl, - the local ed25519 identity key.
Each registered agent runs as a child process spawned on demand when an intent is dispatched. Agents have no direct access to the daemon's state — every interaction goes through the daemon. The runtime wall-clocks each agent against the budget declared in its manifest and kills processes that overrun.
Request lifecycle
- A client (CLI, web UI, third-party caller) sends a
SubmitIntentrequest over the Unix socket or HTTP. - The daemon checks the intent text against the configured ignore set; matches are short-circuited with an
IntentIgnoredaudit event and skipped. - The router scores the intent against registered agent capability cards via keyword overlap and selects the best match (or falls back to an echo response).
- The daemon runs a capability check for the matched agent's required actions. The check writes a
CapabilityCheckaudit event regardless of outcome. A failed check rejects the dispatch withResponse::Error. - On success, the runtime spawns the agent, sends the intent on stdin, reads the result on stdout, and enforces the wall-clock budget.
- The daemon writes a working-tier
MemoryRecord(with an embedding vector if an embedder is configured), aSettlementReceiptfor the resources consumed, and anIntentDispatchedaudit event. - The client receives an
IntentResultwith the intent UUID, the result text, sources, and (when applicable) the receipt.
State on disk
Everything Covenant remembers about its operations sits under $COVENANT_HOME. Default location is ~/.covenant; override with the COVENANT_HOME environment variable.
| Path | Format | Owner |
|---|---|---|
identity/local.key | raw 32 bytes (ed25519 seed) | covenant-identity |
memory.db | SQLite | covenant-memory |
audit/events.jsonl | JSONL, append-only | covenant-audit |
capabilities/granted.jsonl | JSONL, append-only | covenant-permissions |
capabilities/revoked.jsonl | JSONL, append-only (tombstones) | covenant-permissions |
receipts/working.jsonl | JSONL, append-only | covenant-settlement |
agents/*.toml | TOML, one manifest per file | covenant-router |
secrets.toml | TOML | covenant-llm, covenant-tools, covenant-mcp |
.covenantignore | gitignore-style patterns | covenant-memory |
sock | Unix domain socket | covenant-ipc |
Crate layout
The daemon is composed from a number of small Rust crates, each owning one primitive. Each crate exposes a trait + at least two implementations (one for production, one in-memory for tests), which keeps the daemon's wiring straightforward and the test suite fast.
| Crate | Role |
|---|---|
covenant-types | Wire-level types shared by every other crate ( Intent, AgentId, Capability, MemoryRecord, SettlementReceipt). |
covenant-manifest | Parser and validator for agent.toml. |
covenant-router | Loads agent manifests and matches intents to agents via keyword overlap. |
covenant-runtime | Subprocess agent runner with stdin/stdout JSON protocol and a wall-clock budget. |
covenant-memory | Three-tier memory store (SQLite + in-memory) with cosine similarity search over stored vectors. |
covenant-identity | ed25519 identity, on-disk persistence, signing helpers. |
covenant-permissions | Capability tokens — sign, verify, persist, revoke. |
covenant-audit | Append-only audit log with JSONL and in-memory backends. |
covenant-settlement | Settlement primitive: receipts, credits, off-chain accounting that pairs with the on-chain program. |
covenant-llm | Provider trait with mock, Ollama, Anthropic, and OpenAI-compatible implementations. |
covenant-tools | Tool provider trait with mock, Brave, and SerpAPI search implementations. |
covenant-mcp | Model Context Protocol integration — tool trait, registry, native tools, stdio JSON-RPC transport for external servers. |
covenant-a2a | Agent-to-agent task and result envelopes; in-process mailbox. |
covenant-ipc | Length-prefixed JSON IPC protocol for the local socket. |
covenantd | The daemon binary. Wires the primitives together; exposes the IPC and HTTP surfaces. |
covenant | The CLI binary. |
On-chain settlement
The on-chain side of Covenant is a single Anchor program for Solana, deployed under the operator's authority. It implements the credit-mint, consumption, and buyback shape described in Settlement. The daemon batches off-chain receipts and flushes them to the program; once flushed, the receipt's onchain_sig is populated and the receipt is reconcilable from chain state alone.
The program is deliberately small. Bigger token mechanics — oracle integration, DEX routing for buyback — live one layer up and can change without touching the on-chain authority surface.
What is not in scope
Covenant is not an LLM, not an agent framework, and not a chat product. It does not host models, and it does not prescribe how agents should reason. The goal is for an agent stack of any kind — handcrafted, framework-built, fine-tuned end-to-end — to plug into the same primitives so that permissions, memory, identity, and settlement are not each application's problem to solve from scratch.