The Python implementation that grows chapter-by-chapter as you read Building an AI Agent Harness from Scratch.
harness/
├── pyproject.toml # uv-native (Chapter 1)
├── src/harness/
│ ├── agent.py # the loop (Ch 2 → 21)
│ ├── agent_helpers.py # _one_turn (Appendix F)
│ ├── messages.py # Transcript, Message, blocks (Ch 3)
│ ├── providers/ # adapter seam (Ch 2–3, 5)
│ │ ├── base.py # Provider protocol, events, accumulate
│ │ ├── mock.py # scripted provider for tests (Ch 2)
│ │ ├── anthropic.py # (Ch 3)
│ │ ├── openai.py # (Ch 3)
│ │ └── local.py # OpenAI-compat local server (Ch 3)
│ ├── tools/ # tool protocol + registry
│ │ ├── base.py # Tool dataclass + async arun (Ch 4, Appendix F)
│ │ ├── decorator.py # @tool / @async_tool (Ch 4, Appendix F)
│ │ ├── registry.py # dispatch, adispatch, loop detection (Ch 4, 6, 14)
│ │ ├── validation.py # jsonschema validator (Ch 6)
│ │ ├── std.py # calc, bash, read viewport, edit (Ch 4, 11)
│ │ ├── selector.py # ToolCatalog + BM25 selection (Ch 12)
│ │ ├── scratchpad.py # external KV state (Ch 9)
│ │ └── retrieval.py # search_docs + BM25 index (Ch 10)
│ ├── context/
│ │ ├── accountant.py # token accounting, thresholds (Ch 7)
│ │ └── compactor.py # observation masking + summarization (Ch 8)
│ ├── mcp/
│ │ ├── client.py # stdio MCP client wrapper (Ch 13)
│ │ └── tools.py # wrap MCP tools as async Tools (Ch 13)
│ ├── permissions/
│ │ └── manager.py # PermissionManager + policies (Ch 14)
│ ├── subagents/
│ │ ├── spawner.py # SubagentSpawner + budgets (Ch 15)
│ │ ├── subagent.py # SubagentSpec, SubagentResult (Ch 15)
│ │ └── spawn_tool.py # async spawn_subagent Tool (Ch 15)
│ ├── plans/
│ │ └── tools.py # Plan, PlanHolder, plan_* tools (Ch 16)
│ ├── leases/
│ │ └── manager.py # exclusive-write LeaseManager (Ch 17)
│ ├── observability/
│ │ ├── tracing.py # OTel setup, span, SessionContext (Ch 18)
│ │ └── context.py # set_current / get_current context (Ch 18)
│ ├── evals/
│ │ └── runner.py # EvalCase, EvalRunner (Ch 19)
│ ├── cost/
│ │ ├── enforcer.py # BudgetEnforcer (Ch 20)
│ │ └── router.py # ModelRouter (Ch 20)
│ └── checkpoint/
│ ├── store.py # SQLite Checkpointer (Ch 21)
│ └── resume.py # idempotency + pending-call check (Ch 21)
├── tests/
│ └── test_smoke.py # Ch 1
└── examples/ # one runnable example per chapter
# from the harness/ directory
uv sync
uv run pytest tests/test_smoke.py -qEvery .py file under src/harness/ starts as a stub with a pointer to
the chapter that builds it. You type the code as you read. That is by
design — the book's thesis is that the harness is yours, and typing it
is how you learn it.
The canonical consolidated arun signature and the async Tool.arun
extension live in Appendix F of the book.