[{"data":1,"prerenderedAt":2933},["ShallowReactive",2],{"navigation":3,"page-\u002Fchapters\u002Fscratchpad":102,"surround-\u002Fchapters\u002Fscratchpad":2928},[4,8],{"title":5,"path":6,"stem":7},"Home","\u002F","index",{"title":9,"path":10,"stem":11,"children":12,"page":101},"Chapters","\u002Fchapters","2.chapters",[13,17,21,25,29,33,37,41,45,49,53,57,61,65,69,73,77,81,85,89,93,97],{"title":14,"path":15,"stem":16},"Chapter 1. What an Agent Actually Is","\u002Fchapters\u002Fwhat-an-agent-actually-is","2.chapters\u002F01.what-an-agent-actually-is",{"title":18,"path":19,"stem":20},"Chapter 2. The Minimum Viable Loop","\u002Fchapters\u002Fminimum-viable-loop","2.chapters\u002F02.minimum-viable-loop",{"title":22,"path":23,"stem":24},"Chapter 3. Messages, Turns, and the Transcript","\u002Fchapters\u002Fmessages-turns-transcript","2.chapters\u002F03.messages-turns-transcript",{"title":26,"path":27,"stem":28},"Chapter 4. The Tool Protocol","\u002Fchapters\u002Ftool-protocol","2.chapters\u002F04.tool-protocol",{"title":30,"path":31,"stem":32},"Chapter 5. Streaming, Interruption, and Error Handling","\u002Fchapters\u002Fstreaming-interruption-errors","2.chapters\u002F05.streaming-interruption-errors",{"title":34,"path":35,"stem":36},"Chapter 6. Safe Tool Execution","\u002Fchapters\u002Fsafe-tool-execution","2.chapters\u002F06.safe-tool-execution",{"title":38,"path":39,"stem":40},"Chapter 7. The Context Window Is a Resource","\u002Fchapters\u002Fcontext-window-as-resource","2.chapters\u002F07.context-window-as-resource",{"title":42,"path":43,"stem":44},"Chapter 8. Compaction","\u002Fchapters\u002Fcompaction","2.chapters\u002F08.compaction",{"title":46,"path":47,"stem":48},"Chapter 9. External State: The Scratchpad","\u002Fchapters\u002Fscratchpad","2.chapters\u002F09.scratchpad",{"title":50,"path":51,"stem":52},"Chapter 10. Retrieval","\u002Fchapters\u002Fretrieval","2.chapters\u002F10.retrieval",{"title":54,"path":55,"stem":56},"Chapter 11. Designing Tools Models Can Actually Use","\u002Fchapters\u002Fdesigning-tools","2.chapters\u002F11.designing-tools",{"title":58,"path":59,"stem":60},"Chapter 12. The Tool Cliff and Dynamic Loading","\u002Fchapters\u002Ftool-cliff","2.chapters\u002F12.tool-cliff",{"title":62,"path":63,"stem":64},"Chapter 13. MCP: Tools From the Outside World","\u002Fchapters\u002Fmcp","2.chapters\u002F13.mcp",{"title":66,"path":67,"stem":68},"Chapter 14. Sandboxing and Permissions","\u002Fchapters\u002Fsandboxing-permissions","2.chapters\u002F14.sandboxing-permissions",{"title":70,"path":71,"stem":72},"Chapter 15. Sub-agents","\u002Fchapters\u002Fsub-agents","2.chapters\u002F15.sub-agents",{"title":74,"path":75,"stem":76},"Chapter 16. Structured Plans and Verified Completion","\u002Fchapters\u002Fplans-verified-completion","2.chapters\u002F16.plans-verified-completion",{"title":78,"path":79,"stem":80},"Chapter 17. Parallelism and Shared State","\u002Fchapters\u002Fparallelism-shared-state","2.chapters\u002F17.parallelism-shared-state",{"title":82,"path":83,"stem":84},"Chapter 18. Observability","\u002Fchapters\u002Fobservability","2.chapters\u002F18.observability",{"title":86,"path":87,"stem":88},"Chapter 19. Evals","\u002Fchapters\u002Fevals","2.chapters\u002F19.evals",{"title":90,"path":91,"stem":92},"Chapter 20. Cost Control","\u002Fchapters\u002Fcost-control","2.chapters\u002F20.cost-control",{"title":94,"path":95,"stem":96},"Chapter 21. Resumability and Durable State","\u002Fchapters\u002Fresumability","2.chapters\u002F21.resumability",{"title":98,"path":99,"stem":100},"Chapter 22. What Transfers, Where to Go","\u002Fchapters\u002Fwhat-transfers","2.chapters\u002F22.what-transfers",false,{"id":103,"title":46,"body":104,"description":117,"extension":2923,"meta":2924,"navigation":2925,"path":47,"seo":2926,"stem":48,"__hash__":2927},"content\u002F2.chapters\u002F09.scratchpad.md",{"type":105,"value":106,"toc":2912},"minimark",[107,111,118,125,149,152,253,256,261,264,267,274,280,283,285,289,292,1565,1568,1584,1590,1603,1605,1609,1612,1620,1627,1629,1633,1636,2184,2187,2207,2210,2213,2290,2304,2306,2310,2316,2319,2345,2348,2365,2367,2371,2374,2387,2389,2393,2396,2399,2795,2802,2804,2808,2854,2858,2886,2888,2908],[108,109,46],"h1",{"id":110},"chapter-9-external-state-the-scratchpad",[112,113,114],"p",{},[115,116,117],"em",{},"Previously: compaction. Older tool results get masked; the prefix gets summarized when masking isn't enough. The transcript survives long sessions. But anything the agent wanted to keep verbatim is at the mercy of the compactor.",[112,119,120,121,124],{},"A compactor is a janitor. It throws out what doesn't look important. That's fine for tool results and stale discussion, but sometimes the agent produces something ",[115,122,123],{},"it"," knows to be important — a plan, a discovery, a decision it wants to stand by. Those things should not be in the context window. They should be in durable storage the agent can read from on demand, structured so that compaction cannot touch them.",[112,126,127,128,132,133,136,137,140,141,144,145,148],{},"This chapter introduces the scratchpad pattern. The agent gets ",[129,130,131],"code",{},"write_scratchpad"," and ",[129,134,135],{},"read_scratchpad"," tools backed by a filesystem directory. Context contains pointers (keys) the agent remembers; content lives on disk. The pattern has several well-known instances under different names: Wang et al.'s 2023 \"Voyager: An Open-Ended Embodied Agent with Large Language Models\" called it a ",[115,138,139],{},"skill library"," — a persistent repository of learned action sequences the agent could retrieve and reuse across episodes. Park et al.'s 2023 \"Generative Agents: Interactive Simulacra of Human Behavior\" used a ",[115,142,143],{},"memory stream"," with explicit retrieval to give simulated agents continuity across time. Claude Code calls it ",[129,146,147],{},"CLAUDE.md","; Anthropic's multi-agent research system uses it for plans that must survive context truncation. The name varies; the pattern is identical, and the common thread is that non-trivial agents need state that lives outside the context window and survives the compactor.",[112,150,151],{},"By the end of this chapter, your agent can work across sessions. The scratchpad file is on disk; tomorrow's agent reads what today's agent wrote.",[153,154,158,159,158,245],"figure",{"className":155},[156,157],"not-prose","my-8","\n  ",[160,161,166,167,166,209,158],"div",{"className":162},[163,164,165],"flex","flex-col","gap-4","\n    ",[160,168,172,173,172,182,166],{"className":169},[163,170,171],"items-center","gap-3","\n      ",[160,174,181],{"className":175,"style":180},[176,177,178,179],"text-xs","text-muted","uppercase","tracking-wide","width:110px;","In-context",[160,183,191,192,191,198,191,205,172],{"className":184},[185,186,187,188,189,163,190],"flex-1","border","border-default","rounded-md","p-2","gap-1","\n        ",[160,193,197],{"className":194},[176,177,195,196],"px-2","py-1","sys",[160,199,204],{"className":200,"style":203},[185,201,195,196,176,202],"rounded","text-default","background:color-mix(in oklab, currentColor 18%, transparent);","previous tool outputs (bloat) — 42k tokens",[160,206,208],{"className":207},[176,177,195,196],"now",[160,210,172,212,172,217,172,236,166],{"className":211},[163,170,171],[160,213,216],{"className":214,"style":180},[176,215,178,179],"text-primary","External",[160,218,191,220,191,223,191,230,191,233,172],{"className":219},[185,186,187,188,189,163,190,170],[160,221,197],{"className":222},[176,177,195,196],[160,224,229],{"className":225},[201,195,196,176,226,215,227,228],"font-mono","border-2","border-primary","read('plan')",[160,231],{"className":232},[185],[160,234,208],{"className":235},[176,177,195,196],[160,237,244],{"className":238,"style":243},[227,228,239,240,241,176,242,215],"rounded-lg","py-3","px-4","font-semibold","min-width:140px;","scratchpad\u002F*.md",[246,247,252],"figcaption",{"className":248},[176,177,249,250,251],"mt-3","text-center","italic","State that survives compaction is state that was never in context.",[254,255],"hr",{},[257,258,260],"h2",{"id":259},"_91-why-not-just-a-longer-context-window","9.1 Why Not Just a Longer Context Window",[112,262,263],{},"A tempting thought: why bother with external state when models support 200K or 1M tokens? Just write the plan into the conversation and let the compactor leave it alone.",[112,265,266],{},"Two reasons that doesn't work.",[112,268,269,273],{},[270,271,272],"strong",{},"The compactor can't distinguish \"important plan\" from \"verbose tool output\" without being told."," You can teach it (\"preserve things tagged X\"), but now your taxonomy of things is part of the compactor's concern, and every new kind of important state is a compactor change. An external scratchpad pushes that concern out to where the agent lives: the tool interface.",[112,275,276,279],{},[270,277,278],{},"Context doesn't survive process death."," If the harness crashes, or the user comes back tomorrow, the context is gone. The scratchpad file is still on disk. Chapter 21 builds durable checkpointing for the full session state; the scratchpad is its precursor, and a cheaper pattern that covers 80% of the use cases by itself.",[112,281,282],{},"There's a third reason — cost. Content in the scratchpad doesn't eat tokens on every turn; content in the context does. A 2,000-token plan that's relevant to three turns out of thirty is a 2,000 × 27 = 54,000-token waste in context, and a 2,000 × 3 = 6,000-token cost when read from scratchpad on the three turns that need it. Order of magnitude savings for anything the agent doesn't need every turn.",[254,284],{},[257,286,288],{"id":287},"_92-the-scratchpad-interface","9.2 The Scratchpad Interface",[112,290,291],{},"Three tools: write, read, list. A thin layer of discipline around a directory.",[293,294,299],"pre",{"className":295,"code":296,"language":297,"meta":298,"style":298},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","# src\u002Fharness\u002Ftools\u002Fscratchpad.py\nfrom __future__ import annotations\n\nfrom pathlib import Path\n\nfrom .base import Tool\nfrom .decorator import tool\n\n\nclass Scratchpad:\n    \"\"\"Durable per-session key-value store, exposed to the agent as tools.\"\"\"\n\n    def __init__(self, root: Path | str) -> None:\n        self.root = Path(root)\n        self.root.mkdir(parents=True, exist_ok=True)\n\n    def _path(self, key: str) -> Path:\n        # simple key sanitization: allow alphanumerics, dash, underscore\n        safe = \"\".join(c for c in key if c.isalnum() or c in \"-_\")\n        if safe != key:\n            raise ValueError(f\"invalid key {key!r}: use [A-Za-z0-9_-]+\")\n        if not safe:\n            raise ValueError(\"key cannot be empty\")\n        return self.root \u002F f\"{safe}.txt\"\n\n    def write(self, key: str, content: str) -> str:\n        path = self._path(key)\n        path.write_text(content, encoding=\"utf-8\")\n        return f\"wrote {len(content)} chars to scratchpad[{key}]\"\n\n    def read(self, key: str) -> str:\n        path = self._path(key)\n        if not path.exists():\n            raise KeyError(f\"scratchpad[{key}] not found\")\n        return path.read_text(encoding=\"utf-8\")\n\n    def list(self) -> list[str]:\n        return sorted(p.stem for p in self.root.glob(\"*.txt\"))\n\n    def as_tools(self) -> list[Tool]:\n        pad = self\n\n        @tool(side_effects={\"write\"})\n        def scratchpad_write(key: str, content: str) -> str:\n            \"\"\"Store a value in the scratchpad under the given key.\n\n            key: alphanumeric, dashes, underscores only. No slashes, dots.\n            content: any string; overwrites existing value for this key.\n            Side effects: writes one file to the scratchpad directory.\n\n            Use this for: plans, discovered facts, decisions that should\n            survive the context window. Write once, read on demand.\n            \"\"\"\n            return pad.write(key, content)\n\n        @tool(side_effects={\"read\"})\n        def scratchpad_read(key: str) -> str:\n            \"\"\"Retrieve a value from the scratchpad.\n\n            key: the key used when writing.\n            Returns the stored content, or an error if not found.\n            Side effects: reads one file.\n            \"\"\"\n            return pad.read(key)\n\n        @tool(side_effects={\"read\"})\n        def scratchpad_list() -> str:\n            \"\"\"List keys currently in the scratchpad.\n\n            Returns a newline-separated list of keys.\n            Side effects: reads the scratchpad directory.\n\n            Use this at the start of a session to discover what prior\n            agents (or you, in a past turn) have stored.\n            \"\"\"\n            keys = pad.list()\n            return \"\\n\".join(keys) if keys else \"(empty)\"\n\n        return [scratchpad_write, scratchpad_read, scratchpad_list]\n","python","",[129,300,301,310,328,335,349,354,371,386,391,396,410,424,429,479,506,543,548,578,584,651,667,702,715,733,764,769,806,827,859,894,899,927,946,964,990,1017,1022,1049,1097,1102,1127,1138,1143,1172,1205,1214,1219,1225,1231,1237,1242,1248,1254,1260,1283,1288,1312,1336,1344,1349,1355,1361,1367,1372,1389,1394,1417,1433,1441,1446,1452,1458,1463,1469,1475,1480,1498,1538,1543],{"__ignoreMap":298},[302,303,306],"span",{"class":304,"line":305},"line",1,[302,307,309],{"class":308},"sutJx","# src\u002Fharness\u002Ftools\u002Fscratchpad.py\n",[302,311,313,317,321,324],{"class":304,"line":312},2,[302,314,316],{"class":315},"sVHd0","from",[302,318,320],{"class":319},"s_hVV"," __future__",[302,322,323],{"class":315}," import",[302,325,327],{"class":326},"su5hD"," annotations\n",[302,329,331],{"class":304,"line":330},3,[302,332,334],{"emptyLinePlaceholder":333},true,"\n",[302,336,338,340,343,346],{"class":304,"line":337},4,[302,339,316],{"class":315},[302,341,342],{"class":326}," pathlib ",[302,344,345],{"class":315},"import",[302,347,348],{"class":326}," Path\n",[302,350,352],{"class":304,"line":351},5,[302,353,334],{"emptyLinePlaceholder":333},[302,355,357,359,363,366,368],{"class":304,"line":356},6,[302,358,316],{"class":315},[302,360,362],{"class":361},"sP7_E"," .",[302,364,365],{"class":326},"base ",[302,367,345],{"class":315},[302,369,370],{"class":326}," Tool\n",[302,372,374,376,378,381,383],{"class":304,"line":373},7,[302,375,316],{"class":315},[302,377,362],{"class":361},[302,379,380],{"class":326},"decorator ",[302,382,345],{"class":315},[302,384,385],{"class":326}," tool\n",[302,387,389],{"class":304,"line":388},8,[302,390,334],{"emptyLinePlaceholder":333},[302,392,394],{"class":304,"line":393},9,[302,395,334],{"emptyLinePlaceholder":333},[302,397,399,403,407],{"class":304,"line":398},10,[302,400,402],{"class":401},"sbsja","class",[302,404,406],{"class":405},"sbgvK"," Scratchpad",[302,408,409],{"class":361},":\n",[302,411,413,417,421],{"class":304,"line":412},11,[302,414,416],{"class":415},"s2W-s","    \"\"\"",[302,418,420],{"class":419},"sithA","Durable per-session key-value store, exposed to the agent as tools.",[302,422,423],{"class":415},"\"\"\"\n",[302,425,427],{"class":304,"line":426},12,[302,428,334],{"emptyLinePlaceholder":333},[302,430,432,435,439,442,446,449,453,456,459,463,467,470,473,477],{"class":304,"line":431},13,[302,433,434],{"class":401},"    def",[302,436,438],{"class":437},"sptTA"," __init__",[302,440,441],{"class":361},"(",[302,443,445],{"class":444},"smCYv","self",[302,447,448],{"class":361},",",[302,450,452],{"class":451},"sFwrP"," root",[302,454,455],{"class":361},":",[302,457,458],{"class":326}," Path ",[302,460,462],{"class":461},"smGrS","|",[302,464,466],{"class":465},"sZMiF"," str",[302,468,469],{"class":361},")",[302,471,472],{"class":361}," ->",[302,474,476],{"class":475},"s39Yj"," None",[302,478,409],{"class":361},[302,480,482,485,488,492,495,499,501,503],{"class":304,"line":481},14,[302,483,484],{"class":319},"        self",[302,486,487],{"class":361},".",[302,489,491],{"class":490},"skxfh","root",[302,493,494],{"class":461}," =",[302,496,498],{"class":497},"slqww"," Path",[302,500,441],{"class":361},[302,502,491],{"class":497},[302,504,505],{"class":361},")\n",[302,507,509,511,513,515,517,520,522,526,529,532,534,537,539,541],{"class":304,"line":508},15,[302,510,484],{"class":319},[302,512,487],{"class":361},[302,514,491],{"class":490},[302,516,487],{"class":361},[302,518,519],{"class":497},"mkdir",[302,521,441],{"class":361},[302,523,525],{"class":524},"s99_P","parents",[302,527,528],{"class":461},"=",[302,530,531],{"class":475},"True",[302,533,448],{"class":361},[302,535,536],{"class":524}," exist_ok",[302,538,528],{"class":461},[302,540,531],{"class":475},[302,542,505],{"class":361},[302,544,546],{"class":304,"line":545},16,[302,547,334],{"emptyLinePlaceholder":333},[302,549,551,553,557,559,561,563,566,568,570,572,574,576],{"class":304,"line":550},17,[302,552,434],{"class":401},[302,554,556],{"class":555},"sGLFI"," _path",[302,558,441],{"class":361},[302,560,445],{"class":444},[302,562,448],{"class":361},[302,564,565],{"class":451}," key",[302,567,455],{"class":361},[302,569,466],{"class":465},[302,571,469],{"class":361},[302,573,472],{"class":361},[302,575,498],{"class":326},[302,577,409],{"class":361},[302,579,581],{"class":304,"line":580},18,[302,582,583],{"class":308},"        # simple key sanitization: allow alphanumerics, dash, underscore\n",[302,585,587,590,592,596,598,601,603,606,609,612,615,618,621,624,626,629,632,635,637,639,642,646,649],{"class":304,"line":586},19,[302,588,589],{"class":326},"        safe ",[302,591,528],{"class":461},[302,593,595],{"class":594},"sjJ54"," \"\"",[302,597,487],{"class":361},[302,599,600],{"class":497},"join",[302,602,441],{"class":361},[302,604,605],{"class":497},"c ",[302,607,608],{"class":315},"for",[302,610,611],{"class":497}," c ",[302,613,614],{"class":315},"in",[302,616,617],{"class":497}," key ",[302,619,620],{"class":315},"if",[302,622,623],{"class":497}," c",[302,625,487],{"class":361},[302,627,628],{"class":497},"isalnum",[302,630,631],{"class":361},"()",[302,633,634],{"class":315}," or",[302,636,611],{"class":497},[302,638,614],{"class":315},[302,640,641],{"class":594}," \"",[302,643,645],{"class":644},"s_sjI","-_",[302,647,648],{"class":594},"\"",[302,650,505],{"class":361},[302,652,654,657,660,663,665],{"class":304,"line":653},20,[302,655,656],{"class":315},"        if",[302,658,659],{"class":326}," safe ",[302,661,662],{"class":461},"!=",[302,664,565],{"class":326},[302,666,409],{"class":361},[302,668,670,673,676,678,681,684,688,691,694,697,700],{"class":304,"line":669},21,[302,671,672],{"class":315},"            raise",[302,674,675],{"class":465}," ValueError",[302,677,441],{"class":361},[302,679,680],{"class":401},"f",[302,682,683],{"class":644},"\"invalid key ",[302,685,687],{"class":686},"srdBf","{",[302,689,690],{"class":497},"key",[302,692,693],{"class":401},"!r",[302,695,696],{"class":686},"}",[302,698,699],{"class":644},": use [A-Za-z0-9_-]+\"",[302,701,505],{"class":361},[302,703,705,707,710,713],{"class":304,"line":704},22,[302,706,656],{"class":315},[302,708,709],{"class":461}," not",[302,711,712],{"class":326}," safe",[302,714,409],{"class":361},[302,716,718,720,722,724,726,729,731],{"class":304,"line":717},23,[302,719,672],{"class":315},[302,721,675],{"class":465},[302,723,441],{"class":361},[302,725,648],{"class":594},[302,727,728],{"class":644},"key cannot be empty",[302,730,648],{"class":594},[302,732,505],{"class":361},[302,734,736,739,742,744,746,749,752,754,756,759,761],{"class":304,"line":735},24,[302,737,738],{"class":315},"        return",[302,740,741],{"class":319}," self",[302,743,487],{"class":361},[302,745,491],{"class":490},[302,747,748],{"class":461}," \u002F",[302,750,751],{"class":401}," f",[302,753,648],{"class":644},[302,755,687],{"class":686},[302,757,758],{"class":326},"safe",[302,760,696],{"class":686},[302,762,763],{"class":644},".txt\"\n",[302,765,767],{"class":304,"line":766},25,[302,768,334],{"emptyLinePlaceholder":333},[302,770,772,774,777,779,781,783,785,787,789,791,794,796,798,800,802,804],{"class":304,"line":771},26,[302,773,434],{"class":401},[302,775,776],{"class":555}," write",[302,778,441],{"class":361},[302,780,445],{"class":444},[302,782,448],{"class":361},[302,784,565],{"class":451},[302,786,455],{"class":361},[302,788,466],{"class":465},[302,790,448],{"class":361},[302,792,793],{"class":451}," content",[302,795,455],{"class":361},[302,797,466],{"class":465},[302,799,469],{"class":361},[302,801,472],{"class":361},[302,803,466],{"class":465},[302,805,409],{"class":361},[302,807,809,812,814,816,818,821,823,825],{"class":304,"line":808},27,[302,810,811],{"class":326},"        path ",[302,813,528],{"class":461},[302,815,741],{"class":319},[302,817,487],{"class":361},[302,819,820],{"class":497},"_path",[302,822,441],{"class":361},[302,824,690],{"class":497},[302,826,505],{"class":361},[302,828,830,833,835,838,840,843,845,848,850,852,855,857],{"class":304,"line":829},28,[302,831,832],{"class":326},"        path",[302,834,487],{"class":361},[302,836,837],{"class":497},"write_text",[302,839,441],{"class":361},[302,841,842],{"class":497},"content",[302,844,448],{"class":361},[302,846,847],{"class":524}," encoding",[302,849,528],{"class":461},[302,851,648],{"class":594},[302,853,854],{"class":644},"utf-8",[302,856,648],{"class":594},[302,858,505],{"class":361},[302,860,862,864,866,869,871,874,876,878,880,882,885,887,889,891],{"class":304,"line":861},29,[302,863,738],{"class":315},[302,865,751],{"class":401},[302,867,868],{"class":644},"\"wrote ",[302,870,687],{"class":686},[302,872,873],{"class":437},"len",[302,875,441],{"class":361},[302,877,842],{"class":497},[302,879,469],{"class":361},[302,881,696],{"class":686},[302,883,884],{"class":644}," chars to scratchpad[",[302,886,687],{"class":686},[302,888,690],{"class":326},[302,890,696],{"class":686},[302,892,893],{"class":644},"]\"\n",[302,895,897],{"class":304,"line":896},30,[302,898,334],{"emptyLinePlaceholder":333},[302,900,902,904,907,909,911,913,915,917,919,921,923,925],{"class":304,"line":901},31,[302,903,434],{"class":401},[302,905,906],{"class":555}," read",[302,908,441],{"class":361},[302,910,445],{"class":444},[302,912,448],{"class":361},[302,914,565],{"class":451},[302,916,455],{"class":361},[302,918,466],{"class":465},[302,920,469],{"class":361},[302,922,472],{"class":361},[302,924,466],{"class":465},[302,926,409],{"class":361},[302,928,930,932,934,936,938,940,942,944],{"class":304,"line":929},32,[302,931,811],{"class":326},[302,933,528],{"class":461},[302,935,741],{"class":319},[302,937,487],{"class":361},[302,939,820],{"class":497},[302,941,441],{"class":361},[302,943,690],{"class":497},[302,945,505],{"class":361},[302,947,949,951,953,956,958,961],{"class":304,"line":948},33,[302,950,656],{"class":315},[302,952,709],{"class":461},[302,954,955],{"class":326}," path",[302,957,487],{"class":361},[302,959,960],{"class":497},"exists",[302,962,963],{"class":361},"():\n",[302,965,967,969,972,974,976,979,981,983,985,988],{"class":304,"line":966},34,[302,968,672],{"class":315},[302,970,971],{"class":465}," KeyError",[302,973,441],{"class":361},[302,975,680],{"class":401},[302,977,978],{"class":644},"\"scratchpad[",[302,980,687],{"class":686},[302,982,690],{"class":497},[302,984,696],{"class":686},[302,986,987],{"class":644},"] not found\"",[302,989,505],{"class":361},[302,991,993,995,997,999,1002,1004,1007,1009,1011,1013,1015],{"class":304,"line":992},35,[302,994,738],{"class":315},[302,996,955],{"class":326},[302,998,487],{"class":361},[302,1000,1001],{"class":497},"read_text",[302,1003,441],{"class":361},[302,1005,1006],{"class":524},"encoding",[302,1008,528],{"class":461},[302,1010,648],{"class":594},[302,1012,854],{"class":644},[302,1014,648],{"class":594},[302,1016,505],{"class":361},[302,1018,1020],{"class":304,"line":1019},36,[302,1021,334],{"emptyLinePlaceholder":333},[302,1023,1025,1027,1030,1032,1034,1036,1038,1040,1043,1046],{"class":304,"line":1024},37,[302,1026,434],{"class":401},[302,1028,1029],{"class":465}," list",[302,1031,441],{"class":361},[302,1033,445],{"class":444},[302,1035,469],{"class":361},[302,1037,472],{"class":361},[302,1039,1029],{"class":326},[302,1041,1042],{"class":361},"[",[302,1044,1045],{"class":465},"str",[302,1047,1048],{"class":361},"]:\n",[302,1050,1052,1054,1057,1059,1061,1063,1066,1069,1072,1074,1076,1078,1080,1082,1085,1087,1089,1092,1094],{"class":304,"line":1051},38,[302,1053,738],{"class":315},[302,1055,1056],{"class":437}," sorted",[302,1058,441],{"class":361},[302,1060,112],{"class":497},[302,1062,487],{"class":361},[302,1064,1065],{"class":490},"stem",[302,1067,1068],{"class":315}," for",[302,1070,1071],{"class":497}," p ",[302,1073,614],{"class":315},[302,1075,741],{"class":319},[302,1077,487],{"class":361},[302,1079,491],{"class":490},[302,1081,487],{"class":361},[302,1083,1084],{"class":497},"glob",[302,1086,441],{"class":361},[302,1088,648],{"class":594},[302,1090,1091],{"class":644},"*.txt",[302,1093,648],{"class":594},[302,1095,1096],{"class":361},"))\n",[302,1098,1100],{"class":304,"line":1099},39,[302,1101,334],{"emptyLinePlaceholder":333},[302,1103,1105,1107,1110,1112,1114,1116,1118,1120,1122,1125],{"class":304,"line":1104},40,[302,1106,434],{"class":401},[302,1108,1109],{"class":555}," as_tools",[302,1111,441],{"class":361},[302,1113,445],{"class":444},[302,1115,469],{"class":361},[302,1117,472],{"class":361},[302,1119,1029],{"class":326},[302,1121,1042],{"class":361},[302,1123,1124],{"class":326},"Tool",[302,1126,1048],{"class":361},[302,1128,1130,1133,1135],{"class":304,"line":1129},41,[302,1131,1132],{"class":326},"        pad ",[302,1134,528],{"class":461},[302,1136,1137],{"class":319}," self\n",[302,1139,1141],{"class":304,"line":1140},42,[302,1142,334],{"emptyLinePlaceholder":333},[302,1144,1146,1150,1153,1155,1158,1160,1162,1164,1167,1169],{"class":304,"line":1145},43,[302,1147,1149],{"class":1148},"stp6e","        @",[302,1151,1152],{"class":555},"tool",[302,1154,441],{"class":361},[302,1156,1157],{"class":524},"side_effects",[302,1159,528],{"class":461},[302,1161,687],{"class":361},[302,1163,648],{"class":594},[302,1165,1166],{"class":644},"write",[302,1168,648],{"class":594},[302,1170,1171],{"class":361},"})\n",[302,1173,1175,1178,1181,1183,1185,1187,1189,1191,1193,1195,1197,1199,1201,1203],{"class":304,"line":1174},44,[302,1176,1177],{"class":401},"        def",[302,1179,1180],{"class":555}," scratchpad_write",[302,1182,441],{"class":361},[302,1184,690],{"class":451},[302,1186,455],{"class":361},[302,1188,466],{"class":465},[302,1190,448],{"class":361},[302,1192,793],{"class":451},[302,1194,455],{"class":361},[302,1196,466],{"class":465},[302,1198,469],{"class":361},[302,1200,472],{"class":361},[302,1202,466],{"class":465},[302,1204,409],{"class":361},[302,1206,1208,1211],{"class":304,"line":1207},45,[302,1209,1210],{"class":415},"            \"\"\"",[302,1212,1213],{"class":419},"Store a value in the scratchpad under the given key.\n",[302,1215,1217],{"class":304,"line":1216},46,[302,1218,334],{"emptyLinePlaceholder":333},[302,1220,1222],{"class":304,"line":1221},47,[302,1223,1224],{"class":419},"            key: alphanumeric, dashes, underscores only. No slashes, dots.\n",[302,1226,1228],{"class":304,"line":1227},48,[302,1229,1230],{"class":419},"            content: any string; overwrites existing value for this key.\n",[302,1232,1234],{"class":304,"line":1233},49,[302,1235,1236],{"class":419},"            Side effects: writes one file to the scratchpad directory.\n",[302,1238,1240],{"class":304,"line":1239},50,[302,1241,334],{"emptyLinePlaceholder":333},[302,1243,1245],{"class":304,"line":1244},51,[302,1246,1247],{"class":419},"            Use this for: plans, discovered facts, decisions that should\n",[302,1249,1251],{"class":304,"line":1250},52,[302,1252,1253],{"class":419},"            survive the context window. Write once, read on demand.\n",[302,1255,1257],{"class":304,"line":1256},53,[302,1258,1259],{"class":415},"            \"\"\"\n",[302,1261,1263,1266,1269,1271,1273,1275,1277,1279,1281],{"class":304,"line":1262},54,[302,1264,1265],{"class":315},"            return",[302,1267,1268],{"class":326}," pad",[302,1270,487],{"class":361},[302,1272,1166],{"class":497},[302,1274,441],{"class":361},[302,1276,690],{"class":497},[302,1278,448],{"class":361},[302,1280,793],{"class":497},[302,1282,505],{"class":361},[302,1284,1286],{"class":304,"line":1285},55,[302,1287,334],{"emptyLinePlaceholder":333},[302,1289,1291,1293,1295,1297,1299,1301,1303,1305,1308,1310],{"class":304,"line":1290},56,[302,1292,1149],{"class":1148},[302,1294,1152],{"class":555},[302,1296,441],{"class":361},[302,1298,1157],{"class":524},[302,1300,528],{"class":461},[302,1302,687],{"class":361},[302,1304,648],{"class":594},[302,1306,1307],{"class":644},"read",[302,1309,648],{"class":594},[302,1311,1171],{"class":361},[302,1313,1315,1317,1320,1322,1324,1326,1328,1330,1332,1334],{"class":304,"line":1314},57,[302,1316,1177],{"class":401},[302,1318,1319],{"class":555}," scratchpad_read",[302,1321,441],{"class":361},[302,1323,690],{"class":451},[302,1325,455],{"class":361},[302,1327,466],{"class":465},[302,1329,469],{"class":361},[302,1331,472],{"class":361},[302,1333,466],{"class":465},[302,1335,409],{"class":361},[302,1337,1339,1341],{"class":304,"line":1338},58,[302,1340,1210],{"class":415},[302,1342,1343],{"class":419},"Retrieve a value from the scratchpad.\n",[302,1345,1347],{"class":304,"line":1346},59,[302,1348,334],{"emptyLinePlaceholder":333},[302,1350,1352],{"class":304,"line":1351},60,[302,1353,1354],{"class":419},"            key: the key used when writing.\n",[302,1356,1358],{"class":304,"line":1357},61,[302,1359,1360],{"class":419},"            Returns the stored content, or an error if not found.\n",[302,1362,1364],{"class":304,"line":1363},62,[302,1365,1366],{"class":419},"            Side effects: reads one file.\n",[302,1368,1370],{"class":304,"line":1369},63,[302,1371,1259],{"class":415},[302,1373,1375,1377,1379,1381,1383,1385,1387],{"class":304,"line":1374},64,[302,1376,1265],{"class":315},[302,1378,1268],{"class":326},[302,1380,487],{"class":361},[302,1382,1307],{"class":497},[302,1384,441],{"class":361},[302,1386,690],{"class":497},[302,1388,505],{"class":361},[302,1390,1392],{"class":304,"line":1391},65,[302,1393,334],{"emptyLinePlaceholder":333},[302,1395,1397,1399,1401,1403,1405,1407,1409,1411,1413,1415],{"class":304,"line":1396},66,[302,1398,1149],{"class":1148},[302,1400,1152],{"class":555},[302,1402,441],{"class":361},[302,1404,1157],{"class":524},[302,1406,528],{"class":461},[302,1408,687],{"class":361},[302,1410,648],{"class":594},[302,1412,1307],{"class":644},[302,1414,648],{"class":594},[302,1416,1171],{"class":361},[302,1418,1420,1422,1425,1427,1429,1431],{"class":304,"line":1419},67,[302,1421,1177],{"class":401},[302,1423,1424],{"class":555}," scratchpad_list",[302,1426,631],{"class":361},[302,1428,472],{"class":361},[302,1430,466],{"class":465},[302,1432,409],{"class":361},[302,1434,1436,1438],{"class":304,"line":1435},68,[302,1437,1210],{"class":415},[302,1439,1440],{"class":419},"List keys currently in the scratchpad.\n",[302,1442,1444],{"class":304,"line":1443},69,[302,1445,334],{"emptyLinePlaceholder":333},[302,1447,1449],{"class":304,"line":1448},70,[302,1450,1451],{"class":419},"            Returns a newline-separated list of keys.\n",[302,1453,1455],{"class":304,"line":1454},71,[302,1456,1457],{"class":419},"            Side effects: reads the scratchpad directory.\n",[302,1459,1461],{"class":304,"line":1460},72,[302,1462,334],{"emptyLinePlaceholder":333},[302,1464,1466],{"class":304,"line":1465},73,[302,1467,1468],{"class":419},"            Use this at the start of a session to discover what prior\n",[302,1470,1472],{"class":304,"line":1471},74,[302,1473,1474],{"class":419},"            agents (or you, in a past turn) have stored.\n",[302,1476,1478],{"class":304,"line":1477},75,[302,1479,1259],{"class":415},[302,1481,1483,1486,1488,1490,1492,1495],{"class":304,"line":1482},76,[302,1484,1485],{"class":326},"            keys ",[302,1487,528],{"class":461},[302,1489,1268],{"class":326},[302,1491,487],{"class":361},[302,1493,1494],{"class":497},"list",[302,1496,1497],{"class":361},"()\n",[302,1499,1501,1503,1505,1508,1510,1512,1514,1516,1519,1521,1524,1527,1530,1532,1535],{"class":304,"line":1500},77,[302,1502,1265],{"class":315},[302,1504,641],{"class":594},[302,1506,1507],{"class":319},"\\n",[302,1509,648],{"class":594},[302,1511,487],{"class":361},[302,1513,600],{"class":497},[302,1515,441],{"class":361},[302,1517,1518],{"class":497},"keys",[302,1520,469],{"class":361},[302,1522,1523],{"class":315}," if",[302,1525,1526],{"class":326}," keys ",[302,1528,1529],{"class":315},"else",[302,1531,641],{"class":594},[302,1533,1534],{"class":644},"(empty)",[302,1536,1537],{"class":594},"\"\n",[302,1539,1541],{"class":304,"line":1540},78,[302,1542,334],{"emptyLinePlaceholder":333},[302,1544,1546,1548,1551,1554,1556,1558,1560,1562],{"class":304,"line":1545},79,[302,1547,738],{"class":315},[302,1549,1550],{"class":361}," [",[302,1552,1553],{"class":326},"scratchpad_write",[302,1555,448],{"class":361},[302,1557,1319],{"class":326},[302,1559,448],{"class":361},[302,1561,1424],{"class":326},[302,1563,1564],{"class":361},"]\n",[112,1566,1567],{},"Three design points.",[112,1569,1570,1573,1574,1577,1578,1577,1581,487],{},[270,1571,1572],{},"Keys are sanitized, not encoded."," A key containing a slash or a dot would let the agent write outside the scratchpad directory — a path traversal by accident. We reject invalid keys with a clear error rather than silently rewriting them. The model learns the convention quickly: all of my keys are ",[129,1575,1576],{},"plan-a",", ",[129,1579,1580],{},"findings-1",[129,1582,1583],{},"schema-cache",[112,1585,1586,1589],{},[270,1587,1588],{},"Content is always a string."," The scratchpad doesn't know about types. If the agent stores JSON, it stores a JSON string; on read, it gets a JSON string back. Type discipline is the agent's job, not the scratchpad's.",[112,1591,1592,1598,1599,1602],{},[270,1593,1594,1595,487],{},"The three tools are created together via ",[129,1596,1597],{},"as_tools()"," This is a pattern we'll reuse in the MCP chapter: a stateful component exposes itself to the model as a bundle of closure-captured tools, not as individual top-level functions. It keeps the ",[129,1600,1601],{},"Scratchpad"," instance private to the tool bundle and out of the global namespace.",[254,1604],{},[257,1606,1608],{"id":1607},"_93-the-system-prompt-that-teaches-it","9.3 The System Prompt That Teaches It",[112,1610,1611],{},"The agent needs to know the scratchpad exists and what it's for. Good scratchpad use is a system-prompt decision, not a tool-description decision alone. A tool description says \"what this tool does\"; the system prompt says \"when to reach for it.\"",[293,1613,1618],{"className":1614,"code":1616,"language":1617,"meta":298},[1615],"language-text","You have access to a scratchpad — a durable key-value store that survives\nthe context window. Use it whenever you discover or decide something you\nexpect to need more than two turns later.\n\nExamples of what to write to the scratchpad:\n- Plans you commit to. If you decide on a 5-step approach, write it to\n  \"plan\" immediately. Read it back when you're unsure of your next step.\n- Findings from expensive tools. If you ran a 10-second database query,\n  store the result in \"query-result-1\" so you don't have to re-run it.\n- Constraints the user has expressed. \"No changes to production\" goes to\n  \"constraints\" and stays there for the session.\n- Decisions you don't want to revisit. \"Using port 8081 because 8080 is\n  taken\" goes to \"port-decision\".\n\nCall scratchpad_list() at the start of a session to see what's already\nstored. Call scratchpad_read(key) to retrieve values you remember writing.\nCall scratchpad_write(key, content) to persist. Use short keys:\n\"plan\", \"constraints\", \"query-result-1\".\n\nThe scratchpad is durable. What you write here will be readable by future\nsessions (including yourself, tomorrow). Treat it like a shared notebook.\n","text",[129,1619,1616],{"__ignoreMap":298},[112,1621,1622,1623,1626],{},"This isn't decorative. The difference between an agent that uses the scratchpad well and one that doesn't is mostly the system prompt. Without these instructions, most models will write to it occasionally but not systematically. With them, they start every complex session by writing a plan to ",[129,1624,1625],{},"plan"," and reading it whenever they feel lost.",[254,1628],{},[257,1630,1632],{"id":1631},"_94-a-scenario-that-needs-the-scratchpad","9.4 A Scenario That Needs the Scratchpad",[112,1634,1635],{},"The scratchpad's value shows up on long sessions with expensive tool calls. Let's write one.",[293,1637,1639],{"className":295,"code":1638,"language":297,"meta":298,"style":298},"# examples\u002Fch09_investigation.py\nimport asyncio\nfrom pathlib import Path\n\nfrom harness.agent import arun\nfrom harness.context.accountant import ContextAccountant\nfrom harness.context.compactor import Compactor\nfrom harness.providers.anthropic import AnthropicProvider\nfrom harness.tools.registry import ToolRegistry\nfrom harness.tools.scratchpad import Scratchpad\nfrom harness.tools.std import read_file, bash, calc\n\n\nSYSTEM = \"\"\"\\\nYou are an investigative agent. You have a scratchpad — a durable key-value\nstore that survives the context window. Use it whenever you discover or\ndecide something you expect to need more than two turns later.\n\n[... full scratchpad system prompt from 9.3 ...]\n\nAt the start of every session, call scratchpad_list() to see what's there.\n\"\"\"\n\n\nasync def main() -> None:\n    provider = AnthropicProvider()\n    pad = Scratchpad(root=Path(\".scratchpad\"))\n    registry = ToolRegistry(\n        tools=[calc, read_file, bash] + pad.as_tools()\n    )\n    accountant = ContextAccountant()\n    compactor = Compactor(accountant, provider)\n\n    await arun(\n        provider=provider,\n        registry=registry,\n        accountant=accountant,\n        compactor=compactor,\n        system=SYSTEM,\n        user_message=(\n            \"Investigate this machine. First, make a plan in the scratchpad. \"\n            \"Then carry it out: learn about the OS, CPU, memory, disk, and \"\n            \"recent activity. Record your findings in the scratchpad as you \"\n            \"go. When done, synthesize a 200-word report.\"\n        ),\n    )\n\n\nasyncio.run(main())\n",[129,1640,1641,1646,1653,1663,1667,1684,1705,1725,1746,1767,1787,1817,1821,1825,1838,1843,1848,1853,1857,1862,1866,1871,1875,1879,1883,1902,1914,1943,1956,1991,1996,2008,2030,2034,2044,2057,2069,2080,2092,2103,2112,2122,2131,2140,2149,2154,2158,2162,2166],{"__ignoreMap":298},[302,1642,1643],{"class":304,"line":305},[302,1644,1645],{"class":308},"# examples\u002Fch09_investigation.py\n",[302,1647,1648,1650],{"class":304,"line":312},[302,1649,345],{"class":315},[302,1651,1652],{"class":326}," asyncio\n",[302,1654,1655,1657,1659,1661],{"class":304,"line":330},[302,1656,316],{"class":315},[302,1658,342],{"class":326},[302,1660,345],{"class":315},[302,1662,348],{"class":326},[302,1664,1665],{"class":304,"line":337},[302,1666,334],{"emptyLinePlaceholder":333},[302,1668,1669,1671,1674,1676,1679,1681],{"class":304,"line":351},[302,1670,316],{"class":315},[302,1672,1673],{"class":326}," harness",[302,1675,487],{"class":361},[302,1677,1678],{"class":326},"agent ",[302,1680,345],{"class":315},[302,1682,1683],{"class":326}," arun\n",[302,1685,1686,1688,1690,1692,1695,1697,1700,1702],{"class":304,"line":356},[302,1687,316],{"class":315},[302,1689,1673],{"class":326},[302,1691,487],{"class":361},[302,1693,1694],{"class":326},"context",[302,1696,487],{"class":361},[302,1698,1699],{"class":326},"accountant ",[302,1701,345],{"class":315},[302,1703,1704],{"class":326}," ContextAccountant\n",[302,1706,1707,1709,1711,1713,1715,1717,1720,1722],{"class":304,"line":373},[302,1708,316],{"class":315},[302,1710,1673],{"class":326},[302,1712,487],{"class":361},[302,1714,1694],{"class":326},[302,1716,487],{"class":361},[302,1718,1719],{"class":326},"compactor ",[302,1721,345],{"class":315},[302,1723,1724],{"class":326}," Compactor\n",[302,1726,1727,1729,1731,1733,1736,1738,1741,1743],{"class":304,"line":388},[302,1728,316],{"class":315},[302,1730,1673],{"class":326},[302,1732,487],{"class":361},[302,1734,1735],{"class":326},"providers",[302,1737,487],{"class":361},[302,1739,1740],{"class":326},"anthropic ",[302,1742,345],{"class":315},[302,1744,1745],{"class":326}," AnthropicProvider\n",[302,1747,1748,1750,1752,1754,1757,1759,1762,1764],{"class":304,"line":393},[302,1749,316],{"class":315},[302,1751,1673],{"class":326},[302,1753,487],{"class":361},[302,1755,1756],{"class":326},"tools",[302,1758,487],{"class":361},[302,1760,1761],{"class":326},"registry ",[302,1763,345],{"class":315},[302,1765,1766],{"class":326}," ToolRegistry\n",[302,1768,1769,1771,1773,1775,1777,1779,1782,1784],{"class":304,"line":398},[302,1770,316],{"class":315},[302,1772,1673],{"class":326},[302,1774,487],{"class":361},[302,1776,1756],{"class":326},[302,1778,487],{"class":361},[302,1780,1781],{"class":326},"scratchpad ",[302,1783,345],{"class":315},[302,1785,1786],{"class":326}," Scratchpad\n",[302,1788,1789,1791,1793,1795,1797,1799,1802,1804,1807,1809,1812,1814],{"class":304,"line":412},[302,1790,316],{"class":315},[302,1792,1673],{"class":326},[302,1794,487],{"class":361},[302,1796,1756],{"class":326},[302,1798,487],{"class":361},[302,1800,1801],{"class":326},"std ",[302,1803,345],{"class":315},[302,1805,1806],{"class":326}," read_file",[302,1808,448],{"class":361},[302,1810,1811],{"class":326}," bash",[302,1813,448],{"class":361},[302,1815,1816],{"class":326}," calc\n",[302,1818,1819],{"class":304,"line":426},[302,1820,334],{"emptyLinePlaceholder":333},[302,1822,1823],{"class":304,"line":431},[302,1824,334],{"emptyLinePlaceholder":333},[302,1826,1827,1830,1832,1835],{"class":304,"line":481},[302,1828,1829],{"class":319},"SYSTEM",[302,1831,494],{"class":461},[302,1833,1834],{"class":594}," \"\"\"",[302,1836,1837],{"class":475},"\\\n",[302,1839,1840],{"class":304,"line":508},[302,1841,1842],{"class":644},"You are an investigative agent. You have a scratchpad — a durable key-value\n",[302,1844,1845],{"class":304,"line":545},[302,1846,1847],{"class":644},"store that survives the context window. Use it whenever you discover or\n",[302,1849,1850],{"class":304,"line":550},[302,1851,1852],{"class":644},"decide something you expect to need more than two turns later.\n",[302,1854,1855],{"class":304,"line":580},[302,1856,334],{"emptyLinePlaceholder":333},[302,1858,1859],{"class":304,"line":586},[302,1860,1861],{"class":644},"[... full scratchpad system prompt from 9.3 ...]\n",[302,1863,1864],{"class":304,"line":653},[302,1865,334],{"emptyLinePlaceholder":333},[302,1867,1868],{"class":304,"line":669},[302,1869,1870],{"class":644},"At the start of every session, call scratchpad_list() to see what's there.\n",[302,1872,1873],{"class":304,"line":704},[302,1874,423],{"class":594},[302,1876,1877],{"class":304,"line":717},[302,1878,334],{"emptyLinePlaceholder":333},[302,1880,1881],{"class":304,"line":735},[302,1882,334],{"emptyLinePlaceholder":333},[302,1884,1885,1888,1891,1894,1896,1898,1900],{"class":304,"line":766},[302,1886,1887],{"class":401},"async",[302,1889,1890],{"class":401}," def",[302,1892,1893],{"class":555}," main",[302,1895,631],{"class":361},[302,1897,472],{"class":361},[302,1899,476],{"class":475},[302,1901,409],{"class":361},[302,1903,1904,1907,1909,1912],{"class":304,"line":771},[302,1905,1906],{"class":326},"    provider ",[302,1908,528],{"class":461},[302,1910,1911],{"class":497}," AnthropicProvider",[302,1913,1497],{"class":361},[302,1915,1916,1919,1921,1923,1925,1927,1929,1932,1934,1936,1939,1941],{"class":304,"line":808},[302,1917,1918],{"class":326},"    pad ",[302,1920,528],{"class":461},[302,1922,406],{"class":497},[302,1924,441],{"class":361},[302,1926,491],{"class":524},[302,1928,528],{"class":461},[302,1930,1931],{"class":497},"Path",[302,1933,441],{"class":361},[302,1935,648],{"class":594},[302,1937,1938],{"class":644},".scratchpad",[302,1940,648],{"class":594},[302,1942,1096],{"class":361},[302,1944,1945,1948,1950,1953],{"class":304,"line":829},[302,1946,1947],{"class":326},"    registry ",[302,1949,528],{"class":461},[302,1951,1952],{"class":497}," ToolRegistry",[302,1954,1955],{"class":361},"(\n",[302,1957,1958,1961,1963,1965,1968,1970,1972,1974,1976,1979,1982,1984,1986,1989],{"class":304,"line":861},[302,1959,1960],{"class":524},"        tools",[302,1962,528],{"class":461},[302,1964,1042],{"class":361},[302,1966,1967],{"class":497},"calc",[302,1969,448],{"class":361},[302,1971,1806],{"class":497},[302,1973,448],{"class":361},[302,1975,1811],{"class":497},[302,1977,1978],{"class":361},"]",[302,1980,1981],{"class":461}," +",[302,1983,1268],{"class":497},[302,1985,487],{"class":361},[302,1987,1988],{"class":497},"as_tools",[302,1990,1497],{"class":361},[302,1992,1993],{"class":304,"line":896},[302,1994,1995],{"class":361},"    )\n",[302,1997,1998,2001,2003,2006],{"class":304,"line":901},[302,1999,2000],{"class":326},"    accountant ",[302,2002,528],{"class":461},[302,2004,2005],{"class":497}," ContextAccountant",[302,2007,1497],{"class":361},[302,2009,2010,2013,2015,2018,2020,2023,2025,2028],{"class":304,"line":929},[302,2011,2012],{"class":326},"    compactor ",[302,2014,528],{"class":461},[302,2016,2017],{"class":497}," Compactor",[302,2019,441],{"class":361},[302,2021,2022],{"class":497},"accountant",[302,2024,448],{"class":361},[302,2026,2027],{"class":497}," provider",[302,2029,505],{"class":361},[302,2031,2032],{"class":304,"line":948},[302,2033,334],{"emptyLinePlaceholder":333},[302,2035,2036,2039,2042],{"class":304,"line":966},[302,2037,2038],{"class":315},"    await",[302,2040,2041],{"class":497}," arun",[302,2043,1955],{"class":361},[302,2045,2046,2049,2051,2054],{"class":304,"line":992},[302,2047,2048],{"class":524},"        provider",[302,2050,528],{"class":461},[302,2052,2053],{"class":497},"provider",[302,2055,2056],{"class":361},",\n",[302,2058,2059,2062,2064,2067],{"class":304,"line":1019},[302,2060,2061],{"class":524},"        registry",[302,2063,528],{"class":461},[302,2065,2066],{"class":497},"registry",[302,2068,2056],{"class":361},[302,2070,2071,2074,2076,2078],{"class":304,"line":1024},[302,2072,2073],{"class":524},"        accountant",[302,2075,528],{"class":461},[302,2077,2022],{"class":497},[302,2079,2056],{"class":361},[302,2081,2082,2085,2087,2090],{"class":304,"line":1051},[302,2083,2084],{"class":524},"        compactor",[302,2086,528],{"class":461},[302,2088,2089],{"class":497},"compactor",[302,2091,2056],{"class":361},[302,2093,2094,2097,2099,2101],{"class":304,"line":1099},[302,2095,2096],{"class":524},"        system",[302,2098,528],{"class":461},[302,2100,1829],{"class":437},[302,2102,2056],{"class":361},[302,2104,2105,2108,2110],{"class":304,"line":1104},[302,2106,2107],{"class":524},"        user_message",[302,2109,528],{"class":461},[302,2111,1955],{"class":361},[302,2113,2114,2117,2120],{"class":304,"line":1129},[302,2115,2116],{"class":594},"            \"",[302,2118,2119],{"class":644},"Investigate this machine. First, make a plan in the scratchpad. ",[302,2121,1537],{"class":594},[302,2123,2124,2126,2129],{"class":304,"line":1140},[302,2125,2116],{"class":594},[302,2127,2128],{"class":644},"Then carry it out: learn about the OS, CPU, memory, disk, and ",[302,2130,1537],{"class":594},[302,2132,2133,2135,2138],{"class":304,"line":1145},[302,2134,2116],{"class":594},[302,2136,2137],{"class":644},"recent activity. Record your findings in the scratchpad as you ",[302,2139,1537],{"class":594},[302,2141,2142,2144,2147],{"class":304,"line":1174},[302,2143,2116],{"class":594},[302,2145,2146],{"class":644},"go. When done, synthesize a 200-word report.",[302,2148,1537],{"class":594},[302,2150,2151],{"class":304,"line":1207},[302,2152,2153],{"class":361},"        ),\n",[302,2155,2156],{"class":304,"line":1216},[302,2157,1995],{"class":361},[302,2159,2160],{"class":304,"line":1221},[302,2161,334],{"emptyLinePlaceholder":333},[302,2163,2164],{"class":304,"line":1227},[302,2165,334],{"emptyLinePlaceholder":333},[302,2167,2168,2171,2173,2176,2178,2181],{"class":304,"line":1233},[302,2169,2170],{"class":326},"asyncio",[302,2172,487],{"class":361},[302,2174,2175],{"class":497},"run",[302,2177,441],{"class":361},[302,2179,2180],{"class":497},"main",[302,2182,2183],{"class":361},"())\n",[112,2185,2186],{},"Run it and watch the scratchpad directory:",[293,2188,2192],{"className":2189,"code":2190,"language":2191,"meta":298,"style":298},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","ls .scratchpad\u002F\n# plan.txt   findings-os.txt   findings-cpu.txt   report-draft.txt\n","bash",[129,2193,2194,2202],{"__ignoreMap":298},[302,2195,2196,2199],{"class":304,"line":305},[302,2197,2198],{"class":405},"ls",[302,2200,2201],{"class":644}," .scratchpad\u002F\n",[302,2203,2204],{"class":304,"line":312},[302,2205,2206],{"class":308},"# plan.txt   findings-os.txt   findings-cpu.txt   report-draft.txt\n",[112,2208,2209],{},"The model has partitioned its work. The plan is stored separately from the findings. Each finding has its own key. Compaction can fire freely during this run — the tool results can be masked, the older turns can be summarized — and the agent can still reach its plan and findings on demand.",[112,2211,2212],{},"The second-run test is even more telling:",[293,2214,2216],{"className":295,"code":2215,"language":297,"meta":298,"style":298},"# examples\u002Fch09_followup.py\n# Same harness, different user message, same scratchpad directory.\nawait arun(\n    provider=provider,\n    registry=registry,\n    system=SYSTEM,\n    user_message=\"What did you learn yesterday? Briefly summarize.\",\n)\n",[129,2217,2218,2223,2228,2237,2248,2259,2270,2286],{"__ignoreMap":298},[302,2219,2220],{"class":304,"line":305},[302,2221,2222],{"class":308},"# examples\u002Fch09_followup.py\n",[302,2224,2225],{"class":304,"line":312},[302,2226,2227],{"class":308},"# Same harness, different user message, same scratchpad directory.\n",[302,2229,2230,2233,2235],{"class":304,"line":330},[302,2231,2232],{"class":315},"await",[302,2234,2041],{"class":497},[302,2236,1955],{"class":361},[302,2238,2239,2242,2244,2246],{"class":304,"line":337},[302,2240,2241],{"class":524},"    provider",[302,2243,528],{"class":461},[302,2245,2053],{"class":497},[302,2247,2056],{"class":361},[302,2249,2250,2253,2255,2257],{"class":304,"line":351},[302,2251,2252],{"class":524},"    registry",[302,2254,528],{"class":461},[302,2256,2066],{"class":497},[302,2258,2056],{"class":361},[302,2260,2261,2264,2266,2268],{"class":304,"line":356},[302,2262,2263],{"class":524},"    system",[302,2265,528],{"class":461},[302,2267,1829],{"class":437},[302,2269,2056],{"class":361},[302,2271,2272,2275,2277,2279,2282,2284],{"class":304,"line":373},[302,2273,2274],{"class":524},"    user_message",[302,2276,528],{"class":461},[302,2278,648],{"class":594},[302,2280,2281],{"class":644},"What did you learn yesterday? Briefly summarize.",[302,2283,648],{"class":594},[302,2285,2056],{"class":361},[302,2287,2288],{"class":304,"line":388},[302,2289,505],{"class":361},[112,2291,2292,2293,2296,2297,1577,2300,2303],{},"This session starts fresh — no context, no history — but the agent reads ",[129,2294,2295],{},"scratchpad_list()",", sees ",[129,2298,2299],{},"plan.txt",[129,2301,2302],{},"findings-os.txt",", etc., and reconstructs what the previous agent did. That's persistent agent memory, built out of a directory and three tools.",[254,2305],{},[257,2307,2309],{"id":2308},"_95-claude-codes-claudemd-convention","9.5 Claude Code's CLAUDE.md Convention",[112,2311,2312,2313,2315],{},"Claude Code uses a specific convention worth mentioning because it's publicly documented and informs good scratchpad practice more broadly. A file called ",[129,2314,147],{}," in the project root is included automatically in the agent's system prompt every session. It's a standing instruction: \"these are durable rules for this project.\"",[112,2317,2318],{},"The convention:",[2320,2321,2322,2333,2338],"ul",{},[2323,2324,2325,2326,2328,2329,2332],"li",{},"Top-level ",[129,2327,147],{},": project-wide rules (\"we use pytest; tests live in ",[129,2330,2331],{},"tests\u002F","; the build uses uv\").",[2323,2334,2335,2337],{},[129,2336,147],{}," in subdirectories: rules specific to that subdirectory (\"this code is generated; don't edit directly\").",[2323,2339,2340,2341,2344],{},"A ",[129,2342,2343],{},"# Compact Instructions"," section: \"when compacting, preserve the fact that we use uv, never node.\"",[112,2346,2347],{},"This is a different flavor of scratchpad: the agent doesn't write to it, the human does. It's static, not dynamic. But it fills the same role — persistent context that survives compaction — and the mechanism is identical.",[112,2349,2350,2351,132,2354,2357,2358,2361,2362,2364],{},"Our scratchpad supports both roles. The human can pre-populate files before a session starts; the agent reads them in via ",[129,2352,2353],{},"scratchpad_list",[129,2355,2356],{},"scratchpad_read",". Adding a ",[129,2359,2360],{},"persistent-rules.txt"," and instructing the agent to read it first gives you a ",[129,2363,147],{},"-style mechanism without any special casing.",[254,2366],{},[257,2368,2370],{"id":2369},"_96-concurrency-and-the-single-writer-assumption","9.6 Concurrency and the Single-Writer Assumption",[112,2372,2373],{},"A scratchpad written to by multiple agents at once has the classic shared-state problem. Two sub-agents writing to the same key at the same moment — one wins, one loses, and neither knows. Chapter 17 tackles this head-on with a lease system.",[112,2375,2376,2377,2379,2380,1577,2383,2386],{},"For this chapter, the scratchpad is single-agent. If you run multiple agents in parallel, either give each a different root directory or don't let them write to the same keys. The convention that saves you: keys should include the agent's role or ID for namespacing. ",[129,2378,1625],{}," is fine for one agent; ",[129,2381,2382],{},"plan-investigator",[129,2384,2385],{},"plan-writer"," is the start of what Chapter 17 will formalize.",[254,2388],{},[257,2390,2392],{"id":2391},"_97-what-about-databases","9.7 What About Databases?",[112,2394,2395],{},"A filesystem directory is the simplest scratchpad that could possibly work. Production systems often want more: SQLite for indexing, Redis for speed, Postgres for transactionality, S3 for durability across machines.",[112,2397,2398],{},"The scratchpad interface in Section 9.2 doesn't depend on the backing store. You can swap in a SQLite implementation in about thirty lines:",[293,2400,2402],{"className":295,"code":2401,"language":297,"meta":298,"style":298},"# src\u002Fharness\u002Ftools\u002Fscratchpad_sqlite.py\nimport sqlite3\n\nclass SqliteScratchpad:\n    def __init__(self, db_path: str) -> None:\n        self._conn = sqlite3.connect(db_path)\n        self._conn.execute(\"\"\"\n            CREATE TABLE IF NOT EXISTS scratchpad (\n                key TEXT PRIMARY KEY,\n                content TEXT NOT NULL,\n                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n            )\n        \"\"\")\n\n    def write(self, key: str, content: str) -> str:\n        self._conn.execute(\n            \"INSERT OR REPLACE INTO scratchpad (key, content) VALUES (?, ?)\",\n            (key, content),\n        )\n        self._conn.commit()\n        return f\"wrote {len(content)} chars to scratchpad[{key}]\"\n\n    def read(self, key: str) -> str:\n        row = self._conn.execute(\n            \"SELECT content FROM scratchpad WHERE key = ?\", (key,)\n        ).fetchone()\n        if row is None:\n            raise KeyError(f\"scratchpad[{key}] not found\")\n        return row[0]\n\n    # ... same as_tools() as before\n",[129,2403,2404,2409,2416,2420,2429,2456,2482,2499,2504,2509,2514,2519,2524,2531,2535,2569,2583,2594,2608,2613,2628,2658,2662,2688,2707,2726,2736,2750,2772,2786,2790],{"__ignoreMap":298},[302,2405,2406],{"class":304,"line":305},[302,2407,2408],{"class":308},"# src\u002Fharness\u002Ftools\u002Fscratchpad_sqlite.py\n",[302,2410,2411,2413],{"class":304,"line":312},[302,2412,345],{"class":315},[302,2414,2415],{"class":326}," sqlite3\n",[302,2417,2418],{"class":304,"line":330},[302,2419,334],{"emptyLinePlaceholder":333},[302,2421,2422,2424,2427],{"class":304,"line":337},[302,2423,402],{"class":401},[302,2425,2426],{"class":405}," SqliteScratchpad",[302,2428,409],{"class":361},[302,2430,2431,2433,2435,2437,2439,2441,2444,2446,2448,2450,2452,2454],{"class":304,"line":351},[302,2432,434],{"class":401},[302,2434,438],{"class":437},[302,2436,441],{"class":361},[302,2438,445],{"class":444},[302,2440,448],{"class":361},[302,2442,2443],{"class":451}," db_path",[302,2445,455],{"class":361},[302,2447,466],{"class":465},[302,2449,469],{"class":361},[302,2451,472],{"class":361},[302,2453,476],{"class":475},[302,2455,409],{"class":361},[302,2457,2458,2460,2462,2465,2467,2470,2472,2475,2477,2480],{"class":304,"line":356},[302,2459,484],{"class":319},[302,2461,487],{"class":361},[302,2463,2464],{"class":490},"_conn",[302,2466,494],{"class":461},[302,2468,2469],{"class":326}," sqlite3",[302,2471,487],{"class":361},[302,2473,2474],{"class":497},"connect",[302,2476,441],{"class":361},[302,2478,2479],{"class":497},"db_path",[302,2481,505],{"class":361},[302,2483,2484,2486,2488,2490,2492,2495,2497],{"class":304,"line":373},[302,2485,484],{"class":319},[302,2487,487],{"class":361},[302,2489,2464],{"class":490},[302,2491,487],{"class":361},[302,2493,2494],{"class":497},"execute",[302,2496,441],{"class":361},[302,2498,423],{"class":594},[302,2500,2501],{"class":304,"line":388},[302,2502,2503],{"class":644},"            CREATE TABLE IF NOT EXISTS scratchpad (\n",[302,2505,2506],{"class":304,"line":393},[302,2507,2508],{"class":644},"                key TEXT PRIMARY KEY,\n",[302,2510,2511],{"class":304,"line":398},[302,2512,2513],{"class":644},"                content TEXT NOT NULL,\n",[302,2515,2516],{"class":304,"line":412},[302,2517,2518],{"class":644},"                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n",[302,2520,2521],{"class":304,"line":426},[302,2522,2523],{"class":644},"            )\n",[302,2525,2526,2529],{"class":304,"line":431},[302,2527,2528],{"class":594},"        \"\"\"",[302,2530,505],{"class":361},[302,2532,2533],{"class":304,"line":481},[302,2534,334],{"emptyLinePlaceholder":333},[302,2536,2537,2539,2541,2543,2545,2547,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567],{"class":304,"line":508},[302,2538,434],{"class":401},[302,2540,776],{"class":555},[302,2542,441],{"class":361},[302,2544,445],{"class":444},[302,2546,448],{"class":361},[302,2548,565],{"class":451},[302,2550,455],{"class":361},[302,2552,466],{"class":465},[302,2554,448],{"class":361},[302,2556,793],{"class":451},[302,2558,455],{"class":361},[302,2560,466],{"class":465},[302,2562,469],{"class":361},[302,2564,472],{"class":361},[302,2566,466],{"class":465},[302,2568,409],{"class":361},[302,2570,2571,2573,2575,2577,2579,2581],{"class":304,"line":545},[302,2572,484],{"class":319},[302,2574,487],{"class":361},[302,2576,2464],{"class":490},[302,2578,487],{"class":361},[302,2580,2494],{"class":497},[302,2582,1955],{"class":361},[302,2584,2585,2587,2590,2592],{"class":304,"line":550},[302,2586,2116],{"class":594},[302,2588,2589],{"class":644},"INSERT OR REPLACE INTO scratchpad (key, content) VALUES (?, ?)",[302,2591,648],{"class":594},[302,2593,2056],{"class":361},[302,2595,2596,2599,2601,2603,2605],{"class":304,"line":580},[302,2597,2598],{"class":361},"            (",[302,2600,690],{"class":497},[302,2602,448],{"class":361},[302,2604,793],{"class":497},[302,2606,2607],{"class":361},"),\n",[302,2609,2610],{"class":304,"line":586},[302,2611,2612],{"class":361},"        )\n",[302,2614,2615,2617,2619,2621,2623,2626],{"class":304,"line":653},[302,2616,484],{"class":319},[302,2618,487],{"class":361},[302,2620,2464],{"class":490},[302,2622,487],{"class":361},[302,2624,2625],{"class":497},"commit",[302,2627,1497],{"class":361},[302,2629,2630,2632,2634,2636,2638,2640,2642,2644,2646,2648,2650,2652,2654,2656],{"class":304,"line":669},[302,2631,738],{"class":315},[302,2633,751],{"class":401},[302,2635,868],{"class":644},[302,2637,687],{"class":686},[302,2639,873],{"class":437},[302,2641,441],{"class":361},[302,2643,842],{"class":497},[302,2645,469],{"class":361},[302,2647,696],{"class":686},[302,2649,884],{"class":644},[302,2651,687],{"class":686},[302,2653,690],{"class":326},[302,2655,696],{"class":686},[302,2657,893],{"class":644},[302,2659,2660],{"class":304,"line":704},[302,2661,334],{"emptyLinePlaceholder":333},[302,2663,2664,2666,2668,2670,2672,2674,2676,2678,2680,2682,2684,2686],{"class":304,"line":717},[302,2665,434],{"class":401},[302,2667,906],{"class":555},[302,2669,441],{"class":361},[302,2671,445],{"class":444},[302,2673,448],{"class":361},[302,2675,565],{"class":451},[302,2677,455],{"class":361},[302,2679,466],{"class":465},[302,2681,469],{"class":361},[302,2683,472],{"class":361},[302,2685,466],{"class":465},[302,2687,409],{"class":361},[302,2689,2690,2693,2695,2697,2699,2701,2703,2705],{"class":304,"line":735},[302,2691,2692],{"class":326},"        row ",[302,2694,528],{"class":461},[302,2696,741],{"class":319},[302,2698,487],{"class":361},[302,2700,2464],{"class":490},[302,2702,487],{"class":361},[302,2704,2494],{"class":497},[302,2706,1955],{"class":361},[302,2708,2709,2711,2714,2716,2718,2721,2723],{"class":304,"line":766},[302,2710,2116],{"class":594},[302,2712,2713],{"class":644},"SELECT content FROM scratchpad WHERE key = ?",[302,2715,648],{"class":594},[302,2717,448],{"class":361},[302,2719,2720],{"class":361}," (",[302,2722,690],{"class":497},[302,2724,2725],{"class":361},",)\n",[302,2727,2728,2731,2734],{"class":304,"line":771},[302,2729,2730],{"class":361},"        ).",[302,2732,2733],{"class":497},"fetchone",[302,2735,1497],{"class":361},[302,2737,2738,2740,2743,2746,2748],{"class":304,"line":808},[302,2739,656],{"class":315},[302,2741,2742],{"class":326}," row ",[302,2744,2745],{"class":461},"is",[302,2747,476],{"class":475},[302,2749,409],{"class":361},[302,2751,2752,2754,2756,2758,2760,2762,2764,2766,2768,2770],{"class":304,"line":829},[302,2753,672],{"class":315},[302,2755,971],{"class":465},[302,2757,441],{"class":361},[302,2759,680],{"class":401},[302,2761,978],{"class":644},[302,2763,687],{"class":686},[302,2765,690],{"class":497},[302,2767,696],{"class":686},[302,2769,987],{"class":644},[302,2771,505],{"class":361},[302,2773,2774,2776,2779,2781,2784],{"class":304,"line":861},[302,2775,738],{"class":315},[302,2777,2778],{"class":326}," row",[302,2780,1042],{"class":361},[302,2782,2783],{"class":686},"0",[302,2785,1564],{"class":361},[302,2787,2788],{"class":304,"line":896},[302,2789,334],{"emptyLinePlaceholder":333},[302,2791,2792],{"class":304,"line":901},[302,2793,2794],{"class":308},"    # ... same as_tools() as before\n",[112,2796,2797,2798,2801],{},"We don't swap in SQLite in the main harness because the filesystem version is enough for the book's scenarios, and it has the pedagogical advantage that you can ",[129,2799,2800],{},"cat"," a scratchpad file and read what the agent wrote. Chapter 21 revisits persistent state when we build full session checkpointing; at that point, SQLite or Postgres earns its keep.",[254,2803],{},[257,2805,2807],{"id":2806},"_98-commit","9.8 Commit",[293,2809,2811],{"className":2189,"code":2810,"language":2191,"meta":298,"style":298},"git add -A && git commit -m \"ch09: scratchpad — durable external state for the agent\"\ngit tag ch09-scratchpad\n",[129,2812,2813,2844],{"__ignoreMap":298},[302,2814,2815,2818,2821,2825,2828,2831,2834,2837,2839,2842],{"class":304,"line":305},[302,2816,2817],{"class":405},"git",[302,2819,2820],{"class":644}," add",[302,2822,2824],{"class":2823},"stzsN"," -A",[302,2826,2827],{"class":361}," &&",[302,2829,2830],{"class":405}," git",[302,2832,2833],{"class":644}," commit",[302,2835,2836],{"class":2823}," -m",[302,2838,641],{"class":594},[302,2840,2841],{"class":644},"ch09: scratchpad — durable external state for the agent",[302,2843,1537],{"class":594},[302,2845,2846,2848,2851],{"class":304,"line":312},[302,2847,2817],{"class":405},[302,2849,2850],{"class":644}," tag",[302,2852,2853],{"class":644}," ch09-scratchpad\n",[257,2855,2857],{"id":2856},"_99-try-it-yourself","9.9 Try It Yourself",[2859,2860,2861,2867,2880],"ol",{},[2323,2862,2863,2866],{},[270,2864,2865],{},"Measure the context savings."," Run the Chapter 8 long-session scenario (with heavy tool outputs) twice: once without the scratchpad, once with a system prompt that tells the agent to store intermediate findings. Compare peak context utilization and the number of compaction cycles fired.",[2323,2868,2869,2872,2873,2876,2877,2879],{},[270,2870,2871],{},"Catch a misuse."," Add a tool that deliberately uses a non-alphanumeric key: ",[129,2874,2875],{},"pad.write(\"..\u002F..\u002Fetc\u002Fevil\", \"oops\")",". Confirm it raises. Remove the sanitization; confirm it doesn't. That five-line ",[129,2878,820],{}," function is a small but real security boundary.",[2323,2881,2882,2885],{},[270,2883,2884],{},"Run the two-session test."," Run the investigation scenario; kill the process; start it again with a different user message asking about what the previous session discovered. Did the new session reconstruct the old one's state usefully? If not, what was missing from the scratchpad writes?",[254,2887],{},[2889,2890,2891,2902],"what-you-understand",{},[112,2892,2893,2894,2897,2898,2901],{},"The scratchpad pattern gives the agent durable state outside the context window. Three small tools, backed by a directory, teach the model to separate what it's ",[115,2895,2896],{},"doing"," (context) from what it's ",[115,2899,2900],{},"keeping"," (scratchpad). Compaction can do its worst and the agent's plan, findings, and decisions stay intact. The pattern extends cleanly — different backing stores, different keying conventions, different persistence models — but the interface is the same.",[112,2903,2904,2905,2907],{},"What's still missing: retrieval. The scratchpad lets the agent write-then-read what ",[115,2906,123],{}," produced. But sometimes it needs to reach for something it never produced — an existing codebase file, a documentation page, a database schema it didn't create. Loading all of that into context is the Break-5 problem all over again. Chapter 10 adds retrieval: the agent searches, gets relevant chunks back, and lets the harness place them at the right position in context to dodge the lost-in-the-middle penalty.",[2909,2910,2911],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s2W-s, html code.shiki .s2W-s{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}html pre.shiki code .sithA, html code.shiki .sithA{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#032F62;--shiki-default-font-style:inherit;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smCYv, html code.shiki .smCYv{--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#24292E;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .sFwrP, html code.shiki .sFwrP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#24292E;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .slqww, html code.shiki .slqww{--shiki-light:#6182B8;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .stp6e, html code.shiki .stp6e{--shiki-light:#39ADB5;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":298,"searchDepth":312,"depth":312,"links":2913},[2914,2915,2916,2917,2918,2919,2920,2921,2922],{"id":259,"depth":312,"text":260},{"id":287,"depth":312,"text":288},{"id":1607,"depth":312,"text":1608},{"id":1631,"depth":312,"text":1632},{"id":2308,"depth":312,"text":2309},{"id":2369,"depth":312,"text":2370},{"id":2391,"depth":312,"text":2392},{"id":2806,"depth":312,"text":2807},{"id":2856,"depth":312,"text":2857},"md",{},null,{"title":46,"description":117},"ibKfVQp2_snghQLeHbu-XV0H2atDrGKvriHccECUumk",[2929,2931],{"title":42,"path":43,"stem":44,"description":2930,"children":-1},"Previously: the accountant sees the context window. Red state is detected but not acted upon. The transcript keeps growing until the provider refuses to accept it.",{"title":50,"path":51,"stem":52,"description":2932,"children":-1},"Previously: the scratchpad gave the agent durable state for what it produces. What it doesn't cover is what the agent needs to read from but didn't write — a codebase it's exploring, documentation, a knowledge base that's larger than the context window could hold even empty.",1776848984225]