POIROT: Automated forensic analysis for multi-agent AI systems
Project description
POIROT
Automated forensic analysis for multi-agent AI systems.
When a multi-agent system produces a wrong, dangerous, or unexpected output, the hardest question is: which agent caused it? In a system with multiple agents that all communicated with each other, tracing the root cause manually is slow, error-prone, and often impossible.
POIROT automates that investigation. You give it a description of your system and the conversation history of a failed session. It returns a structured forensic report identifying which component is responsible.
Preprint: (coming soon)
Website: (coming soon)
Documentation wiki: (in development — see docs/wiki/ in the meantime)
How it works
POIROT treats a failed session as a crime scene. It runs 4 sequential phases:
- Error Vector Space — maps all possible failure sources in your system into a binary error space
- Individual Analysis — each agent independently self-assesses its own behavior
- Peer Consultation — agents interrogate each other via a LangGraph multi-agent graph
- Weighted Consensus — votes are aggregated using a consistency-weighted formula to identify the faulty component
The result is an explainable, auditable forensic report — not a black-box prediction.
Benchmark results
Evaluated on the Who&When benchmark — 122 heterogeneous multi-agent configurations each with a single injected fault spanning medical, financial, and software domains.
POIROT consistently outperforms a single-LLM baseline across all four tested models. The advantage is largest on harder configurations: for Gemini 2.5 Pro, accuracy jumps from 21.3% (baseline) to 50.4% with POIROT — a +136% relative gain. DeepSeek goes from 32.8% to 52.1% (+59%). Even in the most competitive setting (GPT-oss 120B), POIROT adds +2.8 pp, and smaller models benefit most from the multi-agent protocol.
Installation
pip install poirot-framework
Requires Python 3.10+.
Quickstart
With LangChain agents (direct integration)
from poirot import run_poirot_from_agents, LangChainAgentAdapter
results = run_poirot_from_agents(
agents=[
LangChainAgentAdapter(agent=planner, messages=planner_messages, agent_id="planner", agent_name="PlannerAgent"),
LangChainAgentAdapter(agent=executor, messages=executor_messages, agent_id="executor", agent_name="ExecutorAgent"),
],
system_name="MyAgentSystem",
system_description="...",
provider="gemini",
model="gemini-2.5-pro",
api_key="YOUR_API_KEY",
)
With a SQLite database (any system, any language)
import poirot
results = poirot.run_poirot(
database_path="my_system.db",
system_name="MyAgentSystem",
system_description="""
A 3-agent pipeline:
- PlannerAgent: decomposes the user request into subtasks
- ExecutorAgent: executes each subtask using tools
- ReviewerAgent: validates the output before delivery
""",
provider="gemini",
api_key="YOUR_API_KEY",
)
c = results["consensus"]
if c["is_tie"]:
print(f"TIE between: {', '.join(c['tied_components'])}")
else:
print(f"Faulty component : {c['faulty_component']}")
print(f"Confidence : {c['confidence_pct']:.1f}%")
Supported LLM providers
| Provider | provider= value |
|---|---|
| Google Gemini | "gemini" |
| OpenAI | "openai" |
| DeepSeek | "deepseek" |
| Ollama (local) | "ollama" |
| LM Studio (local) | "local" |
Reading the results
results = poirot.run_poirot(...)
# Main verdict
c = results["consensus"]
c["faulty_component"] # "RiskManagerAgent" — or "AgentA / AgentB" if tied
c["confidence_pct"] # 72.4
c["is_tie"] # False
c["tied_components"] # [] or ["AgentA", "AgentB"] when tied
# Per-agent votes
for agent_id, report in results["agent_reports"].items():
print(report["name"]) # "RiskManagerAgent"
print(report["vote"]) # [1, 1, 0, 0]
print(report["justification"]) # full reasoning
# Raw phase outputs for advanced inspection
results["details"]["phase0_error_space"]
results["details"]["phase1_reports"]
results["details"]["phase2_voting"]
Key parameters
| Parameter | Default | Description |
|---|---|---|
output_dir |
None |
Directory for result files. None = nothing saved |
verbose |
True |
Print protocol progress to terminal |
debug |
False |
Save intermediate LLM context files to debug/ subfolder |
ignore_list |
None |
Component names to exclude from analysis |
Full parameter reference: API Reference
Examples
Working examples for both integration modes are in examples/:
examples/
├── langchain/
│ ├── 01_medical_diagnosis.py
│ ├── 02_stock_trading.py
│ └── 03_web_development.py
└── database/
├── 01_medical_diagnosis.py
├── 02_stock_trading.py
└── 03_web_development.py
Each example includes a realistic multi-agent scenario with an intentional bug for POIROT to identify.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file poirot_framework-0.1.0.tar.gz.
File metadata
- Download URL: poirot_framework-0.1.0.tar.gz
- Upload date:
- Size: 81.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b54c5c1b3bfe4675d9acbf95457ab0848c9bb20893e0b93433e7309c78f748d
|
|
| MD5 |
d91722cdd598225ddc2b1ff88acb458b
|
|
| BLAKE2b-256 |
5b375062d572ced7792f2344bf15664d46a28836c5031430bd1a532d84215f5e
|
File details
Details for the file poirot_framework-0.1.0-py3-none-any.whl.
File metadata
- Download URL: poirot_framework-0.1.0-py3-none-any.whl
- Upload date:
- Size: 85.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c65200429353a6fcc2b7791e9a77420ecad0360d7e3a2b54fec38a1df5ceb03
|
|
| MD5 |
f4dc570a533874b7d011b47009539f1e
|
|
| BLAKE2b-256 |
60885cbc05488312bbcad8b2945c9273ba55de20976fba03131b57ab6d0c7dcc
|