The four layers¶
Four layers. Three ship today; the fourth does not exist yet and is marked as such.
The load-bearing property is the direction of control: every layer runs in the host constle process, and the agent runs in the sandbox. The agent's private key, the real MCP server URLs, and the real A2A peer endpoints never enter the sandbox at all. The agent talks to per-run gate addresses and nothing else.
Layer by layer¶
Shipped
internal/sandbox/
A Firecracker microVM or a two-network Docker sandbox, in both cases with
no default route. Egress traverses a Squid proxy that allowlists
network.allowed_hosts by name, and a wall-clock kill switch stops the
agent when limits.max_duration_seconds elapses.
Both backends render their proxy policy from the same function, so Docker and Firecracker enforce one ruleset rather than two that drift.
Shipped
internal/identity/ · internal/audit/ · internal/mcpgate/ ·
internal/spending/
A W3C did:key identity whose private key never enters the sandbox; a
JSONL audit log that is Ed25519-signed and hash-chained once a DID is
declared; human approval gates at the MCP proxy; and a per-run and
per-day USD ledger metered at the tool-call boundary.
The daily ledger is durable across runs and keyed by DID, so renaming an agent does not reset its spend.
Shipped
internal/a2a/
Agent-to-agent messages as Ed25519-signed envelopes, exchanged only with peers named in the manifest. The host signs and verifies; the sandbox performs no cryptography and never learns a peer's real endpoint.
There is no discovery mechanism, by design — an agent can only talk to what its manifest declared before it started.
Planned — no code in this repository
Agents discovering and paying each other for work. Direction only; see ROADMAP.md.
Why the direction of control matters¶
Every layer above runs in the host constle process. The agent runs in the
sandbox, and the two are not peers: the agent's private key, the real MCP
server URLs, and the real A2A peer endpoints are all host-side and never
cross the boundary. What the agent sees is a set of per-run gate addresses.
That is the whole security argument, and it is worth stating plainly, because it is what separates Constle from a monitoring overlay:
A control the agent can reach is a control the agent can be talked into disabling. These controls are not reachable from inside the sandbox — not because the agent is trusted to leave them alone, but because there is no route, no key, and no endpoint in there to act on.
A prompt injection that convinces the model to exfiltrate a document does not
fail because the model reconsiders. It fails at the network layer, below the
model, and the attempt is written to the audit log as a network_blocked
event — which is how the operator finds out it happened at all.