Aegis
Infrastructure Layer for Autonomous Agents
Updated Aug 2026A systems-architecture problem, not a model problem: agent commitments as first-class, event-sourced objects; a policy gateway that enforces constraints at tool-invocation time, not after the fact; durability and recovery strategies for failures that happen mid-workflow, not just at the edges.
This is not a "better LangChain." Agent frameworks handle orchestration—what should the agent do next? Aegis handles infrastructure—how do we ensure commitments are kept across failures? You can run a LangGraph workflow on Aegis to gain durability and verification that LangGraph doesn't provide natively.
The commitment model is built on Grounded Commitment Learning's verifiable-behavior contracts — the research gave the infrastructure its object model, not the other way around.
Status: single-node, 303 tests passing, no performance benchmarks yet and no production deployment. The state, commitment, policy and LLM layers are real, tested code. The recovery, multi-agent, built-in-tool and MCP layers are scaffolded but untested (0% coverage), and several of their handlers return hard-coded success. See Limitations.
The Gap
Workflow Engines (Temporal, Prefect)
State survives restarts. Tasks retry. Execution history is clear. But no agent-specific abstractions: no commitments, no policy evaluation before tool invocation, no multi-agent coordination primitives.
Agent Frameworks (LangChain, AutoGPT)
Tool calling, memory, planning. But state is ephemeral—restart the process and you lose everything. No checkpoint/replay, no formal verification of what the agent promised, no structured recovery.
What's Missing
Neither treats agent commitments as first-class objects. When an agent says "I will complete this task by 5pm," that's a string in a conversation. No mechanism to verify fulfillment, detect violation, or recover gracefully.
Architecture
Requests flow top-to-bottom; events flow bottom-to-top. The state machine coordinates: receives events, applies transitions, triggers checkpoints, notifies listeners.
Core Components
1. Event-Sourced State
State derives from an append-only event log. Each user message, LLM response, tool invocation, and commitment update is an event. Current state computes by replaying events from the last checkpoint.
1class AgentState(BaseModel):
2 model_config = ConfigDict(frozen=True)
3
4 def with_message(self, message: Message) -> AgentState:
5 return self.model_copy(
6 update={
7 "conversation_history": (*self.conversation_history, message),
8 "version": self.version + 1,
9 }
10 )Trade-off: Storage grows with event count; replay adds latency on restore. Configurable checkpoint intervals mitigate this—checkpoint every N transitions or M seconds, whichever comes first.
2. Commitments as First-Class Objects
Commitments use the GCL 5-tuple:(debtor, creditor, action, condition, deadline). The condition field contains an evaluable expression, not a description.
1class RuntimeCommitment(BaseModel):
2 model_config = ConfigDict(frozen=True)
3
4 debtor: str # Who made the commitment
5 creditor: str # Who receives the commitment
6 action: str # What was committed
7 condition: str # Evaluable expression: "task_complete AND error_count == 0"
8 deadline: datetime | None
9 status: CommitmentStatus # CREATED → ACTIVE → FULFILLED/VIOLATED/CANCELLEDThis enables: verification (check if condition holds), violation detection (deadline passed, condition failed), recovery (select and execute strategy), audit (track commitment lifecycle).
3. Policy Enforcement at the Gateway
Policy enforces at invocation time, not planning time. The gateway sees actual arguments—an agent might plan to "read a file" but the actual path could be /etc/passwd.
1class PolicyRule(BaseModel):
2 name: str
3 action: PolicyAction # ALLOW, DENY, REQUIRE_APPROVAL
4 tool_pattern: str # Glob: "file_*", "web_search"
5 argument_conditions: dict[str, Any] # {"path": {"not_contains": "/etc"}}Trade-off: Can't prevent the agent from wasting tokens planning a disallowed action. The cost of a rejected tool call is low compared to the security benefit.
GCL Integration
GCL provides the theoretical foundation; Aegis provides the runtime. The GCL 5-tuple maps directly to RuntimeCommitment:
| GCL Concept | Aegis Implementation |
|---|---|
| Debtor | commitment.debtor (agent ID) |
| Creditor | commitment.creditor (user/system ID) |
| Action | commitment.action (string) |
| Condition | commitment.condition (evaluable expression) |
| Deadline | commitment.deadline (datetime) |
When GCL isn't installed, Aegis falls back to its own expression evaluator. Supports basic comparisons, logical operators, and membership tests. Unsafe expressions (function calls, imports, attribute access) are rejected.
Validation
303 unit tests, all passing (pytest, 2026-09-08, Python 3.13). They live in a single flat tests/unit/directory; the breakdown below is the actual per-file count, not an estimate.
test_llm.py
Client, streaming, providers: 68 tests
test_tools.py
Gateway, policy, auth: 48 tests
test_audit.py
Event log, audit trail: 46 tests
test_api.py
FastAPI routes and schemas: 37 tests
test_gcl.py
GCL integration, verification: 35 tests
test_state.py
Event-sourced state: 24 tests
test_checkpoint.py
Checkpoint integrity: 23 tests
test_state_machine.py
Transitions, validation: 22 tests
What 303 tests does not cover
Line coverage over src/aegis is 41% (4,449 of 8,096 statements unexecuted). Four subsystems have no tests at all and sit at 0%:
recovery/— detector, orchestrator, strategiesmultiagent/— messaging, patterns, protocol, registrytools/builtin/— filesystem, web, code, systemtools/mcp_adapter.py— the MCP transport layer
core/replay.py is at 26% — there is no dedicated replay test. Coverage is highest where the object model is: state.py 97%, gcl/models.py 95%, events.py 92%.
Limitations
Single-node only
State stores locally. Distributed coordination (multiple agents across nodes, shared state) requires a distributed event log (Kafka, Redis Streams) and consensus for checkpoint coordination. Not implemented.
No content-aware policy
Constitutional AI principles check metadata, not content. Evaluating whether a response "contains harmful content" requires an external classifier.
Recovery strategies do not yet execute a recovery
The strategy selection logic — classify a violation, pick a plan, order it by priority — is real. The execution step is not. RetryStrategy.execute() sleeps for its backoff delay and returns a hard-coded {"success": True} above the comment “in a real implementation, this would re-execute the action”; RenegotiateStrategy.execute() does the same without contacting the creditor. Nothing in recovery/ is covered by a test.
The HTTP API and CLI are surface, not implementation
The FastAPI schemas and routing are tested (37 tests), but POST /sessions/{id}/messages returns a literal "This is a placeholder response." rather than invoking an agent, and the CLI's status and replay commands render placeholder data. The tests verify the contract, not that anything is behind it.
No CI, and no property-based tests
The 303 figure comes from running the suite locally; the repository has no CI workflow, so unlike the CNL benchmark there is no reproducible artifact behind it. An earlier version of this page also claimed property-based tests via Hypothesis and multi-agent message-ordering tests; neither exists — Hypothesis is a declared dev dependency that is never imported.
No performance benchmarks
Checkpoint latency, message throughput, and policy evaluation overhead have not been systematically measured under realistic workloads.