A structured, public database of real AI-agent failures — and the schema for reporting them.
Agents now take real actions in production — they call tools, spend money, write to databases, browse the web, and run code. They fail in novel but repeating ways, yet there is no shared, structured record of those failures. This repo is that record: one rigorous schema, a growing corpus of sourced incidents that conform to it, and the tooling to keep it honest.
→ Browse and search the corpus at swarmproof.github.io/agent-postmortems
| Incidents | 63 and growing (2023–2026) — see the live count badge above | | Type | 34 realized incidents · 29 demonstrated hazards / near-misses | | Coverage | 17 of 19 failure classes; 9 CVE-backed |
| Every record | conforms to one schema, cites public sources, classified against a versioned taxonomy |
Failures span prompt injection, tool misuse, data exfiltration, sandbox escapes, model-template poisoning, reward hacking, autonomous misuse, cost blowups, and destructive actions — across coding agents, MCP servers, browser agents, chatbots, and frontier-model evaluations.
Each incident is one YAML file (incidents/<incident_id>.yaml). Abbreviated example:
incident_id: 2025-replit-prod-db-deletion
title: "Replit AI agent deleted a production database during a declared code freeze"
date: "2025-07-18"
incident_type: incident # incident (realized) | hazard (PoC / near-miss)
severity: high
confidence: confirmed
system:
framework: Replit AI agent
tools: ["database", "code-execution"]
autonomy_level: supervised-autonomous
primary_failure_class: unsafe-action
failure_classes: # the causal chain, not a single label
- {class: unsafe-action, subclass: data-deletion}
- {class: excessive-agency, subclass: missing-approval-gate}
- {class: hallucination, subclass: false-state}
trigger: "During an active code freeze, the agent ran destructive DB commands…"
root_cause: "Irreversible high-privilege actions against production with no enforced approval gate…"
blast_radius:
data: {records: 1200, classification: confidential, description: "Production DB deleted…"}
reversibility: partially-reversible
prevention: "Enforce dev/prod separation; require approval for destructive actions…"
mappings: # cross-references to external security frameworks
owasp_llm: [LLM06, LLM09] # Excessive Agency · Misinformation
owasp_agentic: [T3, T5] # Privilege Compromise · Cascading Hallucination
sources:
- {url: "https://…", type: news, publisher: Fortune}Required core + a large optional body (causation, attack_vector, timeline, cve/cwe, related_incidents, …). Every record is also cross-referenced to OWASP Top 10 for LLM Applications, OWASP Agentic AI Threats, and MITRE ATLAS (derived from its failure classes via schema/framework-mappings.yaml). Full field reference: SCHEMA.md · taxonomy: TAXONOMY.md.
Every incident needs at least one public, linkable source. No rumors, no speculation, no editorializing. Report failures factually; name systems without attacking them. Realized incidents and demonstrated hazards are both recorded, labeled honestly via incident_type. Disputed records are annotated, never deleted. CI enforces the rigor — schema, taxonomy, id-uniqueness, link-liveness, and a neutrality lint all run on every PR.
The corpus is regenerated into machine-readable JSON on every merge — no scraping, no API key:
BASE=https://raw.githubusercontent.com/swarmproof/agent-postmortems/main/export
# Whole corpus as one JSON array
curl -s $BASE/incidents.json | jq '.count'
# All prompt-injection incidents
curl -s $BASE/incidents.json | jq -r '.incidents[] | select(.primary_failure_class=="prompt-injection").incident_id'
# Everything CVE-backed
curl -s $BASE/incidents.json | jq -r '.incidents[] | select(.cve).incident_id'
# Incidents mapped to OWASP LLM06 (Excessive Agency)
curl -s $BASE/incidents.json | jq -r '.incidents[] | select((.mappings.owasp_llm // []) | index("LLM06")).incident_id'Two more feeds project the corpus for downstream tooling — scenarios.json (replayable chaos scenarios for stampede) and seeds.json (denial-of-wallet seeds for costbomb). Export entries carry natural-language trigger shapes, never runnable exploit payloads.
The site also offers a per-incident permalink with a copyable BibTeX citation and an RSS feed.
- Copy
incidents/_TEMPLATE.yamltoincidents/<incident_id>.yaml(filename =incident_id, aYYYY-kebab-slug). - Fill it in; classify with
TAXONOMY.md. - Validate:
uv run scripts/validate.pyanduv run scripts/check_links.py. - Open a PR — the template carries the sourcing + neutrality checklist; CI runs every gate.
New here? The good-first-issue label and the auto-filed candidate / coverage-gap issues are good starting points. See CONTRIBUTING.md.
Weekly workflows find new and not-yet-documented agent incidents and file them for review — automating the toil (discovery, de-dup, drafting, validation) but never merging anything without a human:
- Discovery harvests candidates from security-research feeds, first-party lab/vendor disclosures, arXiv, Google News, and the NVD CVE / GitHub advisory databases, de-dupes against the corpus, and posts a ranked candidates issue.
- Completeness critic diffs the corpus against curated external agent-incident lists and files a coverage-gaps issue — the "what did we miss?" review, automated.
- Auto-draft (opt-in) has Claude research candidates and open review-ready PRs.
See docs/CURATION-PIPELINE.md.
| Project | What it does |
|---|---|
| agent-postmortems | This repo — structured incident database + reporting standard |
| stampede | Drives simulated agent traffic at a system under test |
| mockworld | Mock external services (payments, email, exchange) for agent tests |
| mcp-probe | Lint, contract-test, benchmark, and load-test MCP servers |
| costbomb | Fuzzing for denial-of-wallet / unbounded-spend inputs |
| exactly-once | Idempotency middleware for agent side-effects |
| awesome-agent-reliability | Curated list of agent-reliability resources |
Dual-licensed to separate tooling from data: code (schema, validators, scripts, site) under Apache-2.0; incident data (incidents/, export/) under CC-BY-4.0 — reuse freely with attribution. Cite via CITATION.cff, or use the per-incident BibTeX box on the site.