Run a backward-looking review of a finished period of agent work: compare what was claimed against what shipped, classify each failure, spot repeat findings, and turn the results into a small number of concrete rule or workflow changes. Triggers at the end of a work period, after a batch or project closes, or when the same failure keeps recurring.
./install.sh agent-retrospectivesname: agent_retrospectives description: "Run a backward-looking review of a finished period of agent work: compare what was claimed against what shipped, classify each failure, spot repeat findings, and turn the results into a small number of concrete rule or workflow changes. Triggers at the end of a work period, after a batch or project closes, or when the same failure keeps recurring." metadata: { "includeInPrompt": true }
This skill reviews a finished period of agent work and answers three questions from evidence: what was claimed, what actually shipped, and what will change as a result. It produces one retro document, one claim-vs-shipped table, and a short list of rule or workflow changes that get checked in the next period.
Scope lines against close cousins:
This skill owns the backward-looking review of a finished period of agent work: what was claimed vs what shipped, failure classification, and turning findings into a small number of concrete rule or workflow changes.
Write down, at the top of the retro document:
Freeze the period once defined. Work that finishes after the end date belongs to the next period, even if it fixes a gap found in this one.
Collect three evidence sets before judging any claim:
If a claim has no artifact and no log entry, mark its evidence as missing in step 3. Do not reconstruct evidence from memory.
Build the claim list as a JSON file in the helper format from step 4: a list of objects with id, claim, status, and failure_class. Fill status and failure_class in during step 3.
For each claim, check the artifact and the log, then assign one status:
shipped: the artifact exists, matches the claim, and the log supports the claimed timing.partial: part of the claim shipped, or the artifact exists but falls short of the claim in a stated way.missing: no artifact, or the artifact does not match the claim.blocked: the work did not ship and the log shows a specific external cause that stopped it.Record the table in the retro document with these columns: claim id, claim text, status, evidence (path, link, or log reference), failure class, and a one-line note.
Rules for this step:
missing or partial, never shipped.Save the script at the end of this skill as retro_tally.py, then run:
python3 retro_tally.py claims.json
The helper prints JSON counts by status and by failure class. Copy those counts into the retro document without editing them. If a count looks wrong, fix the claim list and rerun the helper. Do not adjust the printed numbers by hand.
Worked example, run during drafting of this skill. Fixture claims.json held 8 claims: c1 to c3 shipped, c4 partial with failure class planning, c5 missing with failure class verification, c6 missing with failure class tool, c7 blocked with failure class external_block, and c8 partial with failure class reporting. Running the helper printed:
{ "total": 8, "by_status": { "blocked": 1, "missing": 2, "partial": 2, "shipped": 3 }, "by_failure_class": { "external_block": 1, "none": 3, "planning": 1, "reporting": 1, "tool": 1, "verification": 1 } }
An invalid status such as done makes the helper exit 1 with an error naming the claim id, so a bad row fails loudly instead of being silently dropped.
Every claim with status partial, missing, or blocked gets exactly one primary failure class:
planning: the work was scoped wrong, sequenced wrong, missing a step, or based on a wrong assumption that was visible at planning time.tool: a tool, script, command, or API failed, returned wrong output, or lacked a capability the plan required.verification: the work shipped or was reported without a check that would have caught the gap, or a check ran and its result was ignored or misread.reporting: the work state was fine or partly fine, but the report about it was wrong, overstated, incomplete, or sent to the wrong place.external_block: a cause outside the work itself stopped it, for example an outage, a rate limit, a revoked permission, or a missing approval. Name the cause in the note column.Shipped claims use failure class none. Use unclassified only when the evidence is too thin to choose a class, and state what evidence is missing. When two classes fit, pick the earlier cause in the chain: a planning gap that led to a tool failure is planning.
Compare this period against the previous retro document for the same work stream:
verification: totals reported without rerun.no prior retro; repeat detection starts next period and move on.Convert findings into rule or workflow changes. Cap the list at 3 changes per retro as guidance. The cap keeps each change checkable in the next period. If a fourth change looks urgent, write it down and record why it was added or why it waits.
Each change must state:
Prefer changes to checklists, templates, and verification steps over general advice. A change that reads as be more careful fails this step. Rewrite it until it names an action, a place, and a check.
Do not create a change for an external_block finding unless the change reduces the damage from the next block, for example an earlier escalation step or a fallback path. The block itself is outside the workflow.
Use this structure, in this order:
Keep the document short enough to read in one sitting. Put raw logs and full claim files with the document as attachments or linked paths, not pasted into the findings.
At the start of the next retro for the same work stream, before step 3:
reporting if the change was recorded but never applied, or class planning if the change was too vague to apply.Save the following as retro_tally.py. It uses only the Python standard library.
python
#!/usr/bin/env python3
"""Tally claim outcomes for an agent retrospective.
Input: a JSON file containing a list of claim objects:
id str, required
claim str, required
status str, required: shipped, partial, missing, or blocked
failure_class str, optional: planning, tool, verification, reporting,
external_block, or none. Defaults to none for shipped
claims and unclassified for other claims.
Usage:
python3 retro_tally.py claims.json
Output: JSON counts by status and by failure class, plus the total.
Exit code: 0 on success, 1 on invalid input.
"""
import json
import sys
from collections import Counter
from pathlib import Path
STATUSES = {"shipped", "partial", "missing", "blocked"}
FAILURE_CLASSES = {"planning", "tool", "verification", "reporting", "external_block", "none", "unclassified"}
def main():
if len(sys.argv) != 2:
print("usage: python3 retro_tally.py claims.json", file=sys.stderr)
return 1
try:
data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
except Exception as exc:
print(f"error: cannot read JSON: {exc}", file=sys.stderr)
return 1
if not isinstance(data, list):
print("error: top-level JSON must be a list", file=sys.stderr)
return 1
by_status = Counter()
by_failure = Counter()
for item in data:
if not isinstance(item, dict) or not item.get("id") or not item.get("claim"):
print("error: each claim needs id and claim", file=sys.stderr)
return 1
status = str(item.get("status", "")).strip().lower()
if status not in STATUSES:
print(f"error: claim {item['id']} has invalid status {status!r}", file=sys.stderr)
return 1
failure = str(item.get("failure_class") or ("none" if status == "shipped" else "unclassified")).strip().lower()
if failure not in FAILURE_CLASSES:
print(f"error: claim {item['id']} has invalid failure_class {failure!r}", file=sys.stderr)
return 1
by_status[status] += 1
by_failure[failure] += 1
result = {
"total": len(data),
"by_status": dict(sorted(by_status.items())),
"by_failure_class": dict(sorted(by_failure.items())),
}
print(json.dumps(result, indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())
A completed retrospective produces all of the following:
retro_tally.py on the saved claim list.no prior retro; repeat detection starts next period when there is no previous retro.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.