Skip to content

Latest commit

 

History

History
78 lines (70 loc) · 3.59 KB

File metadata and controls

78 lines (70 loc) · 3.59 KB

harness

The Python implementation that grows chapter-by-chapter as you read Building an AI Agent Harness from Scratch.

Layout

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

Getting started

# from the harness/ directory
uv sync
uv run pytest tests/test_smoke.py -q

Status of each module

Every .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.