decision_log is the table everything resolves to. Catalog mutations, ad-budget shifts, refunds, ticket replies — each is a row, and no row is ever updated in place. Reads are how you audit; appends are how the agents act.
Row shape
{
"id": 84193,
"parent_id": 84190, // cycle ancestry
"agent": "catalog.specialist",
"action": "ARCHIVE",
"subject": "sku_4471",
"trigger": "no_sales_180d",
"evidence": ["metrics_window#9m2"],
"judge_score": 0.93,
"cost_confidence": "A",
"reverse_op": "RESTORE sku_4471 winding_down",
"applied_at": "2026-05-18T07:42:11Z",
"sig": "hmac-sha256:…"
}The signature chain
Each row is HMAC-signed and chained to its predecessor. A silent edit breaks the chain and is detectable — which is what makes the log admissible as evidence, not just a record.
Reading it
for row in client.decisions.stream(agent="catalog", since="2026-05-24T00:00:00Z"):
print(row.action, row.subject, row.judge_score)Reversing an action
To undo, read the row and run its stored reverse_op. That creates a new row referencing the original — nothing is deleted. 'Undo' is itself an auditable fact. See ALLOWED_TRANSITIONS for which reversals are valid on catalog rows.
