/ pi
06 Pi from Scratch
How Pi actually works, built up from an empty file the way you would build any coding agent, one layer at a time — but every layer is Pi's real code (earendil-works/pi, MIT). We start with the loop and add exactly one thing per chapter, each because the last chapter left something missing: the toolbox, tool safety, the system prompt, the execution environment, context and cache, subagents, surfaces, and the extension system. Every claim is read straight from the source.
→
Pi from scratch: the planSTART
The whole of Pi on one page before we build it: the three package layers (ai / agent / coding-agent), the small-core-plus-extensions philosophy, and the order we will build it up in. Your map for the rest of the section.
→
The loop: from a chat call to an agentBUILD
The beating heart of Pi. How a plain model call becomes an agent: the loop calls the model, detects tool-use, runs the tools, threads the results back, and repeats until the model stops asking. Pi's real agent runtime, and why state is a session tree, not just an array.
→
The toolbox: giving Pi handsBUILD
A loop that can only talk is a chatbot. Pi's real tools — read, write, edit, bash, grep, find, ls (plus MCP) — and the shape of a Pi tool: name, description, a typed parameter schema, and an execute function. Why the description string is the model's real API.
→
Tool safety: permission gates, protected paths, trustBUILD
The first time bash runs a command you didn't expect, you understand why this chapter exists. How Pi gates dangerous tools before they execute, protects paths, and asks for project trust — all as hooks around tool execution, so safety is policy you can see.
→
The system prompt: how Pi tells the model who it isBUILD
Not one magic string. Pi assembles the prompt compositionally — a base template, your appended instructions, a project_context block of every AGENTS.md/CLAUDE.md found walking up from the cwd, and an available_skills block — then stamps the date and working directory. Read from buildSystemPrompt().
→
The execution environment: local, SSH, sandboxedBUILD
Where do the tools actually run? Pi threads an operations layer through every tool so the same read/bash/edit can run on your machine, over SSH, or in a sandbox without changing the tool. The injection mechanism (ReadOperations and friends) and the blast-radius idea.
→
How Pi manages context (not 'the last three messages')DEEP
Pi does not keep a fixed message window. It compacts on a real token budget: trigger at contextWindow minus 16,384, keep about 20,000 tokens of recent context, and summarize everything older into a structured digest of decisions and files touched. Read straight from compaction.ts.
→
How Pi does cache control: the rolling breakpointDEEP
Pi attaches an Anthropic ephemeral cache breakpoint to the last tool schema and the newest user message, a rolling breakpoint that follows the conversation so the whole growing prefix is served from cache each turn. Why a 100-turn Pi session stays cheap.
→
Does Pi serve the agent everything? (No, it truncates)DEEP
Every Pi tool is capped at 2,000 lines or 50 KB, whichever hits first. read keeps the head with offset/limit paging; bash keeps the tail and spills the full output to a temp file with a pointer; grep caps at 100 matches and 500-char lines; find at 1,000 results. Bounded by default, with an escape hatch.
→
How Pi does subagents: three mechanisms, three scalesDEEP
Pi has three answers to 'one job too big for one context': the subagent tool spawns isolated pi subprocesses (single/parallel/chain) driven by markdown role files (scout/planner/worker/reviewer, each with its own tools + model); handoff starts a fresh focused session; the orchestrator drives a whole fleet of instances across machines. Read straight from the extension + orchestrator source.
→
Surfaces: one headless core, four front-endsBUILD
The same AgentSession core drives a full terminal UI, a one-shot print mode, a JSON mode, and a 100-command JSONL RPC protocol — plus an SDK you embed in your own app. How Pi separates the agent from the way you talk to it, and why that separation is the whole point of a harness.
→
Extensibility: everything is an extensionBUILD
The last layer, and the one that makes Pi Pi. A single ExtensionAPI lets you register tools, slash commands, shortcuts, whole LLM providers, and hook ~31 lifecycle events (tool_call, context, session_before_compact…). Skills add progressive disclosure on top. How a small core becomes anything you need.
