
Write HTML. Render video. Built for agents.
Poirot is a reusable Python foundation for agent-led research and coding workflows. It combines a ReAct loop, long-term memory, multi-agent delegation, skill injection, MCP tools, and Docker sandbox controls into one architecture.
Builders who want to assemble agent workflows with memory, tools, and subagents instead of a single chat loop.
You can run agent sessions that keep context, delegate work, and write artifacts in a controlled environment.
A `LeaderAgent` runs the loop while LangGraph handles the outer flow and middleware hooks handle cross-cutting behavior.
It stores, recalls, externalizes, and consolidates long-term memory with a markdown-backed store and hybrid retrieval.
It can hand tasks to external coding agents or spawn self-copy subagents that share a sandbox.
It enforces file paths and supports local or Docker execution so agent writes persist in the right place.
It loads and evolves reusable research skills, with search, selection, evaluation, and rollback support.
It connects to tools through stdio, SSE, and HTTP transports with on-demand loading and fallback chains.
๐ Documentation: English ยท ็ฎไฝไธญๆ ยท ๆฅๆฌ่ช
ReAct Loop ยท Context Governance ยท 5-Layer Memory ยท Multi-Agent Orchestration ยท Skill Self-Evolution ยท Sandbox Isolation

Poirot is a deep research agent kernel built for those who care about how agents are architected. Rather than chasing a feature checklist, Poirot establishes a clean, decoupled, evaluable foundation โ from the ReAct core loop to context engineering governance, from a five-layer long-term memory system to multi-agent orchestration with shared sandbox isolation, from sandbox path enforcement to a three-layer skill self-evolution system.
Every module is independently designed, independently tested, and independently verifiable. 2400+ tests guard every layer.
A single LeaderAgent orchestrates the research loop. LangGraph handles outer flow orchestration (prepare โ leader_agent โ finalize), while 21 middleware cross-cut every lifecycle hook: before/after_agent, before/after_model, wrap_tool_call.
Breakthrough: Middleware are first-class citizens โ memory recall, skill injection, sandbox lifecycle, consolidation, tool-call pairing, help requests, and context governance are all pluggable cross-cutting concerns, not embedded in the agent loop. The app โ agents dependency is strictly one-directional.
The DefaultStrategy dynamically externalizes historical messages based on a live token budget. Window size is resolved by penetrating through the FallbackChatModel to the active provider's real context window โ no hardcoded thresholds. Dual strategies โ compaction (summarization) and externalization (offloading) โ prevent context overflow in long research sessions without losing critical information.
Breakthrough: The governance layer treats token budget as a first-class runtime concern. The fraction denominator is the real model window (resolved at call time), not a static config โ making P5 circuit-breaker thresholds accurate across provider switches.
Poirot implements a cognitive-science-inspired memory system across five layers, each independently testable:
| Layer | Role | Key Breakthrough |
|---|---|---|
| L1 | Schema + Protocol | MemoryTrace frozen dataclass (15 fields) + MemoryType enum (episodic/semantic/procedural) + 5 atomic operations (Encode/Retrieve/Associate/Consolidate/Reconsolidate) โ tools have no LLM, pure data operations |
| L2 | Default Strategies | Ebbinghaus decay formula (strength = baseร(1-decay)^hours + log(1+access)ร0.1 + importanceร0.05) + composite forget (TTL + strength threshold) + 6 hard-wired decisions (A1-F2) โ lazy decay, strength computed at retrieve time, no background tasks |
| L3 | Store + Retriever | MarkdownFileStore (single traces.md truth source + <!-- trace: {id} --> separators + YAML frontmatter) + HybridRetriever (pure BM25, no vector/graph dependency) โ retrieve reinforcement write-back (1A:ๅฝไธญๅ store.update ๅผบๅ strength) + forgotten filtering (3B: metadata.forgotten=True excluded) + incremental index (5B: store decorator triggers retriever.on_trace_*) |
| L4 | Middleware + Bootstrap | MemoryMiddleware.abefore_model โ per-call HumanMessage injection (protects prompt caching, hide_from_ui=True) + set_turn_id ContextVar (traceability C: actor = turn:N) + bootstrap lifecycle (lazy-load double-check lock + set_memory_config global singleton sync) |
| L5 | Auto-Consolidation | MemoryConsolidationMiddleware.aafter_model โ non-blocking submit every N turns + MemoryWorker (daemon thread + threading.Queue + LLM construction injection) โ LLM extracts episodic memories โ manager.encode โ candidate โฅ N โ LLM generates merged content โ manager.consolidate (max=10, E1) โ errors: log + skip, never blocks main loop |
Key Design: Memory injection is per-call HumanMessage (not system prompt), protecting the LLM's prompt cache prefix. recalled_memories in state stores only indices (id+score+strength), not full content. The MemoryConfig has 4 STARTUP_ONLY fields (use/storage_path/vector_store/graph_store) โ the rest are runtime-swappable via set_memory_config().
Poirot supports delegating sub-tasks to external coding agents and internal self-copies:
delegate_to_specialist(goal, success_criteria) routes to external CLIs (pi / codex / claude) via MCP SpecialistMcpServer (8 sandbox tools exposed). Each specialist runs as a separate process with its own LLM, but shares the same Docker sandbox via --sandbox-url passthrough.delegate_to_subagent(goal) creates a Poirot self-copy with isolated context (no inherited message history) but shared thread sandbox. SandboxMiddleware.abefore_model restores ContextVar from state["sandbox"] โ subagent reuses parent's sandbox_id without re-acquiring.MetricMonitor triggers when effective_rate < threshold, IVEFocuser diagnoses, LLMMutator varies, ScoreDeltaGate gates, GitRatchet rollbacks on degradation.RuntimeTracker feeds degradation signals back to L2.Breakthrough: The "shared thread sandbox" (INV#3) is now actually implemented โ subagent restores ContextVar from state, specialist connects to write to the same mount area, not ephemeral container-internal paths.
Two providers: Local (host process, for development) and Docker (container isolation, for production).
Docker mode breakthroughs:
DockerPathTranslator โ translate_path passes through (container path = bind mount path), reverse_translate maps /mnt/poirot/user-data/<x> โ <sandbox_root>/<sandbox_id>/<x> (Windows host path) โ fixes the present_files artifact extraction chain (shutil.copy2 now gets a real Windows path, not a container path)DockerPathGuard โ write path whitelist: write_file/str_replace paths must be under /mnt/poirot/user-data/, bash redirect targets (>{1,2}\s*(/[^\s;|&]*)) must be in mount area โ forces agent writes to persist, not lost in container-internal /tmp on --rmPOIROT_SANDBOX_IDLE_TIMEOUT=600 (10min)WslDockerExecutor translates D:\foo\bar โ /mnt/d/foo/bar for Docker daemon in WSL2Three transports: stdio, sse, http. Core tools load at startup; non-core tools defer-load on demand. Tool equivalence fallback chains (e.g., web_search โ MCP server โ builtin ddg) ensure resilience. Tool metadata drives externalization thresholds. Configured via .poirot/mcp_servers.yaml.
Skills are research process knowledge bundles โ prompt-level injections, not executable functions. "How to verify a source" is a skill. "Execute a web search" is a tool.
IVEFocuser diagnosis, LLMMutator variation, ScoreDeltaGate gating, GitRatchet ratchet rollback. Skills auto-evolve when effective rate drops below threshold.RuntimeTracker monitors applied-rate trends and feeds degradation signals back to Layer 2.36 builtin skills across 5 categories (core / research / software-development / creative / productivity). Core skills auto-load; others discoverable via /skill search.
poirot cli): Traditional scrolling mode with prompt_toolkit + rich. Slash-command completion + bottom toolbar.FallbackChatModel constructs a role-based routing chain (researcher / reporter). On transient API failures (rate limit, timeout, 5xx), it automatically degrades to the next provider. DeepSeek always sits at the chain tail as the ultimate fallback.
RunJournal records structured events (skill.select, skill.apply, memory.encode, memory.consolidate, compaction, budget). Thread directories persist run artifacts. The /expand command unfolds the previous round's full Thought text and tool results.
Outer flow: prepare โ before_agent โ LeaderAgent (ReAct loop) โ after_agent โ finalize. 21 middleware cross-cut every hook. Memory recall (L4) happens in before_model, consolidation (L5) in after_model. Skill injection (L1+L2+L3) in before_model. Tool calls route through Sandbox / MCP / Builtin via wrap_tool_call. Multi-agent delegation via delegate_to_specialist / delegate_to_subagent.
# 1. Clone
git clone <repo-url> && cd Poirot
# 2. Create environment (Python 3.12+)
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux / macOS
# 3. Install
pip install -e ".[dev]"
# 4. Configure
cp .env.example .env
# Edit .env โ fill in at least: DEEPSEEK_API_KEY=sk-xxx
# 5. Launch (TUI by default)
poirot
Type a question to start researching. Type / for command completion, /help for all commands.
# Long-term memory (L4 recall + L5 auto-consolidation)
POIROT_MEMORY_USE=default
POIROT_MEMORY_PHASE2_ENABLED=true
POIROT_MEMORY_PHASE2_TURNS=10
# Skill system (L1 base + L2 evolution + L3 eval)
POIROT_SKILL_ENABLED=true
POIROT_SKILL_EVOLVE_ENABLED=true
POIROT_SKILL_EVAL_ENABLED=true
POIROT_SKILL_MAX_INJECT=15
# Multi-Agent (specialist delegation + L2/L3)
POIROT_MULTIAGENT_ENABLED=true
POIROT_MULTIAGENT_L2_ENABLED=true
POIROT_MULTIAGENT_L3_ENABLED=true
# Docker sandbox (container isolation)
POIROT_SANDBOX_USE=poirot.backend.agents.sandbox.docker.docker_sandbox_provider:DockerSandboxProvider
POIROT_SANDBOX_EXECUTOR=wsl # Windows + WSL2 Docker
# MCP tools
POIROT_MCP_ENABLED=true
๐ For full configuration, commands, and troubleshooting โ see the Usage Guide.
TUI Conversation View โ dual-panel layout with live context governance, sandbox status, and memory recall
Poirot stands on the shoulders of giants. The architecture draws inspiration from several outstanding open-source projects and research frameworks:
Agent Architecture โ The middleware-first design and ReAct loop orchestration patterns are inspired by modern-based agent frameworks. The separation of concerns โ where memory, skills, sandbox, and tool routing are pluggable cross-cutting middleware rather than embedded agent logic โ builds upon ideas from conversational agent platforms that prioritize decoupled, testable architectures.
Memory System โ The five-layer memory architecture (schema โ strategies โ store โ middleware โ auto-consolidation) is informed by cognitive science models of episodic, semantic, and procedural memory. The Ebbinghaus decay formula, lazy strength computation, and Markdown-as-truth-source patterns draw from long-term memory research in AI agent design. The "tools have no LLM" principle โ where atomic operations are pure data transformations and LLM orchestration lives in the middleware layer โ is inspired by memory framework designs that separate engine from orchestration.
Multi-Agent Orchestration โ The specialist delegation model (where Poirot delegates coding tasks to external CLI agents via MCP) and the shared-thread-sandbox concept build upon multi-agent collaboration patterns from coding agent ecosystems. The idea that a lead agent can orchestrate specialized sub-agents โ each with their own LLM and toolset โ while sharing a unified sandbox for artifact continuity, is informed by production multi-agent system designs.
Sandbox Isolation โ The three-component sandbox model (Runtime + PathTranslator + SecurityGuard) and the warm-pool lifecycle management are inspired by sandbox isolation patterns from deep research agent platforms. The Docker path translation and mount-area enforcement address real-world challenges of cross-platform (Windows + WSL2 + Docker) file persistence.
Skill Self-Evolution โ The three-layer skill architecture (base storage โ LLM-driven evolution โ multi-dimensional evaluation) with ratchet rollback and quality gating builds upon self-improving agent research. The concept of skills as "process knowledge bundles" (prompt-level injections, not executable functions) draws from prompt engineering and skill management frameworks.
We gratefully acknowledge the developers and researchers of these projects whose work โ whether through direct code patterns, architectural ideas, or research papers โ made Poirot possible.
MIT ยฉ Poirot Authors
Built for those who care about how agents are built.
If this project helps you, a โญ is appreciated.
Sign in to join the discussion.
No comments yet. Be the first to say what this is good for.

Write HTML. Render video. Built for agents.
Ultra-lightweight, open-source, self-hosted personal AI agent framework in Python with WebUI, tools, memory, MCP, multi-agent workflows, automation, and chat apps
SkillOpt is a text-space optimizer that trains reusable natural-language skills for frozen LLM agents through trajectory-driven edits, validation-gated updates, and deployable best_skill.md artifacts.

Omnigent is an open-source AI agent framework and meta-harness: orchestrate Claude Code, Codex, Cursor, Pi, and custom agents โ swap harnesses without rewriting, enforce policies and sandboxing, and collaborate in real time from any device.
A theoretical reconstruction of the Claude Mythos architecture, built from first principles using the available research literature.
๐ท๏ธ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!