Skip to content

Commit 3b60694

Browse files
committed
docs: re-anchor README on live-state replay and recovery
Lead with replay-under-live-state and executed recovery (decision #5); move the Auditable Agents paper to Citation as evidence, not the banner. The quickstart now shows the executed rollback through the gate (verified). State the v0.1 boundary honestly and position the data layer (PyOD, v0.2) at roadmap altitude without exposing the private method.
1 parent a374f40 commit 3b60694

1 file changed

Lines changed: 58 additions & 37 deletions

File tree

README.md

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@
22

33
# auditable
44

5-
**Capture, replay, and audit the decisions your AI agents make.**
6-
7-
*AI Risk Audit and Control across Agents, Foundation Models, and Data.*
5+
**Re-decide an agent's action against the state that is live now, and recover when it no longer holds.**
86

97
[![PyPI](https://img.shields.io/pypi/v/auditable.svg)](https://pypi.org/project/auditable/)
108
[![Python](https://img.shields.io/pypi/pyversions/auditable.svg)](https://pypi.org/project/auditable/)
119
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
1210
[![Stars](https://img.shields.io/github/stars/yzhao062/auditable.svg?style=social)](https://github.com/yzhao062/auditable)
1311

12+
[Quickstart](#60-second-quickstart) · [How It Works](#how-it-works) · [The Full Chain](#the-full-chain) · [Roadmap](#roadmap)
13+
1414
</div>
1515

16-
`auditable` is an open-source SDK that makes an AI agent's decisions reconstructable after the fact. For every consequential action your agent takes, it captures a signed record of what the agent read, which model decided, and what the agent did, then lets you **replay** that decision under the state that was actually live and route a fix: allow, block, hand off, or roll back.
16+
`auditable` is an open-source SDK for the moment after an agent acts. For every consequential decision it captures a signed record of what the agent read, the dependency state the decision relied on, which model decided, and the action taken. Later it **replays** that decision against the state that is live now, and when the action no longer holds it **executes** a fix through a rail: allow, block, hand to a human, or roll back.
1717

18-
> By [Yue Zhao](https://github.com/yzhao062), creator of [PyOD](https://github.com/yzhao062/pyod) (42M+ downloads). Built on the Auditable Agents framework ([arXiv:2604.05485](https://arxiv.org/abs/2604.05485)).
18+
> [!NOTE]
19+
> By [Yue Zhao](https://github.com/yzhao062), creator of [PyOD](https://github.com/yzhao062/pyod) (42M+ downloads, ~12k citations). `auditable` holds each layer to PyOD's bar: a method with data and an experiment behind it before that layer is promoted.
1920
2021
## The Problem
2122

22-
Most agent tools log *what happened*. They do not record *what the agent relied on when it decided*, so when a payment, an approval, or a tool call later looks wrong, the budget, the policy, and the allow-list that were live at that moment are already gone. The action was reasoned; the dependency it trusted had drifted. By the time anyone asks, the decision can no longer be reconstructed.
23+
Most agent tools log what happened. They do not record what the agent relied on when it decided, so when a payment, an approval, or a tool call later looks wrong, the budget, the policy, and the allow-list that were live at that moment are already gone. The action was reasoned; the dependency it trusted had drifted. Flagging that after the fact is observability. Re-deciding under the current state and reversing the action is recovery, and recovery is the gap `auditable` fills.
2324

2425
## Install
2526

@@ -30,65 +31,85 @@ pip install auditable
3031
## 60-Second Quickstart
3132

3233
```python
33-
from auditable import Action, DependencySnapshot, audit, replay
34+
from auditable import (
35+
Action, ActionGate, DependencySnapshot, ReferenceLedger, audit, replay,
36+
)
3437

3538
def policy(state, action):
3639
ok = action.cost <= state.get("budget_remaining", 0)
3740
return ok, ("within budget" if ok else f"${action.cost:,.0f} over budget")
3841

39-
# Capture the decision with the dependency snapshot it relied on.
42+
# The agent pays $4,200 against a budget snapshot, through a rail (the money moves).
4043
snapshot = DependencySnapshot(state={"budget_remaining": 10000})
44+
ledger = ReferenceLedger(balance=10000)
45+
gate = ActionGate(ledger)
46+
action = Action("vendor_payment", {"recipient": "acme"}, cost=4200)
47+
4148
with audit("vendor_payment", snapshot=snapshot) as d:
42-
d.model("gpt-x", decision_basis="invoice matches approved PO")
43-
d.act(Action("vendor_payment", {"recipient": "acme"}, cost=4200))
49+
d.model("gpt-x", decision_basis="invoice matches an approved PO")
50+
d.act(action)
51+
receipt = gate.commit(action) # the agent actually pays; balance is now 5,800
4452

45-
# Later, replay it against the live state. The budget has since dropped.
53+
# Later the live budget has dropped. Replay re-decides; the gate executes the fix.
4654
verdict = replay(d.record, live_state={"budget_remaining": 3000}, policy=policy)
47-
print(verdict.action, verdict.reason)
48-
# FixAction.ROLLBACK Decision relied on stale dependency state: $4,200 over budget
55+
outcome = gate.enforce_post_commit(verdict, receipt=receipt)
56+
print(verdict.action.value, "->", outcome.executed) # rollback -> rolled_back
57+
print("balance restored:", ledger.balance) # 10000
4958
```
5059

51-
See [`examples/payment_audit.py`](examples/payment_audit.py) for the full flagship demo.
60+
See [`examples/payment_audit.py`](examples/payment_audit.py) for the full demo that binds all three layers, and [`examples/standalone_report.py`](examples/standalone_report.py) for scoring a single layer on its own.
5261

5362
## How It Works
5463

55-
One agent decision crosses three layers, and `auditable` records all three in a single signed, hash-chained record:
64+
One agent decision crosses three layers, and `auditable` binds all three in a single signed, hash-chained record:
5665

57-
| Layer | What It Captures |
58-
|---|---|
59-
| **Data** | What the agent read: inputs, retrieved context, and the dependency snapshot (budget, policy, allow-list, config versions) that was live |
60-
| **Model** | Which model produced the output, and the stated decision basis |
61-
| **Harness** | The action the agent executed, and its cost |
66+
| Layer | What the record binds | Signal in v0.1 |
67+
|---|---|---|
68+
| **Data** | What the agent read and the dependency snapshot it relied on | Snapshot freshness |
69+
| **Model** | Which model produced the output, and its stated basis | Decision-basis trust flag |
70+
| **Harness** | The action executed and its cost | A static rule, plus the replay verdict |
6271

63-
`replay()` re-derives whether the action is still justified under the live dependency state versus the snapshot the agent actually used. A decision that passed on a stale snapshot but fails on live state is exactly the failure `auditable` exists to catch.
72+
`replay()` re-derives whether the action still holds under the live dependency state versus the snapshot the agent used, and returns one of four verdicts: `ALLOW`, `ROLLBACK` (justified on the snapshot but not on live state, the stale-state case), `BLOCK` (justified on neither), or `HUMAN_REVIEW`. The `ActionGate` then executes that verdict through a rail, so a rollback reverses the action rather than printing a recommendation. Replay is pure: it never mutates the signed record.
6473

65-
## The Full Chain: AI Risk Audit and Control across Agents, Foundation Models, and Data
74+
## The Full Chain
6675

67-
A single agent decision crosses the whole stack, so one `auditable` record already spans all three layers, and the library is built to connect a signal source at each:
76+
The data, model, and harness signals live in one record, so a decision is judged as a unit rather than as three disconnected logs. Each layer's check is a standalone module (an `Auditor` that returns a signed `Report`), and the same modules compose into the decision record. Each layer deepens on its own cadence, and the method behind it carries its own benchmark before it is promoted.
6877

69-
| Layer | What the record captures | Signal source it connects |
78+
| Layer | v0.1 (shipping) | Deepens to |
7079
|---|---|---|
71-
| **Agent (harness)** | The action executed, its cost, and the replayable verdict | Native (shipping now) |
72-
| **Foundation model** | Which model produced the output, and the stated basis | TrustLLM trust and behavior signals (roadmap) |
73-
| **Data** | What the agent read, and the dependency snapshot it relied on | [PyOD](https://github.com/yzhao062/pyod) anomaly scores on inputs and retrieved context (roadmap) |
80+
| **Harness (agent)** | signed record, replay, executed gate over a rail | dynamic rules layered on static rules |
81+
| **Data** | snapshot freshness | anomaly detection on the data a decision relied on, [PyOD](https://github.com/yzhao062/pyod) lineage (v0.2) |
82+
| **Model** | decision-basis trust flag | [TrustLLM](https://github.com/HowieHwong/TrustLLM) trust signals (v0.3) |
7483

75-
The agent decision is the spine. `auditable` starts there, captures the full chain in one signed record, and brings the data-layer and model-layer signals in as plug-in inputs. That is the main line, delivered through one replayable decision record that threads all three layers.
84+
> [!IMPORTANT]
85+
> **v0.1 scope, stated honestly.** The full chain, replay under live state, and executed recovery through a rail-neutral gate ship today, with thin but real data and model signals bound into the record and two sinks (in-memory and append-only JSONL). The deep PyOD and TrustLLM methods, the calibrated cross-layer risk, and the data and model control faces are on the [roadmap](#roadmap). v0.1 does not yet claim a learned data-anomaly method or a model-trust score.
7686
77-
**v0 scope (honest):** the decision record spans all three layers, and the agent-decision capture and replay ship today. The PyOD and TrustLLM signal integrations that fill the data and model spans are on the [roadmap](#roadmap); `auditable` does not yet score data anomalies or model trust itself.
87+
## Using a Single Layer
7888

79-
## Roadmap
89+
Each layer's check runs on its own, with no agent and no chain, and returns a signed report:
8090

81-
The path to the full chain, one signal source at a time:
91+
```python
92+
import time
93+
from auditable import DataAuditor, DependencySnapshot
94+
95+
snapshot = DependencySnapshot(state={"budget_remaining": 1000}, captured_at=time.time() - 7 * 86400)
96+
report = DataAuditor(max_age_seconds=86400).assess(snapshot)
97+
print(report.flag, report.score) # stale 1.0
98+
```
99+
100+
The composition (capture, replay, recovery) is the main line; the standalone modules are inputs to it.
101+
102+
## Roadmap
82103

83-
- [ ] **Agent layer**: LangChain callback integration (`auditable.integrations.langchain`)
84-
- [ ] **Data layer**: anomaly-triggered surfacing via [PyOD](https://github.com/yzhao062/pyod), flag which decisions to replay from anomalies in what the agent read
85-
- [ ] **Model layer**: TrustLLM trust and behavior signals attached to the model span
86-
- [ ] Pluggable sinks (file, OpenTelemetry, LangSmith, Datadog)
87-
- [ ] Signed, exportable evidence bundles
104+
- [ ] **v0.2 Data** anomaly detection on the dependency state ([PyOD](https://github.com/yzhao062/pyod)), plus a calibrated cross-layer risk
105+
- [ ] **v0.3 Model** TrustLLM trust and behavior signals on the model span
106+
- [ ] **v0.4 Control** data refresh or quarantine, model fallback or sign-off
107+
- [ ] **v1.0** pluggable sinks (OpenTelemetry, LangSmith), exportable evidence bundles, a stable public API
108+
- [ ] Framework integrations (LangChain, LangGraph, CrewAI) and an MCP server
88109

89110
## Citation
90111

91-
If you use `auditable` in research, please cite the Auditable Agents framework:
112+
If you use `auditable` in research, the decision-audit approach builds on the Auditable Agents framework:
92113

93114
```bibtex
94115
@inproceedings{auditable-agents-2026,

0 commit comments

Comments
 (0)