An AI saying "done" is a claim. Work is complete only when something outside that AI has checked it.
I run my personal website, akiohirayama.com, in nine languages with ChatGPT/Codex and Claude. Several AIs touch the same work: one drafts, another reviews, a third checks how pages actually render. The weak point is the handoff. The next AI usually receives a summary it has to believe.
This post shows the fix I use: a small, structured receipt that travels with the work, and a check that reads it.
The Multi-AI Handoff & Approval Card has eight fields. If any of them is empty, the work has only been reported. It is not done yet.
{
"task": "what was asked, in one sentence",
"claimed_result": "what the AI says it did",
"risk_tier": "auto | auto-then-verify | human-approval",
"risk_reason": "why this tier",
"evidence": [
{ "check": "what was checked", "checked_by": "script / fresh-context run / human (not the same AI run)", "result": "pass | fail | unclear" }
],
"changed": ["pages, files or systems touched"],
"rollback": { "how": "how to undo it", "who": "who can undo it" },
"open_items": ["anything unverified, ambiguous or skipped"],
"approved_by": "a human, or the rule that allowed auto-approval"
}
Three fields do most of the work:
Not every step needs a human. Approving everything trains people to click "yes" without reading.
| Tier | Examples | Default |
|---|---|---|
| auto | Draft a translation, generate a design option | Run automatically, log it |
| auto-then-verify | Change a live page, update shared text | Run, then verify before it counts as done |
| human-approval | Publish, delete, spend, touch credentials, message anyone | Stop and ask a human, with a one-screen summary |
A receipt is only useful if something reads it. This script returns DONE only when every field is filled, every piece of evidence passed and has a named checker, the rollback says both how and who, and no open items remain.
import json
import sys
REQUIRED = ["task", "claimed_result", "risk_tier", "risk_reason", "evidence",
"changed", "rollback", "open_items", "approved_by"]
TIERS = {"auto", "auto-then-verify", "human-approval"}
def check(card):
problems = []
for key in REQUIRED:
if key not in card:
problems.append(f"missing field: {key}")
for key in ["task", "claimed_result", "risk_reason", "approved_by"]:
if key in card and not str(card[key]).strip():
problems.append(f"empty field: {key}")
if card.get("risk_tier") not in TIERS:
problems.append("risk_tier must be auto, auto-then-verify or human-approval")
evidence = card.get("evidence") or []
if not evidence:
problems.append("no evidence: the work is reported, not done")
for item in evidence:
if item.get("result") != "pass":
problems.append(f"evidence not passing: {item.get('check', '?')}")
if not str(item.get("checked_by", "")).strip():
problems.append(f"evidence without a checker: {item.get('check', '?')}")
rollback = card.get("rollback") or {}
if not rollback.get("how") or not rollback.get("who"):
problems.append("rollback needs both how and who")
if card.get("open_items"):
problems.append(f"{len(card['open_items'])} open item(s) still listed")
return problems
if __name__ == "__main__":
with open(sys.argv[1], encoding="utf-8") as f:
card = json.load(f)
found = check(card)
for p in found:
print("-", p)
print("DONE" if not found else "NOT DONE")
sys.exit(0 if not found else 1)
Here is a card that fails:
{"task":"Publish the article","claimed_result":"Published","risk_tier":"human-approval","risk_reason":"public","evidence":[{"check":"links work","checked_by":"","result":"unclear"}],"changed":["note.com"],"rollback":{"how":"unpublish"},"open_items":["image credits"],"approved_by":""}
- empty field: approved_by
- evidence not passing: links work
- evidence without a checker: links work
- rollback needs both how and who
- 1 open item(s) still listed
NOT DONE
The exit code is non-zero, so the same check can gate a pipeline step or a handoff to the next agent.
The card, card.json and a longer field guide are free under CC BY 4.0:
I am also hiring an AI Engineer, at a monthly salary of USD 30,000, to build this kind of control layer across multiple AIs: role details.
— AKIO HIRAYAMA (akiohirayama.com)