This release is a pre-release and may not be stable for production use.
Expectation Ledger
A circuit breaker for AI agents: predict what should happen, compare against what did, and block the next mutation when they diverge.
Expectation Ledger is a zero-dependency Python library that runs inside an AI agent's control loop. Before each action the agent records what it expects; after the action, the result is classified against that prediction; when a high-stakes action contradicts its prediction, a circuit breaker opens and blocks further mutations until a verification step passes.
Most agent safeguards are perimeter controls — ask a human first, or run it in a sandbox. Both limit what an agent can reach. Neither stops an agent from compounding a mistake inside the boundary it was already allowed to operate in, because the agent doesn't know its last action failed. Expectation Ledger closes that gap, in-process, with no model retraining, no prompt engineering, and no external service.
This is not "AI safety" in the alignment sense. It's engineering safety, in the reliability sense — the same principle as a circuit breaker in your house: when something goes wrong, stop the current before it does more damage.
pip install expectation-ledger
How it works
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
│ 1. PREDICT │ ──▶ │ 2. ACT │ ──▶ │ 3. COMPARE │
│ Derive what │ │ Run handler, │ │ Classified │
│ should happen │ │ get result │ │ vs expected │
└──────────────┘ └───────────────┘ └──────┬───────┘
│
┌──────────────▼──────────────┐
│ 4. ENFORCE │
│ Low severity → log/continue │
│ High severity → open breaker│
│ Breaker open → block mutate │
│ Verify pass → close breaker│
└─────────────────────────────┘
Four concepts, zero dependencies:
| Concept | What it is |
|---|---|
| Prediction | What the agent expects to happen — an invariant + success evidence + known failure modes |
| PredictionOutcome | What actually happened — classified as matched, contradicted, or unknown |
| PolicyRule | What to do for each severity × stakes combination (continue, log, board, force-verify) |
| BreakerState | An open/closed circuit breaker — blocks new mutations until verified safe |
Quick start
from expectation_ledger import (
Prediction,
BreakerState,
compare_prediction,
update_breaker,
breaker_blocks,
)
# 1. Before acting: state what you expect
prediction = Prediction(
prediction_id="apply-config-1",
transition="apply_config:nginx",
expected="config file is written and nginx reload succeeds",
invariant="existing unrelated config files are unchanged",
success_evidence="handler returns ok=True with verification status",
failure_modes=["permission denied", "syntax error", "reload failed"],
)
# 2. Act — your agent does something here...
result = {"ok": False, "status": "syntax_error", "error": "unexpected '}' on line 12"}
# 3. Compare
stakes = "high"
outcome = compare_prediction(prediction, result, stakes)
# outcome.result → "contradicted", outcome.severity → "high"
# 4. Enforce
breaker = BreakerState()
breaker = update_breaker(breaker, "apply_config", "nginx", [outcome], None)
# breaker.state → "open"
# 5. Breaker blocks the next mutation
if breaker_blocks(breaker, "apply_config", {"apply_config", "deploy"}):
print("blocked — must verify before mutating again")
# 6. After verification passes, breaker closes
verify_result = {"ok": True, "status": "syntax_check_passed"}
verify_outcome = compare_prediction(
Prediction("verify-1", "verify:dashboard", "syntax check passes", "", "", []),
verify_result,
"high",
)
breaker = update_breaker(breaker, "verify", "nginx", [verify_outcome], None)
# breaker.state → "closed" — agent can mutate again
How it compares
| Capability | Expectation Ledger | Prompt-based guardrails | External approval | Sandbox |
|---|---|---|---|---|
| Runs in-process (no network, no service) | ✓ | ✓ | ✗ | ✗ |
| Structured pass/fail comparison | ✓ | ✗ | — | — |
| Severity routing (low/medium/high) | ✓ | — | — | — |
| Self-blocking (agent stops itself on failure) | ✓ | ✗ | ✗ | — |
| Verified recovery path | ✓ | — | — | — |
| Audit trail (every prediction/outcome recorded) | ✓ | ✗ | ✓ | — |
| Framework-agnostic | ✓ | ✓ | ✓ | ✗ |
Expectation Ledger vs. prompt-based guardrails
Prompt-based guardrails ("think step by step," "verify before answering") are cheap and easy but have no enforcement mechanism — the model can ignore them under pressure or in long contexts. Expectation Ledger is structural: it compares structured output against structured predictions, and the breaker is code, not prose.
Expectation Ledger vs. external approval
Asking a human to approve every action works for low-frequency changes but doesn't scale to an agent that runs dozens of operations per minute. Expectation Ledger is designed for agents that already have operator approval for the category of work they're doing — it catches the unexpected failures inside approved operations, not the decision to operate at all.
Expectation Ledger vs. sandboxing
Sandboxes prevent an agent from reaching beyond a boundary. Expectation Ledger prevents an agent from compounding a mistake inside the boundary. They're complementary — a sandbox limits blast radius; Expectation Ledger stops the agent from chaining errors within that radius.
Using it with your agent
Expectation Ledger is not a service. It's a library you import and call at two points in your agent's control loop:
- Before acting: call your prediction source to generate
Predictionobjects - After acting: call
compare_prediction(), thenevaluate_policy(), thenupdate_breaker()
Two thin adapters ship in the box:
- Hermes —
expectation_ledger.adapters.hermes.build_ledger_context_block()andledger_response_frame_overlay()for response frame integration - OpenClaw / generic —
expectation_ledger.adapters.openclaw.build_context_packet()for pre-model context assembly
For a worked example of wiring Expectation Ledger into a Hermes engineering control loop, see examples/hermes_integration.py.
Expectation Ledger is also available as part of the Memorant suite, where it works alongside Memorant (trusted long-term claims) and Context Tuner (compression audit) for end-to-end agent memory governance. See Memorant and Hermes Context Tuner.
FAQ
What is Expectation Ledger?
Expectation Ledger is an open-source Python library that adds a circuit breaker to an AI agent's control loop. The agent predicts what an action should do, compares the actual result against that prediction, and blocks further mutations when a high-stakes action contradicts what was expected.
How is this different from prompt-based guardrails?
Prompt instructions like "verify before answering" have no enforcement mechanism — a model can ignore them under pressure or in a long context. Expectation Ledger compares structured output against structured predictions, and the breaker is code rather than prose.
Does it replace human approval or sandboxing?
No — it's complementary. A sandbox limits how far an agent can reach; human approval gates whether it acts at all. Expectation Ledger catches unexpected failures inside operations that were already approved, and stops the agent from chaining errors after one.
What is a circuit breaker in this context?
The same pattern used in distributed systems (Hystrix, resilience4j): when an operation fails in a way that suggests further attempts will also fail, the breaker opens and blocks subsequent calls until a health check passes. Here the failure signal is a prediction that was contradicted, and the health check is a verification step.
Does it require an LLM call, a network connection, or a service?
No. Expectation Ledger is a pure-Python library with zero dependencies. It makes no network calls and invokes no model.
Which agent frameworks does it work with?
It's framework-agnostic — two functions called at two points in any control loop. Thin adapters for Hermes and OpenClaw ship in the box; anything else uses the core API directly.
Is Expectation Ledger production-ready?
No. It's alpha (v0.1.0-alpha.x). Core types, severity routing, the policy table, breaker logic, and framework adapters are implemented and tested. Frequency-based prediction sources, similar-prediction retrieval, and breaker persistence are still to come.
Project status
Alpha (v0.1.0-alpha.x). Core types, severity routing, policy table, breaker logic, and framework adapters are implemented and tested. Future work includes frequency-based prediction sources, kNN retrieval for similar-prediction lookup, and breaker persistence backends.
License
Apache License 2.0. See LICENSE.
Metadata
Release files for expectation-ledger 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| expectation_ledger-0.1.0a1.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| expectation_ledger-0.1.0a1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 33.6 kB
Release files / expectation_ledger-0.1.0a1.tar.gz
| Download URL | expectation_ledger-0.1.0a1.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2876b07c809aadf667785b3589f3d9eced9228e0ac597e4ba6491a7665f405b0
|
|
BLAKE2b-256 checksum How to use checksums |
5b55ce679292781b05421444a754fb833b46dbe04db7b04506a871e403162716
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / expectation_ledger-0.1.0a1-py3-none-any.whl
| Download URL | expectation_ledger-0.1.0a1-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
04fd44492e2aba73ee24a0c59908bc1254a89f5c9d890a9ee06f7df148f9965d
|
|
BLAKE2b-256 checksum How to use checksums |
8c6c94dee50cb718b80d33599730effc33e6a51ab9e21b362a98e7a22c87e3a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|