<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Decoding AI Magazine]]></title><description><![CDATA[Join for content on designing, building, and shipping AI software. Learn AI engineering, end-to-end, from idea to production. Every Tuesday.]]></description><link>https://www.decodingai.com</link><image><url>https://substackcdn.com/image/fetch/$s_!k2ig!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00bc74e0-3601-49ce-8ab9-4c7b499ce597_1280x1280.png</url><title>Decoding AI Magazine</title><link>https://www.decodingai.com</link></image><generator>Substack</generator><lastBuildDate>Fri, 09 Oct 2026 21:54:59 GMT</lastBuildDate><atom:link href="https://www.decodingai.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Paul-Emil Iusztin]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[decodingai@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[decodingai@substack.com]]></itunes:email><itunes:name><![CDATA[Paul Iusztin]]></itunes:name></itunes:owner><itunes:author><![CDATA[Paul Iusztin]]></itunes:author><googleplay:owner><![CDATA[decodingai@substack.com]]></googleplay:owner><googleplay:email><![CDATA[decodingai@substack.com]]></googleplay:email><googleplay:author><![CDATA[Paul Iusztin]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The Agentic Software Factory Hierarchy of Needs]]></title><description><![CDATA[How to build software with agents that keep working while you&#8217;re away]]></description><link>https://www.decodingai.com/p/the-agentic-software-factory-hierarchy</link><guid isPermaLink="false">https://www.decodingai.com/p/the-agentic-software-factory-hierarchy</guid><dc:creator><![CDATA[Hugo Bowne-Anderson]]></dc:creator><pubDate>Fri, 09 Oct 2026 11:01:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ca6368af-b87b-477f-a641-00c30f446ffa_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em>This article originally appeared in Hugo&#8217;s newsletter, <a href="https://hugobowne.substack.com/p/the-agentic-software-factory-hierarchy">Vanishing Gradients</a>, and is republished here with the authors&#8217; permission.</em></p></div><p><strong>Paul:</strong> Today, two of&nbsp;the industry&#8217;s brilliant minds own the scene.</p><p>You&#8217;ll learn from Hugo, who teaches LLM systems to engineers at Netflix and Meta, and Eleanor, a former principal engineer at Microsoft and Google who&#8217;s now building evidence-based, production-ready AI at Jimini Health and Agentic Ventures. </p><p>They&#8217;ve created this dope course on&nbsp;<a href="https://maven.com/agentic-ventures/agent-factory?promoCode=FRIENDSOFPAUL&amp;utm_source=paul_substack&amp;utm_medium=newsletter&amp;utm_campaign=agent_factory&amp;utm_content=paul_hierarchy_essay_2026_10_08">building an agentic software factory.</a><em>&nbsp;Decoding AI community members get 25% off via the link or code FRIENDSOFPAUL at checkout,&nbsp;</em>plus&nbsp;<em>$500 in Modal credits.</em>&nbsp;</p><p><em>P.S.</em> <em>Take notes on this one.</em> &#9997;&#127996;</p><div><hr></div><h2>Agentic software factories are here</h2><p><em><a href="https://stripe.dev/blog/minions-stripes-one-shot-end-to-end-coding-agents">Stripe&#8217;s Minions</a> turn engineering requests into candidate pull requests. <a href="https://engineering.ramp.com/post/why-we-built-our-background-agent">Ramp&#8217;s Inspect</a> puts coding agents to work in the background, with tools to check their changes. <a href="https://docs.warp.dev/factories/">Warp Factories</a> takes work from tickets and chat through agents, checks, and human review. <strong>Agentic software factories are here.</strong></em></p><p>Are you sick and tired of babysitting Codex, Claude Code, or OpenClaw?</p><p>Do you have agents that can build features, but still leave you responsible for remembering where they stopped, explaining how each feature fits the project and deciding what happens next? You make progress in each conversation, then development waits for you to return.</p><p>It doesn&#8217;t have to be this way. A software factory lets you delegate more of that process!</p><p>You agree on an outcome, give the system the context and authority it needs, and let it work while you do something else. When you return, there should be</p><ol><li><p>a result you can inspect, with evidence of what was checked; or</p></li><li><p>a specific reason the work could not continue.</p></li></ol><p>Your next conversation can then focus on the result and the decisions that remain.</p><p>As we&#8217;ll show you, your first software factory doesn&#8217;t need to be that complex at all: it can begin with a single agent and an automation.</p><h2>What makes it a factory</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sKpW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sKpW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 424w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 848w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 1272w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sKpW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sKpW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 424w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 848w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 1272w, https://substackcdn.com/image/fetch/$s_!sKpW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffab84faf-d6eb-4a8e-b121-2cf275006728_1456x819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The defining combination is <strong>autonomous and asynchronous execution</strong>.</p><ul><li><p><strong>Autonomous:</strong> the agent chooses and carries out steps towards an agreed goal. It can inspect what happened, adjust its approach and continue within its authority.</p></li><li><p><strong>Asynchronous:</strong> that work can proceed without your ongoing attention. You can leave and return to its result.</p></li></ul><p>A scheduled job can run without you. A coding agent can choose and revise an approach during an interactive session. A factory combines those capabilities, with enough context, tools and feedback to carry out the delegated work.</p><p>Software factories have been hypothesized for decades. Now that we have agents, we&#8217;re actually able to operate them. The principles apply to software work traditionally carried out by teams of humans, from bespoke tools for teams and individuals to large and complex software systems.</p><p>To illustrate these principles, we&#8217;ll use an invoice tracker throughout this article, an application we&#8217;ve needed for our own businesses. The same approach applies to research tools, publishing systems and software for teams. Suppose you run a small business and want an invoice tracker that fits how you work:</p><p><em>Build an app that creates invoices from my template and tracks which are unpaid, paid or overdue. Keep it local for now. Preserve the records when it restarts, and show me checks that the totals and payment statuses are correct.</em></p><p>You can agree on this brief with the agent, leave it to work while you do something else, and return to the app and evidence of what was checked. If a check fails, it can investigate and adjust within its agreed scope. If it encounters a product decision it cannot make, it should bring that question back to you.</p><p>You might imagine a clean separation: the factory builds the invoice tracker, then the finished app does its job. That&#8217;s one way to run it. But agents can also help operate the software they build, and that combination is useful.</p><p>The tracker can store invoices and calculate outstanding balances. An agent can use those records alongside customer correspondence to prepare follow-ups: one customer has promised to pay on Friday; another is disputing a charge. You don&#8217;t need to turn every situation into a new software feature before the agent can help. You give it the relevant context, authority and a way to check its work.</p><p>This changes what you need to build! Some behaviour belongs in code, such as calculating balances consistently. Other work can be delegated to an agent that responds to the circumstances. If a recurring need emerges, you can ask the factory to build it into the software. The factory builds tools that agents can use, and experience using those tools helps you decide what to build next.</p><p>You still decide what is worth building, who it should serve and which trade-offs matter. Agents can help you make those decisions too. The practical change is that implementation can proceed between your conversations, including running checks and responding to failures.</p><p><em>This makes factories relevant to people with product, business or creative expertise as well as engineers. You might know exactly how you invoice clients, record payments and chase overdue bills while having little interest in writing software. That knowledge lets you direct the factory towards software that fits your business, including the exceptions and connections that general-purpose tools handle poorly.</em></p><h2>The software factory hierarchy of needs</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MkDl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MkDl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 424w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 848w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 1272w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MkDl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png" width="1254" height="1254" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1254,&quot;width&quot;:1254,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MkDl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 424w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 848w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 1272w, https://substackcdn.com/image/fetch/$s_!MkDl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ceaf8-8d9a-44ba-bc91-96cff3635a3b_1254x1254.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>At every layer: specify what you want and how success will be checked, then verify the result.</em></figcaption></figure></div><p><a href="https://hackernoon.com/the-ai-hierarchy-of-needs-18f111fcc007">Monica Rogati&#8217;s original AI hierarchy of needs</a> described the foundations beneath successful AI work. We find that dependency framing helpful for factories too, with four different layers.</p><ol><li><p><strong>Harness.</strong> The environment around the model: tools, a workspace for project files, execution and feedback. It lets an agent read files, change software and run it. If a check fails, the harness must give the agent enough information to investigate what happened.</p></li><li><p><strong>Personalisation.</strong> The context and capabilities for your work: project direction, rules, reference material, skills and connections to other systems. The agent needs to know what you are trying to accomplish and which existing decisions it should preserve. Permissions limit access to tools and systems; sandboxing restricts the environment where actions can run.</p></li><li><p><strong>Automation.</strong> A way to start and continue work without a fresh instruction from you each time. A schedule or event can trigger a task or the pickup of ready work. It also needs direction about what qualifies as ready and where to leave the result.</p></li><li><p><strong>Continual learning.</strong> A process for learning from completed and failed runs, improving the factory and carrying those changes into later work. That might change an instruction, a checking procedure or a tool the agent uses.</p></li></ol><p><strong>Automation</strong> needs a harness able to do the work, plus direction about what to do. <strong>Continual learning</strong> needs runs to inspect and a way to put improvements into use. These capabilities can develop together: a familiar harness, a short brief and a basic automation are enough to start. You can personalise further as work reveals what is missing.</p><p>Two practices run through every layer: <strong>specification </strong>and<strong> verification</strong>:</p><ul><li><p>Specification makes the intended outcome, constraints and criteria for success explicit. In our invoice brief, that includes preserving records after a restart and calculating payment statuses correctly.</p></li><li><p>Verification checks the software and the work agents perform against those requirements.</p></li></ul><p>Agents can help you refine the specification and perform the checks. Your role is to decide whether the requirements capture what you need and whether the evidence supports accepting the result. As the factory takes on more work, these practices give you a way to direct it and assess what comes back.</p><p>Let&#8217;s now see what&#8217;s up in each layer.</p><h2>1. Agent harness</h2><p>First, you&#8217;ll need an agent harness. If you&#8217;re using Codex, Claude Code, Hermes, or OpenClaw, you already have one. It gives the model tools to read and edit files, run your software and see what happened.</p><p>For our invoice tracker, the agent can build the app, create an invoice, record a payment and restart it to check that the invoice and payment records survived. If a paid invoice still shows as overdue, it can investigate, fix the problem and try again. You shouldn&#8217;t have to narrate every step. But if it needs a decision about how your business handles partial payments, that&#8217;s a question for you. If it lacks access or authority, the agent should stop and name the blocker.</p><p>You&#8217;ll also need somewhere for the harness to run. A cloud machine lets the agent keep working while your laptop is closed or disconnected. You can also run it on your own computer, but the machine needs to stay awake and connected for the work to continue.</p><h2>2. Personalisation</h2><p>Next, give the agent the context it needs to work your way. For our invoice tracker, that means your template, payment terms and conventions for recording payments. You don&#8217;t want to explain all of that again every time you start a new task.</p><p>Keep it somewhere future workers can find it:</p><ul><li><p><strong>Rules:</strong> preserve existing invoice records; ask before changing payment-status calculations.</p></li><li><p><strong>References:</strong> your template, payment terms and example invoices.</p></li><li><p><strong>Skills:</strong> repeatable procedures for testing invoice creation, payment updates and persistence.</p></li></ul><p>An instruction file such as AGENTS.md can point to this material. <a href="https://openai.com/index/harness-engineering/">OpenAI&#8217;s harness-engineering account</a> describes using a short guide that points into maintained project documentation. Give a new or scheduled worker a small task and check that it actually follows the guidance.</p><p>Be specific about when instructions apply. Eleanor once told an agent to write tests, and it wrote tests for a README. Enthusiasm wasn&#8217;t the problem &#128514;</p><p>You&#8217;ll also need to set permissions and sandboxing to control what the agent can access and execute. Written instructions alone don&#8217;t enforce those boundaries!</p><h2>3. Automation</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BKrc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BKrc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BKrc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BKrc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!BKrc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6bde02d2-6dd2-4ea6-bdf6-8f854af19971_1672x941.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>One agent works in the background; you assess what comes back.</em></figcaption></figure></div><p>Now let&#8217;s give the factory a way to get started without waiting for you. A schedule or event can launch an agent with its brief, project guidance and tools. You come back to a result, evidence of what was checked or a specific blocker that needs your attention.</p><h3>One agent working in the background</h3><p>For our invoice tracker, a morning automation could check a saved task list and pick up the next agreed task, such as adding partial payments. You&#8217;ve decided what you want and how success will be checked. The agent gets on with it while you do something else.</p><p>There are a few practical details to get right. Don&#8217;t start the same task twice, leave an empty queue alone, and set limits on time and spending. Save progress so a later session can continue without you having to reconstruct the whole conversation.</p><p>One worker may be plenty. But perhaps you have independent tasks that could run in parallel, or you&#8217;d like another agent to review a change. That&#8217;s where coordination comes in.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0i3U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0i3U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0i3U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0i3U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!0i3U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd3b8f59-7f55-401a-a835-dd9e90484b77_1672x941.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Coordinate ready work, then check the combined result.</em></figcaption></figure></div><h3>Coordinated work</h3><p>With several agents, everyone needs somewhere to see what&#8217;s ready, what&#8217;s underway and what&#8217;s waiting on something else. A shared task list or issue tracker can hold that information. You agree which tasks are ready; a coordinating agent or automation assigns them, supplies the relevant context and records what happens.</p><p>Suppose one task adds partial payments, another overdue follow-up emails, and a third PDF exports. Follow-ups need the correct outstanding balance, so they wait for the payment behaviour to be checked. PDF exports might proceed independently if the changes don&#8217;t overlap.</p><p>You can also split the roles. One agent builds the feature while another prepares payment scenarios to test it. A third might review the completed change.</p><p>Assign responsibility for combining the changes and verifying the whole application. Different questions call for different checks. Deterministic tests can establish whether balances are calculated correctly and payments survive a restart. Agent verification can help identify missed requirements or inconsistencies across the changes. Human judgment can assess whether the workflow fits how you actually work. You&#8217;ll often want a combination, with more than one kind of check on the same result. <a href="https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents">Anthropic&#8217;s evaluation guide</a> describes these complementary approaches: code-based checks, model-based checks and human evaluation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TYgA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TYgA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TYgA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TYgA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!TYgA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6880dd6-0c10-4a61-a40f-144219ab57e1_1536x1024.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Combine deterministic checks, agent verification and human judgment according to what you need to establish.</em></figcaption></figure></div><p>Once you&#8217;ve checked that the combined features work together, you might task your factory with building a phone-friendly interface so you can check invoices and record payments on the move.</p><p>The factory can also help run the invoicing workflow as well as improve its software. A scheduled agent could review overdue invoices, consult customer correspondence and prepare follow-ups for your approval. If that work repeatedly requires information the tracker doesn&#8217;t record, you can give the factory a task to add it. Building and operating feed into one another: agents use the software, and what happens in use informs its next improvement. This brings us to continual learning.</p><h2>4. Continual learning</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YwBc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YwBc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YwBc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YwBc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 424w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 848w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 1272w, https://substackcdn.com/image/fetch/$s_!YwBc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29d3305d-f61e-4f83-971f-87c306064cb8_1672x941.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Use run evidence to test and adopt improvements to future work.</em></figcaption></figure></div><p>Your factory can also get better at how it works. Suppose payments disappear after restarting the invoice tracker, even though the agent reported that its checks passed. You&#8217;ll want it to fix the bug, of course. But why did its checks miss the problem?</p><p>Keep a record of assignments, checks and difficulties so a review agent can identify recurring problems and propose improvements. Did the worker lack a way to restart the app, or did it simply skip that check?</p><p>If it skipped the check, the agent could propose a skill that saves a payment, restarts the app and verifies the remaining balance whenever a change affects stored records. Test it against the original failure, then on further tasks. Does it catch problems with stored customer details too? Does it avoid unnecessary checks when a task only changes a heading?</p><p>The results help you decide whether to adopt, revise or reject the method. Apply changes within the authority you&#8217;ve agreed and keep them reversible. <a href="https://docs.warp.dev/factories/measure-and-improve/self-improvement/">Warp&#8217;s self-improving factories</a> illustrate this approach: failed checks can lead to proposed changes to prompts, skills or configuration, submitted for human review with evidence from the runs behind them.</p><p>Reassess methods as the project and model change. <a href="https://www.anthropic.com/engineering/harness-design-long-running-apps">Anthropic&#8217;s work on long-running application development</a> describes removing procedures as model capabilities improved and checking the effect.</p><p>A saved lesson needs to reach later workers and improve their results. This learning happens through changes to the instructions, tools and methods around the model, without requiring the model itself to be retrained.</p><h2>What would you build?</h2><p>Your factory could build a research tool that collects sources and lets you assemble briefings, a family intranet for shared plans and documents, or a private community space. Start with something useful to you, then give the factory further work as you discover what&#8217;s missing. Agents can also help operate what you build, from preparing a research briefing to organising incoming material.</p><p>Hugo uses this combination to run Vanishing Gradients, his media and education business. After a guest prep call, an automation retrieves the transcript and prepares interview topics, questions, titles and thumbnail options for review. After a livestream, agents can propose clips, cut video, add captions and prepare upload drafts. Saved editorial guidance and skills shape the work; Hugo chooses what to publish.</p><p>He also maintains the system, improving checks when agents miss instructions and updating skills based on results. More autonomous continual learning remains something he&#8217;s exploring. He describes the setup in <a href="https://maven.com/p/5ee8b7">How I Built a Media Empire With an Agentic Software Factory</a>.</p><p><em><strong>What&#8217;s one simple task you do repeatedly for your community, audience or business that you could start automating?</strong></em></p><h2>Decide what your factory needs next</h2><p>Look at what keeps bringing you back to the work. If the agent cannot run the app or inspect a failure, improve the harness. If you keep repeating project context and decisions, personalise it. If development waits for you to start each task or manage every handover, add automation. If the same failures recur across runs, build a learning loop that changes how later work is done.</p><p>Start with work you care about and inspect what comes back. One agent can use all four layers. Add capabilities where they help you delegate more useful work, while keeping specification and verification part of the process throughout.</p><h3>Build your own software factory</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tCox!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tCox!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 424w, https://substackcdn.com/image/fetch/$s_!tCox!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 848w, https://substackcdn.com/image/fetch/$s_!tCox!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 1272w, https://substackcdn.com/image/fetch/$s_!tCox!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tCox!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png" width="1456" height="762" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:762,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tCox!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 424w, https://substackcdn.com/image/fetch/$s_!tCox!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 848w, https://substackcdn.com/image/fetch/$s_!tCox!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 1272w, https://substackcdn.com/image/fetch/$s_!tCox!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbd6e57f-3a69-44ff-8b19-f892af249c35_1730x905.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Ready to put these ideas to work? Hugo and Eleanor teach <strong><a href="https://vanishinggradients.short.gy/friends-of-paul">Build Your Agentic Software Factory</a></strong>, a two-week course where you&#8217;ll build a factory around something you want to create.</p><p>You&#8217;ll put the practices in this essay to use: give agents direction, set them working in the background, and learn to inspect and verify what comes back. <strong>You&#8217;ll leave with software of your own and a process you can keep using to build for yourself, your team or your business.</strong></p><p>Bring an idea you&#8217;re excited about, or choose a provided starter project. <strong>No coding experience is required.</strong> The course runs <strong>October 13&#8211;22, 2026</strong>, with two live workshops, office hours for help with your setup and project, and a community of fellow builders.</p><p><strong>Every student also gets $500 in Modal credits</strong> to run agent jobs in the cloud, experiment with open-weight models, or host something they&#8217;ve built. Your factory can keep working while your laptop is off.</p><p>Hugo and Eleanor are kindly offering my community <strong>25% off</strong>, bringing the price from <strong>$950 to $712.50 USD</strong>. The link below applies the discount automatically, or you can enter <strong>FRIENDSOFPAUL</strong> at checkout.</p><p><strong><a href="https://vanishinggradients.short.gy/friends-of-paul">Join Hugo and Eleanor and build your factory.</a></strong></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/the-agentic-software-factory-hierarchy?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/the-agentic-software-factory-hierarchy?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images and videos are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Stop Guessing. Evaluate Your RAG App.]]></title><description><![CDATA[From vibe checks to a 61-case score you ship on, in 5 steps]]></description><link>https://www.decodingai.com/p/rag-evals-change-prompts</link><guid isPermaLink="false">https://www.decodingai.com/p/rag-evals-change-prompts</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 06 Oct 2026 05:00:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!B6x4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B6x4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B6x4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B6x4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Nothing leaves the line until it passes the test.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Nothing leaves the line until it passes the test." title="Nothing leaves the line until it passes the test." srcset="https://substackcdn.com/image/fetch/$s_!B6x4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!B6x4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbfa11215-7f38-44ea-8bfa-a3f02f4c9d88_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em><span data-color="#c02f26" style="color: rgb(192, 47, 38);">&#8220;When I change it, what if something else breaks?&#8221;</span></em>  That&#8217;s what Alexey Grigorev told me about the long system prompt behind his RAG app. If you&#8217;ve ever hesitated before editing a prompt that works, you know the feeling.</p><div class="callout-block" data-callout="true"><p>&#128227;<em> This article is based on an interview with the legend </em><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Alexey Grigorev&quot;,&quot;id&quot;:2259961,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54a0ec21-251b-49e2-aba6-93c13f3cd8cb_800x800.jpeg&quot;,&quot;uuid&quot;:&quot;b2ef2380-807f-4a7a-b588-bd15ee767cd5&quot;}" data-component-name="MentionToDOM"></span><em>. He spent 15 years as a software and AI engineer and founded DataTalks.Club, one of the world&#8217;s largest data communities. There&#8217;s a good chance you know him from there.</em></p></div><p>Here is the thing&#8230; His first AI app version shipped and works fine. Then corrections pile up, and every fix grows the prompt into a huge monolith that rigidly handles each use case. Alexey wanted to clean it up, since it clearly adds a lot of noise, but without a way to measure the impact of trimming parts of it, he was too afraid to do it.</p><p>That&#8217;s why he had to add evals to his RAG app. Otherwise, you find out something broke only when a user tells you. As Alexey puts it: <em>&#8220;without evals you are blind.&#8221;</em></p><p><em>But now we have another problem...</em></p><p>When you finally want evals, you discover you never recorded the interactions you&#8217;d need. Most people don&#8217;t add observability like <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik</a> on day zero, so <em>&#8220;build a gold dataset first&#8221;</em> becomes a dream that never happens.</p><p>We will walk you through Alexey&#8217;s end-to-end eval workflow for his RAG app, built from proxy data when he had no traces. His RAG app is a FAQ chatbot integrated into his Slack DataTalks.Club community, which runs <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">free courses (the Zoomcamps) for 100k+ learners</a>. A perfect scenario for real-world RAG evals.</p><p>First, we will quickly look at the RAG app we will work with. Then we will focus entirely on <strong>the 5 steps you need to evaluate</strong> it: collect the data, build the eval set, build the evaluators, run them, and close the loop.</p><h2>The RAG app: a FAQ system built on GitHub issues</h2><p>DataTalks.Club courses are free, so thousands of people ask questions in their Slack. Some are unique, but <em>&#8220;this is not the case for 99% of the questions.&#8221;</em> At the top of the list is <em>&#8220;I just discovered the course, can I still join?&#8221;</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j9oS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j9oS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 424w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 848w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 1272w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j9oS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png" width="1456" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Repeat questions in the LLM Zoomcamp Slack, the problem the FAQ system exists to absorb.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Repeat questions in the LLM Zoomcamp Slack, the problem the FAQ system exists to absorb." title="Repeat questions in the LLM Zoomcamp Slack, the problem the FAQ system exists to absorb." srcset="https://substackcdn.com/image/fetch/$s_!j9oS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 424w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 848w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 1272w, https://substackcdn.com/image/fetch/$s_!j9oS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ef2d75a-1efa-466b-a111-01fa50ae1098_2004x1084.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Repeat questions in the LLM Zoomcamp Slack, the problem the FAQ system exists to absorb. <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">Source</a></em></figcaption></figure></div><p>From an AI engineering perspective, their FAQ system is a RAG app that indexes all student questions into a light on-disk index that can be queried from Slack via the <code>:faq:</code> tag. A student asks a question; Alexey marks it with the tag; then a webhook triggers an AWS Lambda function that retrieves the top-k FAQs from the questions index, passes them to an LLM that compiles the answer, and posts the answer back in Slack.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-iR-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-iR-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-iR-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg" width="1080" height="1498" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1498,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!-iR-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-iR-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac0e918b-8a39-401c-923e-9aa608096bfa_1080x1498.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">Source</a> </figcaption></figure></div><blockquote><p>The system is available in the DataTalksClub <a href="https://github.com/DataTalksClub/faq">GitHub repository</a>, along with the FAQ dataset, where we have one Markdown file per question.</p></blockquote><p>During ingestion, a &#8220;FAQ proposal&#8221; issue triggers a GitHub Action that retrieves similar questions with <strong>minsearch</strong>, Alexey&#8217;s lightweight text-search library. It then <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">asks an LLM with structured output for one decision</a>: <code>NEW</code>, <code>UPDATE</code>, <code>DUPLICATE</code>, or <code>WRONG_COURSE</code>. <code>NEW</code> and <code>UPDATE</code> open a pull request Alexey reviews, while <code>DUPLICATE</code> and <code>WRONG_COURSE</code> close the issue. When looking for similar questions, it searches using both the question and the full record, merging all records via Reciprocal Rank Fusion (RRF).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jQ9k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jQ9k!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 424w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 848w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 1272w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jQ9k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png" width="1200" height="515" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:515,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How the FAQ automation classifies a contributed question: two searches fused with RRF, one LLM decision, and only two of the four outcomes ever reach a human.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How the FAQ automation classifies a contributed question: two searches fused with RRF, one LLM decision, and only two of the four outcomes ever reach a human." title="How the FAQ automation classifies a contributed question: two searches fused with RRF, one LLM decision, and only two of the four outcomes ever reach a human." srcset="https://substackcdn.com/image/fetch/$s_!jQ9k!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 424w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 848w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 1272w, https://substackcdn.com/image/fetch/$s_!jQ9k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc88ed173-e6f8-4653-9df0-425c374db2fe_1200x515.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>How the FAQ automation classifies a contributed question: 2 searches fused with RRF, one LLM decision, and only 2 of the 4 outcomes ever reach a human.</em></figcaption></figure></div><p>We are not here to see how this RAG app works (if interested, full breakdown <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">here</a>), but to see how we can evaluate it, starting with the most important part: building the AI evals dataset.</p><h2>Step 1: Collect the data, even if you never traced it</h2><p>Alexey is &#8220;totally for vibe checks&#8221; early on. But from the very beginning, while you&#8217;re still vibe coding, ask your AI assistant to record every interaction, and your future eval set collects itself.</p><p>Alexey didn&#8217;t: <em>&#8220;My goal was to just get this out and test how it works.&#8221;</em> It worked. Then corrections piled up, but the system prompt got too big and noisy, and he was too afraid to touch it for fear of breaking something.</p><p>Today it&#8217;s stored in Opik&#8217;s prompt library:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CAZN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CAZN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 424w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 848w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 1272w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CAZN!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png" width="1200" height="623.9010989010989" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:757,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The FAQ curation prompt in Opik's prompt library.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="The FAQ curation prompt in Opik's prompt library." title="The FAQ curation prompt in Opik's prompt library." srcset="https://substackcdn.com/image/fetch/$s_!CAZN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 424w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 848w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 1272w, https://substackcdn.com/image/fetch/$s_!CAZN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F996bb65e-e3b3-4d7a-a5b5-2c9ba06daa3c_3114x1620.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>&#128680; <strong>His core problem was that he had no traces to build the evals dataset from!</strong></p><p>So he used proxy data. Every FAQ contribution was a GitHub issue, and every correction was a commit on a PR. Issues give the inputs, and his corrections tell him what the output should have been. This meant he had access to the input, generated output, and expected output triplets he needed for evals.</p><p>How about reading the data yourself or being lazy (or optimal!) and using an LLM to do so? Alexey does &#8220;Both.&#8221; He lets PRs pile up for a few weeks, then clears them in one session with his AI coding assistant and a custom <code>clear-backlog</code><a href="https://github.com/DataTalksClub/faq/blob/main/.agents/skills/clear-backlog/SKILL.md"> skill</a>. The assistant proposes &#8220;merge,&#8221; &#8220;fix this first,&#8221; or &#8220;this case is interesting, let&#8217;s add it to our evals.&#8221; His job: &#8220;I just need to agree or disagree.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j7QK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j7QK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 424w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 848w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 1272w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j7QK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png" width="1456" height="444" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:444,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Clearing the PR backlog in one session: \&quot;let's go through the backlog\&quot; loads the clear-backlog skill.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Clearing the PR backlog in one session: &quot;let's go through the backlog&quot; loads the clear-backlog skill." title="Clearing the PR backlog in one session: &quot;let's go through the backlog&quot; loads the clear-backlog skill." srcset="https://substackcdn.com/image/fetch/$s_!j7QK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 424w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 848w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 1272w, https://substackcdn.com/image/fetch/$s_!j7QK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5ac881-42e2-475b-b294-3f5bc05c0a27_1946x594.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Clearing the PR backlog in one session: &#8220;let&#8217;s go through the backlog&#8221; loads the <code>clear-backlog</code> skill. <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">Source</a></figcaption></figure></div><p>Using the proxy data to fix his cold-start problem was only a temporary solution. Today, both the curation automation and the Slack assistant send traces to Opik: inputs, retrieved documents, outputs.</p><p>Here is how the Slack assistant traces look in <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik</a>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HjKA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HjKA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 424w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 848w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 1272w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HjKA!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png" width="1200" height="632.1428571428571" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:767,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Slack assistant traces in Opik.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="Slack assistant traces in Opik." title="Slack assistant traces in Opik." srcset="https://substackcdn.com/image/fetch/$s_!HjKA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 424w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 848w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 1272w, https://substackcdn.com/image/fetch/$s_!HjKA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ce287a1-8ab1-4026-8173-0de4ed4d8a47_3110x1638.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We have similar traces for the FAQ curation ingestion automation, but in a different Opik project. It works for both queries and ingestion.</p><p><strong>For your RAG app</strong>, look for any place a human already judged your output (edited PRs, support tickets, corrected answers, thumbs-down). Then trace everything from now on, so you won&#8217;t need proxies again.</p><h2>Step 2: Build the eval set</h2><p>When building your dataset, the hardest part is labeling it with pass/fail scores, plus a critique. In Alexey&#8217;s scenario, every past decision told him what the right answer was, in 2 main ways:</p><ul><li><p>A PR he accepted unchanged is a &#8220;pass&#8221; sample.</p></li><li><p>A PR where he had to alter it in any way becomes a &#8220;fail&#8221;, adding a one-sentence critique about why the review wasn&#8217;t accepted.</p></li></ul><p>A false <code>DUPLICATE</code> (or <code>WRONG_COURSE</code>) is the dangerous error. The issue closes automatically, and no PR is opened, <em>&#8220;so I would never discover it.&#8221;</em></p><p>The second biggest issue is replicating the context your RAG app used when ingesting/retrieving an item.</p><p>In our FAQ app, a question that was new when the issue arrived is now merged. Replay it as-is and the system correctly says <code>DUPLICATE</code>, so the eval case fails for the wrong reason. As I said during the interview, you have to <em>&#8220;install your data,&#8221;</em> not just your dependencies.</p><p>His answer is <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">leave-one-out</a>, shown in the image below. With 200 records within the dataset, where record D came from the issue under test, he removes D, replays the issue against the other 199, and expects <code>NEW</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9KH8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9KH8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 424w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 848w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 1272w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9KH8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png" width="1200" height="403" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:403,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Leave-one-out: remove the record the issue created, then replay the issue against the rest.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Leave-one-out: remove the record the issue created, then replay the issue against the rest." title="Leave-one-out: remove the record the issue created, then replay the issue against the rest." srcset="https://substackcdn.com/image/fetch/$s_!9KH8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 424w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 848w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 1272w, https://substackcdn.com/image/fetch/$s_!9KH8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9c03721-6e27-413b-9833-d854b27b06b7_1200x403.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Leave-one-out: remove the record the issue created, then replay the issue against the rest.</em></figcaption></figure></div><p>Each eval case is a few lines of Python code in Git: case ID, question, answer, expected action, and the ID of the doc to remove. The case ID is the GitHub issue number, so every case traces back to its issue or PR. <a href="https://github.com/DataTalksClub/faq/blob/main/faq_automation/evals/cases.py#L212">See all here</a>.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">EvalCase(
    course="llm-zoomcamp",
    case_id=274,
    question="OpenRouter: Error code 402 when calling responses.create (max_output_tokens)",
    answer="""OpenRouter can return APIStatusError with code 402 when responses.create() 
is called without a max_output_tokens limit. Pass a lower limit: max_output_tokens=1024.""",
    expected_action="NEW",
    expected_section="module-1-homework",
    description="OpenRouter 402 error &#8212; valid NEW for module-1-homework",
    checks=[action_is("NEW"), section_is("module-1-homework")],
    tags=["correct-new"],
    relevant_doc_id="cfb07a27d5",
)</code></pre></div><p>Every run costs money, so he trimmed the eval dataset to a small core set: 61 cases, with 38 <code>NEW</code>, 10 <code>DUPLICATE</code>, 7 <code>WRONG_COURSE</code>, 4 not <code>WRONG_COURSE</code>, and 2 <code>UPDATE</code>.</p><p>All the cases are imported into Opik as a versioned dataset for running the experiments:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!U3FN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!U3FN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 424w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 848w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 1272w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!U3FN!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png" width="1200" height="515.934065934066" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:626,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!U3FN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 424w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 848w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 1272w, https://substackcdn.com/image/fetch/$s_!U3FN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F600ea3a3-08eb-4af1-8778-ff66ef2bfd40_3038x1306.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>For your RAG app</strong>, an eval set is inputs plus expected outcomes, weighted towards the errors that cost you most, and replayed against the knowledge base as it was when each input arrived.</p><h2>Step 3: Build the evaluators</h2><p>I asked Alexey, <em>&#8220;How did you decide what metrics actually to measure?&#8221;</em> His answer was per case type. Cases are grouped <em>&#8220;based on the outcome I want&#8221;:</em> correctly new, true duplicate, not a duplicate, wrong course. Each type <em>&#8220;has its stack and then different logic for checking.&#8221;</em> A &#8220;correct new&#8221; case checks both that the question is flagged as <code>NEW</code> by the LLM and that it is ingested in the right section.</p><p>His curation automation returns a structured decision, so the evaluators are deterministic: <strong>action match</strong> (right decision) and <strong>placement match</strong> (right section), plus the <strong>cost</strong> of each case. When he analyzed all his traces, the most common error turned out to be incorrect section placement. Instead of placing a record about projects in the &#8220;Project&#8221; section, it would place it in &#8220;General&#8221;.</p><p>One curation trace flagged as DUPLICATE with its structured decision, model, and cost:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wc-K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wc-K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 424w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 848w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 1272w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wc-K!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png" width="1200" height="798.6263736263736" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:969,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;One curation trace: structured decision, model, and cost.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="One curation trace: structured decision, model, and cost." title="One curation trace: structured decision, model, and cost." srcset="https://substackcdn.com/image/fetch/$s_!Wc-K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 424w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 848w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 1272w, https://substackcdn.com/image/fetch/$s_!Wc-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9534722-186c-4bee-bcf4-1dc5949fb2bb_2970x1976.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>These evaluators need no LLM, are cheap to run, and are never ambiguous. Retrieval is checked separately: for a given query, it verifies that it retrieves the expected chunks. A 25-case suite scored by recall@5 runs in about 2 seconds, while the 61-case generation suite takes about 2 minutes.</p><p>The Slack assistant&#8217;s answers have no single right string. There, you need an LLM judge aligned with your own labels. Label 10 to 15 examples as good or bad yourself, write the rules down, and iterate until the judge agrees with you, <a href="https://aishippingblog.com/p/how-to-do-evals-in-2026">as Alexey lays out in his evals guide</a>.</p><p><strong>For your RAG app</strong>, use code checks wherever the right answer is known (a decision, a label, a retrieved document), check retrieval separately from generation, and save LLM judges for free-text answers.</p><p>Next, I asked him how he decides whether an eval experiment passed.</p><h2>Step 4: Run the evaluators in your eval harness</h2><p>First, let&#8217;s see how the eval harness that runs the experiments works.</p><p>Alexey keeps the eval cases in Git as the source of truth, and uses Opik as the eval harness: he uploads that dataset version and attaches it to each experiment, so every result shows what it ran on.</p><p>His runner is plain code in Git that runs all cases, or just one, and logs each run to Opik as an experiment with per-case action match, placement match, and cost. He admits it&#8217;s &#8220;not very scientific&#8221; yet and wants to track runs historically in Opik.</p><p>Here is one eval run, as an Opik experiment, where we can see the aggregated and per-item scores:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nOzk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nOzk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 424w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 848w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 1272w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nOzk!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png" width="1200" height="573.6263736263736" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:696,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;One eval run as an Opik experiment.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="One eval run as an Opik experiment." title="One eval run as an Opik experiment." srcset="https://substackcdn.com/image/fetch/$s_!nOzk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 424w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 848w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 1272w, https://substackcdn.com/image/fetch/$s_!nOzk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c7343bd-b31a-431a-87c7-a3670747d550_3114x1488.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>&#8220;I never needed 100 percent,&#8221; Alexey says, because his AI assistant still reviews every PR. The number is a benchmark that must not go down. Today the generation eval set passes <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">42 of 61 cases</a> on GPT-5.4 nano. When new cases make it dip, he changes nothing else and takes it as the new baseline. Hard cases can sit in FAIL: he doesn&#8217;t want the system prompt to grow to handle every corner case, but he does want to know those cases exist.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LzGh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LzGh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 424w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 848w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 1272w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LzGh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png" width="1456" height="619" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:619,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Alexey's two eval suites: retrieval (25 cases, recall@5) and generation (61 cases, 42 passing on GPT-5.4 nano).&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Alexey's two eval suites: retrieval (25 cases, recall@5) and generation (61 cases, 42 passing on GPT-5.4 nano)." title="Alexey's two eval suites: retrieval (25 cases, recall@5) and generation (61 cases, 42 passing on GPT-5.4 nano)." srcset="https://substackcdn.com/image/fetch/$s_!LzGh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 424w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 848w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 1272w, https://substackcdn.com/image/fetch/$s_!LzGh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6f03428-6c23-4840-8725-014ee96e10ed_1832x779.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Alexey&#8217;s 2 eval suites: retrieval (25 cases, recall@5) and generation (61 cases, 42 passing on GPT-5.4 nano). <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">Source</a></em></figcaption></figure></div><p>He pays for this community project out of his own pocket and wants <em>&#8220;the cheapest possible way that is performant enough to be useful.&#8221;</em></p><p>With evals, he compared models: GPT-4o mini is <em>&#8220;very cheap but stupid&#8221;</em> for this decision, so he chose <strong>GPT-5.4 nano</strong>, the cheapest that still delivers good quality. He keeps $5 in his OpenAI account and forgets about it &#8220;for half a year or even more,&#8221; because &#8220;each query costs on average less than one cent,&#8221; as the metrics from Opik show.</p><p>When the automation misbehaves, he first captures the failure as an eval case. He runs the new prompt on that case until it passes, then on the whole set to check nothing else broke. <em>&#8220;It&#8217;s kind of test-driven development, but like eval-driven development.&#8221;</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uSHt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uSHt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 424w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 848w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 1272w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uSHt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png" width="1203" height="1197" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1197,&quot;width&quot;:1203,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Eval-driven development: capture the failure first, fix it, then prove nothing else broke.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Eval-driven development: capture the failure first, fix it, then prove nothing else broke." title="Eval-driven development: capture the failure first, fix it, then prove nothing else broke." srcset="https://substackcdn.com/image/fetch/$s_!uSHt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 424w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 848w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 1272w, https://substackcdn.com/image/fetch/$s_!uSHt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F197a0874-89d6-423f-942f-65008b2b2ace_1203x1197.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Eval-driven development: capture the failure first, fix it, then prove nothing else broke.</em></figcaption></figure></div><p>By tracking each run as an Opik experiment, we can clearly see the difference in scores in the before, after, and verify runs tracked over time:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CTDh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CTDh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 424w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 848w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CTDh!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png" width="1200" height="493.68131868131866" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:599,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Before, after, and verify runs as Opik experiments.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="Before, after, and verify runs as Opik experiments." title="Before, after, and verify runs as Opik experiments." srcset="https://substackcdn.com/image/fetch/$s_!CTDh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 424w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 848w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!CTDh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71977474-bd58-4a71-b9ed-153d9df50694_3114x1282.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>For your RAG app</strong>, keep the cases in version control, run each experiment against a versioned dataset in your eval harness, always keep one baseline number as reference, and turn every failure into a case before you fix it.</p><h2>Step 5: Close the loop in Opik</h2><p>Mining Git history worked once, but &#8220;<em>it&#8217;s not the exercise I want to perform every time.&#8221;</em> Now, when he sees a bad Slack reply or someone corrects the bot, <a href="https://aishippingblog.com/p/rebuilding-a-faq-system-for-datatalksclub">that question becomes an eval case</a>. He uses his coding agent to pull the trace from Opik into his eval set.</p><p>Below is Alexey&#8217;s Slack assistant correction dataset:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BjrT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BjrT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 424w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 848w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 1272w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BjrT!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png" width="1200" height="571.1538461538462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:693,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Slack assistant corrections as an Opik eval dataset.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="Slack assistant corrections as an Opik eval dataset." title="Slack assistant corrections as an Opik eval dataset." srcset="https://substackcdn.com/image/fetch/$s_!BjrT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 424w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 848w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 1272w, https://substackcdn.com/image/fetch/$s_!BjrT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47caddec-4fe8-429b-8959-cd50ae74e05e_3120x1484.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em>&#8220;Because I have evals &#8230; I can see where it&#8217;s failing,&#8221;</em> and he usually fixes it by improving the FAQ, the docs, or the course repository, not with a fancier model. Then he re-runs the evals.</p><p>Alexey calls evals <strong>&#8220;basic hygiene&#8221;</strong> that you know is good for you, but you still skip it from time to time. Everyone knows you should go to bed at the same time, and sometimes you still go at 2 a.m. instead of 10 p.m.</p><p><strong>For your RAG app</strong>, route every user correction straight from your traces into the eval set instead of reconstructing it from history.</p><p>In my experience, integrating Opik takes about 5 minutes, and the free tier covers 25k spans a month, which, for this project, Alexey <em>&#8220;can use free forever&#8221;</em> (a serious production app might burn that in a day). He tried the <a href="https://github.com/comet-ml/opik">open-source version</a> first, but with his lean infra, self-hosting would have been more expensive.</p><p>Opik didn&#8217;t fit in 2 places. His evals remove records from the dataset per case, and he found no straightforward way to run that inside Opik, though <em>&#8220;maybe it&#8217;s just I should spend more time on understanding.&#8221;</em> And his zero-dependency Lambda couldn&#8217;t easily take Opik&#8217;s default Python client, so his AI assistant switched to plain <a href="https://www.comet.com/docs/opik/reference/rest-api/overview?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">HTTP requests</a>, which <em>&#8220;was so simple at the end.&#8221;</em></p><h2>Final Thoughts</h2><blockquote><p><em>&#8220;I have so many applications with zero evals and a bunch of vibe-coded test cases I don&#8217;t even know test the right thing. Is that wrong?&#8221;</em><br>&#8212; Paul</p></blockquote><p>Alexey&#8217;s answer: there&#8217;s nothing wrong with it, as long as you know how to build an eval set when you need one. First figure out how the app should work and what the UX is. If you pour time into evals and then learn the UX is wrong, you throw the evals away with it.</p><blockquote><p><em>&#8220;Many engineers who don&#8217;t know the domain look blindly at the logs and can&#8217;t decide: is this good, is this bad, what am I looking at?&#8221;</em><br>&#8212; Paul</p></blockquote><p>His advice: sit down with the domain experts. Even when he was a data scientist, long before AI automation, the most useful thing he did in every job was learn from the people his models were built for, because their input decides what &#8220;good&#8221; means.</p><p>That&#8217;s why I think humans still sit in evals. A coding agent can build the app, but it won&#8217;t tell you what it costs to run, how slow it is, or whether it&#8217;s actually good. Start with Alexey&#8217;s <em><a href="https://aishippingblog.com/p/how-to-do-evals-in-2026">How to Do Evals in 2026</a>, </em>then Eugene Yan on <a href="https://eugeneyan.com/writing/aligneval/">aligning LLM evaluators</a> and Hamel Husain on <a href="https://hamel.dev/blog/posts/evals/">why AI products need evals</a>. </p><div class="callout-block" data-callout="true"><p>And if you&#8217;re starting a RAG app today, trace it on <strong><a href="https://www.comet.com/signup?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik&#8217;s free tier</a> (25k spans/month, enough for any MVP)</strong> to make your transition from your first vibe check to evals smoother.</p></div><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>How are you evaluating your RAG workflow or agent?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/rag-evals-change-prompts/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/rag-evals-change-prompts/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/rag-evals-change-prompts?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/rag-evals-change-prompts?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><p><em>Thanks again to <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik</a> for sponsoring this case study and keeping it free!</em></p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oSDm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 424w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 848w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1272w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png" width="1456" height="364" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:364,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Opik Banner&quot;,&quot;title&quot;:&quot;Opik Banner&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Opik Banner" title="Opik Banner" srcset="https://substackcdn.com/image/fetch/$s_!oSDm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 424w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 848w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1272w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption"><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Try Opik for free here</a> (25k spans/month free)</figcaption></figure></div><p><strong>If you want to monitor, evaluate, and optimize your AI workflows and agents:</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&quot;,&quot;text&quot;:&quot;Try Opik for free&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul"><span>Try Opik for free</span></a></p><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Will Your Next Change Break Your Agent?]]></title><description><![CDATA[Error analysis and replays that reproduce agent bugs in their original context]]></description><link>https://www.decodingai.com/p/transform-agent-traces-into-regression-cases</link><guid isPermaLink="false">https://www.decodingai.com/p/transform-agent-traces-into-regression-cases</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 29 Sep 2026 05:02:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IOyu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc67f45e1-4702-4a10-903e-80e4aa1ba00e_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);"> </span></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><strong>Turn Your Agent&#8217;s Failures Into a Regression Suite</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 8: Turn Your Agent&#8217;s Failures Into a Regression Suite</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J0HL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J0HL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J0HL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The same recording, played again: listen for what changed.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The same recording, played again: listen for what changed." title="The same recording, played again: listen for what changed." srcset="https://substackcdn.com/image/fetch/$s_!J0HL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!J0HL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd25c8015-5f2b-4ee6-acef-62f1f2b3290e_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here I am, at 10 p.m., creating my implementation plan for my software factory. Tired, I vibe-planned more than usual, using Claude Code to implement Decode&#8217;s evals layer via my Modal serverless endpoint so I could access all the necessary LLMs. The endpoint returned a 503 before it finished warming up, and instead of stopping, the coding agent found a Gemini API key in memory and decided to use it to achieve its goal no matter what. The result: $40 <em>of</em> <em>tokens</em> <em>burned</em> <em>on</em> 20 <em>benchmark</em> <em>tests</em> <em>by</em> <em>the</em> <em>next</em> <em>morning</em>, <em>compared</em> <em>to </em>$4 to $5 on Modal. Ouch.</p><p>The fix was extremely simple, just 2 lines: wait for the warm-up and properly guard my credentials from the env vars. The hard part is guaranteeing that the same error never happens again after the next prompt, tool, or model change.</p><p>Without that guarantee, you&#8217;re afraid to change your prompts, because the chance of breaking what worked last week without noticing is too high. That slows development down, especially in larger teams where you have to touch other people&#8217;s code.</p><div class="callout-block" data-callout="true"><p>&#128161; The answer to all our problems is <strong>regression tests</strong> (the suite you re-run after every change to prove earlier behavior still holds), which are the most important part of AI evals for a custom AI app, more than benchmarks or online monitoring. They let you ship more features while being sure nothing else broke, just like the unit, integration, and regression tests of traditional software.</p></div><p>For an agent, the best way to organically grow your regression tests without spending too much time guessing them or money on testing useless errors is the <strong>error analysis</strong> framework.</p><p>To apply the error analysis framework to your production or synthetic traces, you need to build an eval harness that runs your agents in parallel in isolated containers, emulates the right context for each test, and collects the outputs from all your tests.</p><p>For that, there is a new family of tools in town, such as <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a> by ZenML Labs</strong>, focused on capturing your agent runs and replaying them with the same context so you can easily reproduce bugs, fix your code, and grow and manage your regression tests.</p><p>First, you&#8217;ll get a strong intuition for how the error analysis framework works, then you&#8217;ll apply it to fix and build regression tests on top of Decode, the Claude Code clone we&#8217;ve built during this series. This article will make sense even if you haven&#8217;t read previous lessons. Still, reading Lesson 7 on <a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a> would definitely help you get the foundations of evals.</p><h2>Regression tests via the error analysis framework</h2><p>Every change to a coding agent mixes plain English (prompts, tool descriptions, skills) and code: tool implementations, harness components, <strong>the sandbox</strong> layer (the container its bash and file tools run in), and compaction. So implementing unit/integration tests as we know them won&#8217;t work for three reasons: it&#8217;s impossible to write unit tests for prompts, writing integration tests for too many scenarios is too costly, and you can&#8217;t assert unstructured data via code.</p><p>What works is the error analysis framework, popularized by Hamel Husain and Andrew Ng.</p><p><strong>Here is how error analysis works, step-by-step.</strong></p><p>You record real runs, read a sample by hand, and give each a pass/fail label with a short critique, never a 1-to-5 score, because a &#8220;fail&#8221; (instead of a &#8220;pass&#8221;) is actionable, while a &#8220;3&#8221; (instead of a &#8220;2&#8221; or &#8220;4&#8221;) is not. You fix the obvious right away, cluster the rest by failure type, rank by frequency &#215; severity, and run a <strong>root cause analysis</strong> (tracing one failing run back to the step that broke it) on each high-priority cluster. Then you write one cheap evaluator per cluster and re-run it after every change.</p><p>Hamel Husain calls it <a href="https://hamel.dev/blog/posts/evals-faq/">&#8220;the most important activity in evals&#8221;</a> because it decides which evals to write at all, and Anthropic&#8217;s field guide sets the entry bar low: <a href="https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents">&#8220;20-50 simple tasks drawn from real failures is a great start&#8221;</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QBWK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QBWK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 424w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 848w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QBWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png" width="1178" height="1140" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/16769af1-b345-43ae-939e-51df00663ada_1178x1140.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1140,&quot;width&quot;:1178,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The error analysis loop in Kitaru's vocabulary &#8212; sessions in, an investigation of verdicts, cohorts per failure class, one evaluator each, and an experiment that gates every later change&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The error analysis loop in Kitaru's vocabulary &#8212; sessions in, an investigation of verdicts, cohorts per failure class, one evaluator each, and an experiment that gates every later change" title="The error analysis loop in Kitaru's vocabulary &#8212; sessions in, an investigation of verdicts, cohorts per failure class, one evaluator each, and an experiment that gates every later change" srcset="https://substackcdn.com/image/fetch/$s_!QBWK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 424w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 848w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!QBWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16769af1-b345-43ae-939e-51df00663ada_1178x1140.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The error analysis loop in Kitaru&#8217;s vocabulary: record sessions, label the sessions in an investigation, fix the obvious, cluster the rest into cohorts, write one evaluator per cohort, and replay the cohort as an experiment after every change to see if you actually fixed the bug.</em></figcaption></figure></div><p>Error analysis sounds powerful, but how do we do it in practice? How do we look at our data, cluster it and run evaluators?</p><p>That&#8217;s what we will show you in this lesson, using <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a></strong>.</p><p>When evaluating Decode, you record isolated <code>decode run</code> executions (Decode&#8217;s headless command) as <strong>sessions</strong>, with every LLM and tool call included. One Kitaru session maps to one Decode session, similar to threads or a collection of traces from other tools. Or, in plain English, your end-to-end conversation with an agent is a session. <a href="https://docs.zenml.io/kitaru/core-concepts/agents-and-sessions?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=docs">More here</a>.</p><p>Ideally, you already have Kitaru plugged in while running your AI app in production. Otherwise, you can easily import all your data from observability tools like Opik, Braintrust, or Langfuse.</p><p>Next, you sample ~20-30 sessions into an investigation, label each session as pass/fail, and add a short critique message. For errors, the message should contain the first failure reason.</p><p>After that, because Kitaru connects to your coding agent through its MCP server and skills, the agent knows how to cluster the problematic ones by error type into <strong>cohorts</strong>. For each cohort, you will implement one <strong>evaluator</strong>, a few lines of Python that read a session and say pass or fail. You fix the code, then start an <strong>experiment</strong> that replays every session of the cohort with the fix in place.</p><p><strong>The power of Kitaru is in its replay mechanism.</strong> Why? When implementing the eval harness, one of the hardest parts is recreating the same context for each task you want to evaluate. Via replays, you inject that context automatically by caching the tool outputs of the session you want to replay. This means that if a tool gets the same input, it returns the same output. Tool calls with different arguments, or tools changed during your fix, run from scratch.</p><p>Now let&#8217;s plug Kitaru into Decode&#8217;s harness to record, review and replay its agent loop.</p><h2>Integrating Kitaru into the agent harness</h2><p>Sessions can get into Kitaru in three different ways:</p><ol><li><p>Kitaru is already plugged into your harness</p></li><li><p>You import sessions from an observability tool like <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a></p></li><li><p>You run experiments via Kitaru after fixing a bug or implementing a feature</p></li></ol><p>In all three methods, everything is ingested into Kitaru&#8217;s <strong>control plane</strong>. Your coding agent talks to that control plane to do the error analysis, and experiments replay sessions on <strong>workers</strong> that you host yourself.</p><p>From an architectural perspective, 4 components talk to each other:</p><ul><li><p><strong>Decode</strong> is the agent under test, available in <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">the series repo</a>.</p></li><li><p><strong>The Kitaru control plane</strong> stores sessions and tracks the error analysis: local <a href="https://github.com/zenml-io/kitaru">open-source</a> via Docker Compose, managed, or self-hosted.</p></li><li><p><strong>The Kitaru workers</strong> run Decode in isolated containers: via Docker when running locally, as <a href="https://modal.com?source=decodingai&amp;campaign=harnesseng.">Modal</a> serverless apps when deployed, or any other method you prefer. The idea is that everything runs on your infra, and Kitaru doesn&#8217;t manage it.</p></li><li><p><strong>Your coding agent</strong> (Claude Code, Pi, Codex) does the error analysis through the Kitaru MCP server (the repo&#8217;s <code>.mcp.json</code>), guided by 3 <a href="https://github.com/zenml-io/kitaru-skills">Kitaru skills</a>: <code>kitaru-investigation</code>, <code>kitaru-validate-evaluator</code>, <code>kitaru-replay-experiment</code>.</p></li></ul><p>A worker, when executing an experiment or a replay, pulls each job on your infra and spawns one isolated Decode per session.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!15Q3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!15Q3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 424w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 848w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 1272w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!15Q3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png" width="1200" height="786" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:786,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Kitaru inside Decode's system &#8212; error analysis on the left feeds the control plane, Workers run the agent and send sessions back, your coding agent analyzes sessions through the skills and MCP server, and every cohort goes through one experiment on the right&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Kitaru inside Decode's system &#8212; error analysis on the left feeds the control plane, Workers run the agent and send sessions back, your coding agent analyzes sessions through the skills and MCP server, and every cohort goes through one experiment on the right" title="Kitaru inside Decode's system &#8212; error analysis on the left feeds the control plane, Workers run the agent and send sessions back, your coding agent analyzes sessions through the skills and MCP server, and every cohort goes through one experiment on the right" srcset="https://substackcdn.com/image/fetch/$s_!15Q3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 424w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 848w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 1272w, https://substackcdn.com/image/fetch/$s_!15Q3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F761b7a0d-93c8-4c0c-99b7-fc104a8c2dbf_1200x786.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Kitaru inside Decode&#8217;s system: error analysis feeds the control plane; workers run the agent and send sessions back; your coding agent analyzes sessions through the Kitaru skills and MCP server; and every cohort is used to grow the eval dataset and evaluators.</em></figcaption></figure></div><p>In the code snippet below, we can see how Decode plugs into our Pydantic AI agent using the <code>wrap_for_recording</code> function, which wraps the agent using <code>KitaruAgent</code> only when recording is configured, with no Kitaru import on the bare path.</p><p>It probes the workspace once, so an unreachable Kitaru server degrades to an unrecorded run with one warning line. The one exception the block leaves out is a replay spawned by a Kitaru worker, where the same failure is fatal because an unrecorded replay would waste tokens.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/runtime/recording.py">src/decode/runtime/recording.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def wrap_for_recording[DepsT, OutputT](
    agent: AbstractAgent[DepsT, OutputT], *, session_name: str | None = None
) -&gt; tuple[AbstractAgent[DepsT, OutputT], str | None]:
    if not recording_is_configured():          
    # KITARU_AGENT_ID + KITARU_API_URL, else the bare agent
        return agent, None

    export_kitaru_api_url()
    try:
        agent_id = _configured_agent_id()
        ...
        await _probe_workspace(agent_id)       
        # Ping the workspace ONCE, before the run burns tokens
        from kitaru_pydantic_ai import KitaruAgent

        wrapped = KitaruAgent(agent, agent_id=agent_id, session_name=session_name)
    except Exception as error:  
    # Broad on purpose: ANY setup failure degrades to the bare agent
        ...
        notice = (
            f"[kitaru] not recording this run: {_workspace_label()} is unavailable "
            f"({one_line(error)}); continuing on the bare agent"
        )
        logger.warning("%s", notice)
        return agent, notice

    ...
    return wrapped, None</code></pre></div><p>And this is how we call it, <em>from <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/runtime/headless.py">src/decode/runtime/headless.py</a></em>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">agent, recording_notice = await wrap_for_recording(
    _build_headless_agent(model), session_name=session_id
)</code></pre></div><p><code>session_name</code> is Decode&#8217;s own session id, so a Kitaru session and its Opik trace thread share one id, which is what makes the Opik import in the next section a one-to-one mapping.</p><p>With everything in place, let&#8217;s run the framework end to end.</p><h2>From 30 runs to a regression suite</h2><p>You need a mix of at least 20 to 30 sessions to see the agent loop in action. Either run <code>decode run "&lt;goal&gt;"</code> yourself, or let <code>make kitaru-seed</code> record 30 runs in ~10 minutes. You get 14 good sessions and 2 intentionally introduced error clusters: 8 cut off by <code>--max-requests 1</code>, and 8 crashed on a bogus model or a broken provider. The seed emulates 2 common errors we hit while developing Decode and stores all the threads in <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>.</p><blockquote><p>You can find all the commands on how to replicate our experiment in our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/running_the_code/06_evals_replays.md">GitHub runbook</a>.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2pZu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2pZu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 424w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 848w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 1272w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2pZu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png" width="1456" height="838" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:838,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!2pZu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 424w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 848w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 1272w, https://substackcdn.com/image/fetch/$s_!2pZu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c91c88b-b642-47ec-85d0-d69f793d644c_3374x1942.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You sample 20 of the newest 30 sessions into an investigation. For each one, you ask, &#8220;What do you notice? Did it match what should have happened?&#8221; and label it in the UI as <code>acceptable</code>, <code>problematic</code>, or <code>uncertain</code>, plus an optional critique.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fci4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fci4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 424w, https://substackcdn.com/image/fetch/$s_!fci4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 848w, https://substackcdn.com/image/fetch/$s_!fci4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 1272w, https://substackcdn.com/image/fetch/$s_!fci4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fci4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png" width="1456" height="829" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!fci4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 424w, https://substackcdn.com/image/fetch/$s_!fci4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 848w, https://substackcdn.com/image/fetch/$s_!fci4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 1272w, https://substackcdn.com/image/fetch/$s_!fci4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69247435-c6c9-46d1-8ec7-29af4141578e_3360x1914.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I had 6 acceptable, 14 problematic, and 0 uncertain, which the investigations tab sums up in one row:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Oo5G!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Oo5G!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 424w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 848w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Oo5G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png" width="1456" height="525" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/61579021-8294-420e-be6a-924c8e732959_3304x1192.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:525,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Oo5G!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 424w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 848w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 1272w, https://substackcdn.com/image/fetch/$s_!Oo5G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61579021-8294-420e-be6a-924c8e732959_3304x1192.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>After wrapping up the investigation, the UI hands you a prompt to paste into a coding agent with the Kitaru skills and MCP server hooked up. I used Opus 5.5:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">Investigation complete: my-discovery-1. 20 of 20 sessions reviewed, agent: decode.
Reviewed 23 September 2026.

Verdicts: 6 acceptable, 14 problematic, 0 uncertain.

Choose what to do next:
1. Build a cohort from a behavior found in these reviewed sessions.
2. Investigate the 14 problematic sessions in more detail.</code></pre></div><p>Running the prompt finds 2 cohort candidates by error type: a run that hits the request limit and ends on a raw <code>UsageLimitExceeded</code> (the error Decode raises when a run hits its request cap) with no output, and a connection error, which it suggests rejecting as agent behavior. You answer <em>&#8220;Create a cohort for each candidate!&#8221;</em> and get 2 cohorts.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MsHW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MsHW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 424w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 848w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 1272w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MsHW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png" width="1456" height="1125" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1125,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!MsHW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 424w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 848w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 1272w, https://substackcdn.com/image/fetch/$s_!MsHW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ea9c52e-2e7c-454b-89d9-ea087343b2f2_1998x1544.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You either apply an existing evaluator or create one per cohort. We have one of each: <code>decode_connection_error.py</code> for the connection-error cohort and <code>decode_request_limit.py</code> for the request-limit cohort. A new failure class needs a new evaluator, which is easy because the cohort holds every session&#8217;s logs and errors, providing enough context to your coding agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cdUg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cdUg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 424w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 848w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cdUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png" width="1456" height="718" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:718,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cdUg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 424w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 848w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!cdUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2990af-3619-4a50-bb3d-b557dc342c96_3384x1668.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>&#128161; We always prioritize code checks over LLM judges. They are cheap, fast, and need no maintenance, while a judge needs labeled examples and calibration first. A judge is always the last resort.</p></blockquote><p>Both evaluators read the session&#8217;s terminal error and flag the marker they own, and a non-terminal session with no error returns <code>passed=None</code>, never a silent fail. The evaluator <em>fails</em> when the failure class is present, so a cohort session fails until the code is properly fixed or the bug is accidentally reintroduced.</p><p>Anthropic warns that checking an exact tool-call sequence is <a href="https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents">&#8220;too rigid&#8221;</a>, so check the overall contract, such as the outcome or a hard constraint like &#8220;the run must not end on this error&#8221;.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/evaluators/decode_connection_error.py">evaluators/decode_connection_error.py</a></em>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from typing import Any

from kitaru.task.evaluator import EvaluationResult, SessionView

_RESULT_NAME = "connection_error_crash"
_MARKERS = ("Connection error", "ConnectError")


def evaluate(session: SessionView, **params: Any) -&gt; EvaluationResult | list[EvaluationResult]:
    record = session.session
    error = record.error or ""

    if not error and str(record.status or "") == "in_progress":
        return EvaluationResult(
            name=_RESULT_NAME,
            passed=None,
            value="unresolved",
            explanation="Session is non-terminal with no error; evidence missing.",
        )

    detected = any(marker in error for marker in _MARKERS)
    explanation = (
        "Terminal error is a connection failure: the provider endpoint was unreachable."
        if detected
        else "No connection failure: the session has no error or failed for another reason."
    )
    return EvaluationResult(
        name=_RESULT_NAME, score=detected, passed=not detected, explanation=explanation
    )</code></pre></div><p>The <code>decode_request_limit</code> evaluator, <em>from <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/evaluators/decode_request_limit.py">evaluators/decode_request_limit.py</a></em>, has the same Python logic, but with different markers:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">_RESULT_NAME = "request_limit_cutoff"
_MARKERS = ("UsageLimitExceeded", "exceed the request_limit")</code></pre></div><p>You prompt the coding agent to apply the 2 evaluators, one per cohort. Each session fails because it still contains the error.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k1ar!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k1ar!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 424w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 848w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k1ar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png" width="1456" height="610" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:610,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!k1ar!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 424w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 848w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!k1ar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d1e40cf-37cf-4bc7-85ae-36cf7872ac57_3354x1406.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now you run a root cause analysis on one cohort session and fix the code behind it. Ours was artificially injected by the seed, so we know the rerun will pass. In a real scenario, you fix the code first.</p><p>This cohort is the failure class of my 503 error due to the missing warm-up logic when running my models on Modal, now frozen as 4 replayable sessions. After fixing the bug, you prompt, in the same session: <em>&#8220;For cohort </em><code>decode-connection-error</code><em> we fixed the connection error. Start an experiment based on the sessions from the cohort, rerun the evaluator and see if the failure class has been resolved.&#8221;</em></p><p>Kitaru replays every cohort session on a worker in an isolated Decode instance, from the original prompt. These baselines crashed before their first tool call, so the experiment&#8217;s <strong>tool policy</strong> (next section) lets tools run for real.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fAjN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fAjN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 424w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 848w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 1272w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fAjN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png" width="1456" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!fAjN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 424w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 848w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 1272w, https://substackcdn.com/image/fetch/$s_!fAjN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9db5f5c9-2f65-49dc-904d-9c7672db0cb7_3372x1458.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Two runs: run 1 replays the cohort with the code untouched and still fails on every session, so the failure reproduces and the recording is trustworthy. Run 2, after the fix, shows the failure class resolved on every session.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!U59E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!U59E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 424w, https://substackcdn.com/image/fetch/$s_!U59E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 848w, https://substackcdn.com/image/fetch/$s_!U59E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 1272w, https://substackcdn.com/image/fetch/$s_!U59E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!U59E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png" width="1456" height="661" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:661,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!U59E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 424w, https://substackcdn.com/image/fetch/$s_!U59E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 848w, https://substackcdn.com/image/fetch/$s_!U59E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 1272w, https://substackcdn.com/image/fetch/$s_!U59E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10f96b81-b1c0-457b-b5a4-10fc7613f4eb_3376x1532.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Properly understanding replays</h2><p>A <strong>replay</strong> re-runs Decode from scratch. The only exception is that all tool calls are recorded, which means that if an agent calls a tool with the same inputs, it will use a cached output.</p><p>This means the agent loop&#8217;s decision path reflects the latest code changes. To avoid recreating the same context used by the tools, we reuse cached tool outputs instead, making it 10x easier to run experiments in the same context than to reproduce the files or database state the agent had at that moment. In Kitaru&#8217;s terms, a replay is still a <a href="https://docs.zenml.io/kitaru/guides/replay-and-overrides?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=docs">fresh execution, not a playback</a>.</p><p>Replays are an amazing way to reproduce your bugs as well. Start from your <strong>observed</strong> session, <strong>reproduce</strong> it with 0 changes to the code, then create a <strong>fork</strong>, change your model, system prompt or other parts of the code and run a replay again. Then you can do a diff between the reproduction and the fork to see the impact of your change.</p><p>Remember that every replay, as it executes your agent, burns real tokens instead of mocking the calls, so a 4-session cohort is cheap to rerun on every change and a 200-session one is not. That&#8217;s why cohorts stay small, and ideally evaluators are code, not judges.</p><p>In reality, we have more control than always using the cached outputs. For each tool (bash, file writes, web fetches), the tool policy decides whether the call is answered from the recording, a fixed table, a real execution, or a model, and what happens on a miss. Without a suitable policy, <a href="https://docs.zenml.io/kitaru/guides/tool-policies?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=docs">&#8220;a replay can call a live tool and repeat its side effects&#8221;</a>: with the default <code>passthrough</code>, a replayed <code>refund_payment</code> refunds the card again.</p><p><strong>Tool policy configs:</strong></p><ul><li><p><strong>type</strong>: <code>history</code> (answer from the recording), <code>static</code> (a fixed table), <code>passthrough</code> (run the tool for real), or <code>llm</code> (let a model invent the result).</p></li><li><p><strong>on_miss</strong>: what happens when the recording has no answer: <code>fail</code> (stop the replay), <code>error_result</code> (hand the model an error and continue), or <code>passthrough</code> (run the tool for real).</p></li><li><p><strong>scope</strong>: which recordings <code>history</code> may answer from: <code>baseline</code>, <code>cohort_version</code>, or <code>agent</code>.</p></li></ul><p>Pick <code>on_miss</code> (what a replay does when the recording has no answer for a tool call) by how complete the recording is. Complete baselines get <code>history</code> with <code>on_miss: fail</code>, so an unanswerable call stops the replay instead of inventing the rest. Cut-off or crashed baselines, like our 2 cohorts, need <code>on_miss: passthrough</code>.</p><p>The tool then runs live inside the worker&#8217;s <strong>workspace</strong> (the fresh clone a worker runs Decode in). That is safe for Decode only because its live tools are bash and file edits inside a throwaway container. For an agent whose tools touch real resources such as a payment card or a database, <code>passthrough</code> is extremely dangerous and needs to be carefully mocked.</p><p>A replay always starts from a single session and produces a new one, listed next to the original in the sessions tab with <code>Replay</code> as its origin:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4zOc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4zOc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 424w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 848w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4zOc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png" width="1456" height="655" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:655,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4zOc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 424w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 848w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!4zOc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdbbddefe-52c0-4b0c-aa4f-481570a581ec_3364x1514.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Select both, and the dashboard diffs the replay against its baseline, node by node:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2kJV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2kJV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 424w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 848w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 1272w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2kJV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png" width="1456" height="724" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:724,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!2kJV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 424w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 848w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 1272w, https://substackcdn.com/image/fetch/$s_!2kJV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe152ed5b-a777-4173-b6a9-611e9084a79e_3294x1638.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>A replay with one change is exactly how you test a change to the harness. Let&#8217;s see how that works when swapping the model.</p><h2>Swap the model, replay the same cohort</h2><p>Suppose you change the harness and want to see how that change affects performance. Here the change is the model: from <code>Qwen/Qwen3.6-35B-A3B-FP8</code> on <a href="https://modal.com?source=decodingai&amp;campaign=harnesseng.">Modal</a> to <code>gemini-3.8-flash</code>.</p><p>You create the experiment (nothing runs yet) with the following config: the <code>decode-connection-error</code> evaluator, a tool policy of <code>history</code> on the baseline with <code>on_miss: passthrough</code>, and a model override that replaces the model on every model call. The same experiment shape tests a prompt change through the <code>system_prompt</code> or <code>prompt</code> keys, or a parameter change through <code>model_params</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_iUE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_iUE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 424w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 848w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 1272w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_iUE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png" width="1456" height="597" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:597,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_iUE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 424w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 848w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 1272w, https://substackcdn.com/image/fetch/$s_!_iUE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f156cc5-54a0-4a9a-96dc-18056ef98dc3_3304x1354.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You start the run against the cohort version you replayed before (the frozen list of session ids the experiment ran against), and the worker replays each session on the new model.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YpNh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YpNh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 424w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 848w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YpNh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png" width="1456" height="666" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:666,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!YpNh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 424w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 848w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 1272w, https://substackcdn.com/image/fetch/$s_!YpNh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f251559-13a7-4300-90fc-73835ecd5715_3290x1504.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When it finishes, you read the pass/fail counts for that run. All 4 sessions passed:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oJF6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oJF6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 424w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 848w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 1272w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oJF6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png" width="1456" height="775" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:775,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!oJF6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 424w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 848w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 1272w, https://substackcdn.com/image/fetch/$s_!oJF6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15362f61-9189-471c-bec5-5a9ce71548bc_3326x1770.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And the full experiment config sits next to them, with the model overridden and every tool answered from the recording:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kHyB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kHyB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 424w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 848w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kHyB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png" width="1456" height="647" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:647,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!kHyB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 424w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 848w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!kHyB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c8034b0-c8ac-4d3b-b1e9-a7c65403e17b_2620x1164.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>&#9888;&#65039; <code>decode-connection-error</code> only flags connection errors, so a replay that crashes for any other reason still passes it. A green run shows the new model did not reintroduce connection failures, not that the migration works. Pair it with an evaluator that checks the task itself, and read pass/fail per session plus the cost delta, never one aggregate score.</p></blockquote><h2>What replays do not solve</h2><p>Replays are a good strategy for reproducing behavior and running regression tests, but not for running benchmarks that measure performance and optimize your system. In that case, run everything from scratch in isolated environments on open-ended tasks that ask whether the agent can complete its goal at all. See <a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Lesson 7</a> to learn more about implementing your custom benchmark.</p><p>Replays also do not discover unseen scenarios. A regression suite only catches previous errors detected via the error analysis framework.</p><blockquote><p>&#129489;&#8205;&#128187; Clone the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/tree/main">course repo</a>, follow the replays <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/running_the_code/06_evals_replays.md">runbook</a>, seed 30 sessions, label 20, pick a cohort and build an evaluator for it.</p></blockquote><p>With this lesson, we&#8217;ve finally wrapped up the <strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">How to Build a Coding Agent From Scratch</a></strong> course, where we&#8217;ve learned how to design, build and evaluate a Claude Code-style coding agent.</p><p><em>For previous lessons, here is the lesson-by-lesson course roadmap (<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all on GitHub</a>):</em></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><strong>Turn Your Agent&#8217;s Failures Into a Regression Suite</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li></ol><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What is your current strategy to grow your regression tests?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/transform-agent-traces-into-regression-cases/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/transform-agent-traces-into-regression-cases?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images and videos are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Agent Evals 101: Stop Guessing, Start Measuring]]></title><description><![CDATA[How to benchmark and regression-test any agent harness]]></description><link>https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests</link><guid isPermaLink="false">https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 22 Sep 2026 05:01:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iONv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);"> </span></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><strong>Agent Evals 101</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 7: Agent Evals 101</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iONv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iONv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!iONv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!iONv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!iONv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iONv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/84545663-2d8e-4362-8142-f2968a12a641_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1164312,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/216358812?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iONv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!iONv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!iONv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!iONv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84545663-2d8e-4362-8142-f2968a12a641_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>While optimizing my coding agent on my custom benchmark, I compared its performance against two models: a 35B vs. a 120B. The winner should be obvious, right? As the 120B model is 3 to 4 times larger (both are MoE). Well... the 35B model had a 95% success rate, while the 120B model had 53%. Auch.</p><p>There is more to this story, which I will explain in this article, but this is a clear signal that public benchmarks, model size, or other model features mean nothing until you test them on your custom evals built for your use case.</p><p>In this article, I want to show you exactly that. How to build a custom eval harness for your agent harness (word overloading alert!) to quantify your application&#8217;s performance, cost and latency on what you care about. Delivering shareholder value... Or if you are like me, just to create a badass AI app that you actually know works with concrete metrics, not just assumptions and vibes.</p><p>To avoid staying too abstract, I will show you how to build the evals layer for Decode, my Claude Code educational clone I built for this series. Still, this piece makes sense on its own, treating the coding agent as a black box. Plus, we will focus on techniques that can easily be extrapolated to other types of harnesses such as research agents or personal assistants. Ultimately, the core of the harness is the same regardless of the domain it attacks.</p><p>In reality, evals are more than benchmarks. That&#8217;s why it can get confusing, since it has so many facets. So let&#8217;s start by understanding the 3 big ways to think about evals and how to integrate them into your AI app. Then, we will zoom in on designing and building them.</p><h2>Three questions every production agent must answer</h2><p>We run Decode as a background agent by typing <code>decode run</code> in the terminal. The eval harness uses the same interface to run it as a subprocess, so we can leverage the sandbox (the container its bash and file tools run in) and hand-back mechanism (the agent returns its work as a git branch) already baked into the coding agent to isolate the agent while being executed within the eval harness.</p><p><em>From </em><code>evals/harness/trial.py</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">command = [
    sys.executable, "-m", "decode", "run",
    task.instruction,                    # inject trial instruction
    "--repo", str(seed_dir),             # where to get the code from
    "--local",
    "--max-requests", str(task.max_steps),
    "--summary-json", str(agent_dir / "summary.json"),
]
process = subprocess.Popen(
    command,
    cwd=home_dir,                        # working directory of the trial
    env=child_env(sandbox=sandbox),      # SANDBOX_MODE=docker|modal,
    start_new_session=True
)</code></pre></div><p>The <code>--repo</code> flag clones the <strong>seed repo</strong> (a fresh git repo at a pinned commit) so every trial starts identical, and <code>--summary-json</code> outputs the run&#8217;s report, so grading never parses traces, but loads a structured report that can be interpreted in Python or other programming language.</p><p>The eval harness never imports the agent&#8217;s loop. It launches the agent in a different process as a completely different program through the narrowest interface the product has (a command line, an HTTP call, a function). So the eval and coding harnesses are two different programs, completely decoupled.</p><div class="pullquote"><p>&#128161; The <strong>3 questions we must answer</strong> whenever we evaluate our agent!</p></div><p><strong>Benchmarks</strong> answer <em>&#8220;does it work?&#8221;</em> They run during feature development. These are the metrics you optimize every feature against. It helps you understand if a prompt tweak truly helps or not.</p><p><strong>Regression tests</strong> answer <em>&#8220;do previous features still work?&#8221;</em> after making changes to your codebase. When you change system prompts to optimize bash tool calls, they help measure how that affects the agent&#8217;s recall on other tools.</p><p><strong>Online evals</strong> answer <em>&#8220;does it work as expected?&#8221;</em> on live traffic samples from production.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XoPZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XoPZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 424w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 848w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 1272w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XoPZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png" width="1200" height="738" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:738,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Two sources of work &#8212; a feature being implemented and the traces production emits &#8212; feed three questions, and one evals harness answers all three&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Two sources of work &#8212; a feature being implemented and the traces production emits &#8212; feed three questions, and one evals harness answers all three" title="Two sources of work &#8212; a feature being implemented and the traces production emits &#8212; feed three questions, and one evals harness answers all three" srcset="https://substackcdn.com/image/fetch/$s_!XoPZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 424w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 848w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 1272w, https://substackcdn.com/image/fetch/$s_!XoPZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e4d6937-4c37-4129-a5f7-9642b907b411_1200x738.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The three questions your AI evals should answer.</em></figcaption></figure></div><p>In a coding agent, swapping Kimi K3 for GLM 5.2 can improve our benchmark scores but fail the regression that checks whether the read tool is triggered when skills point to subfiles that should be read via progressive disclosure.</p><p>Or in a research agent, a prompt tweak that makes it stop citing sources passes every benchmark it was optimized on, but fails the regression case that asserts <em>&#8220;every claim cites a document&#8221;.</em></p><blockquote><p>I have an <a href="https://www.decodingai.com/p/integrating-ai-evals-into-your-ai-app">article on integrating AI evals into an AI app</a> for the 3 stages in depth.</p></blockquote><p>Now, let&#8217;s take a look at the system design of the eval harness.</p><h2>The system design of an evaluation harness</h2><p>Any benchmark trial from Decode runs through 5 phases: seed &#8594; run &#8594; collect &#8594; verify &#8594; record. Collect reads <code>summary.json</code> as the report from the git branch the agent handed back. Record writes <code>result.json</code> to the <strong>trial dir</strong>, where we collect all the results.</p><p>Within an agent harness, &#8220;Harness&#8221; usually means everything around the model: <code>harness = agent - model</code>. An eval harness is a separate application on top of that agent. Its sole purpose is to execute and evaluate the agent harness within the right environment and context.</p><p>Our educational harness is inspired by <a href="https://www.harborframework.com/docs/core-concepts">Harbor</a>, one of the most popular eval frameworks used to compute the Terminal-Bench (general agentic computer use) and <a href="https://arxiv.org/abs/2607.07946">DeepSWE</a> (agentic coding) benchmarks.</p><p>They frame the eval harness as the referee and the agent under test as <strong>the player</strong>. Harbor&#8217;s rule: <a href="https://github.com/harbor-framework/harbor">&#8220;the agent never grades itself and never provisions itself&#8221;</a>. In Decode&#8217;s implementation, this can easily be achieved by always calling the agent as a subprocess via <code>decode run</code> as seen in the previous section.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KCkA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KCkA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 424w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 848w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 1272w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KCkA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png" width="1200" height="806" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:806,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The evaluation harness: dataset items run in parallel through sandboxed copies of the agent, each solution is graded by the Verifier into a reward of 0 or 1, and Opik keeps the traces, datasets, and experiments&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The evaluation harness: dataset items run in parallel through sandboxed copies of the agent, each solution is graded by the Verifier into a reward of 0 or 1, and Opik keeps the traces, datasets, and experiments" title="The evaluation harness: dataset items run in parallel through sandboxed copies of the agent, each solution is graded by the Verifier into a reward of 0 or 1, and Opik keeps the traces, datasets, and experiments" srcset="https://substackcdn.com/image/fetch/$s_!KCkA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 424w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 848w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 1272w, https://substackcdn.com/image/fetch/$s_!KCkA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b6517cd-cbc6-4331-9bd7-d62b47e3b336_1200x806.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The evaluation harness: Dataset items fan out to sandboxed copies of the agent in parallel; each solution is checked by the Verifier against the expected solution, grading it with a reward of 0 or 1, while Opik keeps the traces, the datasets, and the experiments.</em></figcaption></figure></div><p>We used the same vocabulary as in Harbor. A <strong>task</strong> is an instruction, an environment, and a hidden oracle. A <strong>dataset</strong> is a collection of tasks. A <strong>trial</strong> is a rollout of a Task that produces a reward. A <strong>job</strong> is many trials run in parallel.</p><p>The idea is to keep this design flexible enough to use either Harbor or a custom version. In our implementation, we used <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a> (<a href="https://github.com/comet-ml/opik">open-source</a>) as our evals platform. Beyond capturing and storing all the agent&#8217;s traces, it lets us store and version datasets, run jobs, and wrap the whole run as an experiment. Extremely useful for lineage and comparing multiple runs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Oixp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Oixp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 424w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 848w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Oixp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png" width="1190" height="1668" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1668,&quot;width&quot;:1190,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Oixp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 424w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 848w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!Oixp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fded9f672-830c-4216-a892-eb52a3e71e6a_1190x1668.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Capturing traces in Opik</figcaption></figure></div><p>Below, we see how we defined a job run via Opik where we define the <code>"decode-benchmark"</code> dataset, the task function that executes the coding agent for each item in the dataset, the metrics, and other job details. The scoring metric is the 0 or 1 reward emitted at the trial level, while the experiment scoring function is used at the experiment level to compute aggregate metrics such as <code>pass@k</code> (at least one of the k trials per task passed), <code>pass^k</code> (all <code>k</code> trials pass) and <code>flakiness</code> (<code>pass@k</code> &#8722; <code>pass^k</code>, the tasks that pass sometimes but not always, which the agent can solve but not reliably).</p><p><em>From </em><code>evals/harness/benchmark.py</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from opik.evaluation import evaluate


task_fn = make_benchmark_task_fn(
        {task.id: task for task in all_tasks},
        sandbox=sandbox,
        job_dir=job_dir,
        model=model
    )

result = evaluate(
    dataset="decode-benchmark",
    task=task_fn,                                      # one trial
    scoring_metrics=[RewardMetric()],                  # the verifier's reward function that outputs 0 or 1
    experiment_scoring_functions=EXPERIMENT_SCORING_FUNCTIONS,   # pass@k, pass^k, flakiness,
    experiment_config=experiment_config(
        sandbox=sandbox, trials=trials, model=model
    ),
    experiment_name=job_name,
    dataset_item_ids=list(item_ids.values()),          # only the matching items
    task_threads=task_threads,
    trial_count=trials,                                # --trials k &#8594; pass@k
)</code></pre></div><p>Example with k=3 and 10 tasks: 7 tasks pass all 3 trials, 2 pass 1 or 2 trials, and 1 never passes. That gives pass@3 = 90%, pass^3 = 70% and flakiness = 20%.</p><p>When k=1, all three collapse to pass@1, and flakiness is 0, as the Opik experiment below shows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iki7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iki7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 424w, https://substackcdn.com/image/fetch/$s_!iki7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 848w, https://substackcdn.com/image/fetch/$s_!iki7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!iki7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iki7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png" width="1456" height="809" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:809,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iki7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 424w, https://substackcdn.com/image/fetch/$s_!iki7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 848w, https://substackcdn.com/image/fetch/$s_!iki7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!iki7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F674debb2-c2ec-465e-a7c9-666fdf73d7f2_3240x1800.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>On top of that, it is good to track error types, so you never mistake an infrastructure issue for a reward of 0:</p><ul><li><p><strong>infra_error:</strong> the harness failed (seed, clone, a crashed verifier).</p></li><li><p><strong>agent_fail:</strong> the agent failed (wrong answer, request ceiling, timeout).</p></li></ul><p>Within Opik, we keep all our data: traces, datasets, experiments, test suites, and online rules. The actual execution of the benchmark is done on our end via our custom eval harness (or Harbor).</p><p>Other popular eval platforms include <a href="https://www.langchain.com/langsmith">LangSmith</a>, <a href="https://langfuse.com/">Langfuse</a>, <a href="https://www.braintrust.dev/">Braintrust</a>, and <a href="https://learn.microsoft.com/en-us/azure/ai-foundry/concepts/evaluation-approach-gen-ai">Azure AI Foundry</a>. If you have the right resources (and knowledge!), you can also consider building your own infrastructure. Especially now, it&#8217;s quite easy to one-shot a simple observability tool with a coding agent as long as you have a hosted database in place. But still, starting with one of these tools is the easiest path. Especially because tools like Opik are <a href="https://github.com/comet-ml/opik">open-source</a>. The only reason to go custom is if they are too rigid for your use case, a common scenario being your data format.</p><p>Now, let&#8217;s see how we designed our benchmark and regression tests.</p><h2>Designing a benchmark that predicts your agent</h2><p>The best way to understand how the benchmark works is by looking at one example: <code>007-fix-failing-test</code>: the agent gets an instruction and a seed repository, hands back a git branch, and the verifier runs the one fail-to-pass test, which returns a reward of 0 or 1.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Myqv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Myqv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 424w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 848w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 1272w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Myqv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png" width="1200" height="858" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:858,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Inside one Benchmark Task: the folder, the Trial, and the moment the hidden tests enter&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Inside one Benchmark Task: the folder, the Trial, and the moment the hidden tests enter" title="Inside one Benchmark Task: the folder, the Trial, and the moment the hidden tests enter" srcset="https://substackcdn.com/image/fetch/$s_!Myqv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 424w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 848w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 1272w, https://substackcdn.com/image/fetch/$s_!Myqv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22873061-1988-413d-81e5-34dc4560ecd1_1200x858.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The relationship between what a benchmark task looks like and how it&#8217;s executed during one trial.</em></figcaption></figure></div><p>Here is how the task is structured, where the agent gets a buggy environment it needs to fix:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">evals/benchmark/tasks/007-fix-failing-test/
&#9500;&#9472;&#9472; task.toml            # step budget, timeouts, fail_to_pass / pass_to_pass
&#9500;&#9472;&#9472; instruction.md       # the agent's prompt
&#9500;&#9472;&#9472; environment/
&#9474;   &#9500;&#9472;&#9472; ranges.py        # the buggy module
&#9474;   &#9492;&#9472;&#9472; test_ranges.py   # the test suite
&#9500;&#9472;&#9472; tests/
&#9474;   &#9500;&#9472;&#9472; test.sh          # the Verifier: writes $VERIFIER_DIR/reward.txt
&#9474;   &#9492;&#9472;&#9472; test_ranges.py   # the HIDDEN test suite
&#9492;&#9472;&#9472; solution/            # the oracle solution
    &#9500;&#9472;&#9472; solve.sh          
    &#9492;&#9472;&#9472; ranges.py</code></pre></div><p>The domain-agnostic contract: an instruction, a frozen environment, and a hidden verifier program that turns the end state into one reward. We use the same layout as <a href="https://github.com/harbor-framework/terminal-bench">Terminal-Bench</a>where the verifier runs in isolation after the agent finishes.</p><p>Each trial is its own <code>decode run</code> subprocess, with the agent&#8217;s workspace isolated in a Docker container (or a Modal sandbox) via the sandboxing logic from <a href="https://www.decodingai.com/p/run-coding-agents-safely">lesson 3</a>. When the agent finishes, its work is handed back as a git branch. The host grades a clean clone of that branch with the hidden tests copied in last (to avoid leaking the solution), then aggregates the rewards across trials.</p><p>For a research agent, we could define a task as a question, a seeded corpus, and a hidden code verifier that checks whether the agent used the right citations against a ground-truth file, instead of a costly and flaky LLM judge.</p><p><code>tests/</code> is <strong>the verifier</strong> (the hidden program that turns a trial into one reward), injected only after the run. <code>solution/</code> is <strong>the oracle</strong>, a reference that, if everything works well, outputs a reward of 1. We use it within our CI pipeline to test our eval harness, alongside running it on the unfixed environment, which should have a reward of 9.</p><p>Here is what the <code>task.toml</code> file from the <code>007-fix-failing-test</code> task looks like:</p><p><em>From </em><code>evals/benchmark/tasks/007-fix-failing-test/task.toml</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;toml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-toml">[task]
name = "007-fix-failing-test"
description = "Fix the bug in a small module so its whole unittest suite passes."

[metadata]
difficulty = "easy"          # easy 15 steps / 600 s &#183; medium 25 / 900 s &#183; hard 40 / 1500 s
category = "Software"        # Terminal-Bench's taxonomy

[agent]
timeout_sec = 600.0
max_steps = 15               # decode run --max-requests

[verifier.tests]             # SWE-bench shape: the test the fix must flip, the tests it must not break
fail_to_pass = ["test_ranges.TestRanges.test_inclusive_end"]
pass_to_pass = ["test_ranges.TestRanges.test_starts_at_one", "test_ranges.TestRanges.test_contains_two", "test_ranges.TestRanges.test_no_zero"]</code></pre></div><p>And here is the <code>test.sh</code> file that emits the reward. Custom for each task, where every exit path must still write exactly one reward.</p><p><em>From </em><code>evals/benchmark/tasks/007-fix-failing-test/tests/test.sh</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">(
  cd tests &amp;&amp; python3 -m unittest -v \
    test_ranges.TestRanges.test_inclusive_end \
    test_ranges.TestRanges.test_starts_at_one \
    test_ranges.TestRanges.test_contains_two \
    test_ranges.TestRanges.test_no_zero
)
status=$?
reward=0
[[ $status -eq 0 ]] &amp;&amp; reward=1
printf '%s\n' "$reward" &gt; "$VERIFIER_DIR/reward.txt"</code></pre></div><p>In our benchmark, we have a total of 19 tasks, while Terminal-Bench has 66 (see them <a href="https://github.com/harbor-framework/terminal-bench/tree/main/tasks">here</a>) and DeepSWE has 117 (see them <a href="https://github.com/datacurve-ai/deep-swe/tree/main/tasks">here</a>). In this case, <strong>more is NOT better!</strong> The idea is not to have hundreds of tests, since they can get expensive to run, but to have tests as diverse as possible, capturing all your scenarios and edge cases. This is known as your <em>core set</em>. So you need to think through each task carefully, designing each environment, prompt, and test file that measures the outcome.</p><p>In other words, creating a high-signal benchmark that&#8217;s actually useful is not that easy. That&#8217;s why regression tests, as we will soon see, are an easy win relative to benchmarks.</p><p>In our Decode benchmark, we have 7 easy tasks, 6 medium, and 6 hard.</p><p>We stored and versioned the whole dataset in Opik, which makes it easy to share across runs or people:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6fLe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6fLe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 424w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 848w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 1272w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6fLe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png" width="1456" height="926" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:926,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!6fLe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 424w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 848w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 1272w, https://substackcdn.com/image/fetch/$s_!6fLe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbf5bd2-38a3-4bac-89d6-242cf221f6e7_2572x1636.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Task <code>015-secret-scrub</code> asks the agent to move two hardcoded secrets into environment variables, and the first check of its verifier diffs the handed-back branch against the seed repo&#8217;s base commit. It fails the trial if any file other than <code>service.py</code> changed or if <code>service.py</code> changed by more than 8 added-plus-deleted lines, which turns <em>&#8220;keep the diff minimal&#8221;</em> from a judge&#8217;s opinion into a measured bound.</p><p><em>From </em><code>evals/benchmark/tasks/015-secret-scrub/tests/test.sh</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">MAX_CHANGED_LINES, CHANGED_FILE = 8, "service.py"
base = git("rev-list", "--max-parents=0", "HEAD").split()[0]        # the seed Repo's base commit
changed: dict[str, int] = {}
for line in git("diff", "--numstat", base).splitlines():            # added, deleted, path &#8212; per file
    added, deleted, path = line.split("\t", 2)
    if not ignored(path):                                           # tests/, .verifier/, .git/ don't count
        changed[path] = changed.get(path, 0) + int(added) + int(deleted)
extra = sorted(p for p in changed if p != CHANGED_FILE)
if extra:
    print(f"FAIL: only {CHANGED_FILE} may change, but the answer also touched {extra}"); sys.exit(1)
if changed.get(CHANGED_FILE, 0) &gt; MAX_CHANGED_LINES:
    print(f"FAIL: the change to {CHANGED_FILE} is more than the {MAX_CHANGED_LINES} lines a minimal fix needs"); sys.exit(1)</code></pre></div><p>The beautiful part of putting all this effort into a benchmark is that once it exists, it gives the coding agent so much signal that we can start optimizing our agent on automode. We just give the coding agent the goal of tweaking the harness until it passes all the trials, similar to TDD. Who knows, maybe in the future, all we will do is design benchmarks and let coding agents do the rest.</p><p>When using Opik, you can use their <a href="https://www.comet.com/docs/opik/development/optimization-runs/overview?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Agent Optimizer</a> to vary prompts, tool descriptions, and model parameters; score each trial against the dataset into an experiment; compare them; pick the best one; and repeat. Or run a similar loop by plugging Opik&#8217;s experiments into your coding agent via <a href="https://www.comet.com/docs/opik/mcp-server?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">their MCP server</a>.</p><p>Here is how you can run the benchmark job over Decode using Modal to host a Qwen3.6-35B model, where all the results will be saved as an Opik experiment:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">LLM_PROVIDER=modal make eval-benchmark ARGS='--threads 1 --job-name qwen36-modal'</code></pre></div><p>It scores 95% <code>pass@1</code> across all 19 tasks:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5HvJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5HvJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 424w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 848w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5HvJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png" width="1456" height="955" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:955,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!5HvJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 424w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 848w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 1272w, https://substackcdn.com/image/fetch/$s_!5HvJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc985b6e-da0a-4c45-a352-3ddb511e1abe_2592x1700.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And this is what it looks like when we compare two experiments to test how the harness behaves with a larger model (GPT-OSS-120B) against the default model we optimized the harness for (Qwen3.6-35B):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J4uv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J4uv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 424w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 848w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 1272w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J4uv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png" width="1456" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!J4uv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 424w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 848w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 1272w, https://substackcdn.com/image/fetch/$s_!J4uv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1acfa1e-4ef1-402a-a5bf-4b20ff2f29b9_2624x1384.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The table below, run via a Modal endpoint with 1 trial per task, shows that the larger model does not win. The 120B scored 53%, while the 35B scored 95% on the same tasks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tsJD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tsJD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 424w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 848w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 1272w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tsJD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png" width="1456" height="372" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:372,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;table&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="table" title="table" srcset="https://substackcdn.com/image/fetch/$s_!tsJD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 424w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 848w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 1272w, https://substackcdn.com/image/fetch/$s_!tsJD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb730dab8-8bcf-4709-a8b4-0890fd6991d8_1920x490.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Two different models, same nineteen tasks, as of 2026-09-17.</figcaption></figure></div><p>We know that <em>gpt-oss-120B</em> is about 1 year older than <em>qwen3.6-35B</em>, which, in AI terms, is a century. But that&#8217;s our whole point. With a benchmark, you don&#8217;t have to overthink what to choose, since you can quickly measure it on your own data.</p><blockquote><p>&#128161; <strong>The lesson?</strong> Don&#8217;t trust generic benchmarks or model features, such as parameter count, in isolation. Always test against your custom benchmark to evaluate how the model performs on your use case. </p></blockquote><p>We ran another experiment comparing billing models on the same workload using the same model (Qwen3.6-35B): pay-per-token (OpenRouter) vs. pay-per-GPU hour (<a href="https://modal.com/pricing?source=decodingai&amp;campaign=harnesseng">Modal</a>). At this scale, pay-per-token wins: 1.2 M tokens for about 18 cents, while the GPU sat mostly idle behind one trial at a time and still billed its wall-clock time. By <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">Modal&#8217;s own rule</a>, pay-per-compute wins only once you keep the GPU at 100% capacity via continuous batching.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4b-e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4b-e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 424w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 848w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 1272w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4b-e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png" width="1456" height="372" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:372,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;table&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="table" title="table" srcset="https://substackcdn.com/image/fetch/$s_!4b-e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 424w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 848w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 1272w, https://substackcdn.com/image/fetch/$s_!4b-e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89b1a24c-dc09-4f63-8477-9ca2b86dcd50_1920x490.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">One model, pay-per-GPU-hour versus pay-per-token, as of 2026-09-17.</figcaption></figure></div><p>These are two clear examples of how, once you have a benchmark in place, you can optimize not only performance but also cost and latency. Now, let&#8217;s look into how regression tests are different.</p><h2>Growing a regression suite from production</h2><p>When I was mining my Decode traces (searching live traces for failures worth pinning) I caught 6 runs asking my agent to <em>&#8220;Add my cat as the main contributor to the README and commit&#8221;</em>, where each called <code>read(path="README")</code> in a repo whose readme is <code>README.md</code>. As it became a recurring issue, I fixed it and then moved it into a regression test to ensure it won&#8217;t happen again.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h_AU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h_AU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 424w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 848w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 1272w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h_AU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png" width="1200" height="943" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cee57b81-f3be-4573-b192-723951d859ca_1200x943.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:943,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The regression loop: live traces &#8594; mined failure groups &#8594; a fix &#8594; one pass/fail case per group &#8594; a gate on every change&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The regression loop: live traces &#8594; mined failure groups &#8594; a fix &#8594; one pass/fail case per group &#8594; a gate on every change" title="The regression loop: live traces &#8594; mined failure groups &#8594; a fix &#8594; one pass/fail case per group &#8594; a gate on every change" srcset="https://substackcdn.com/image/fetch/$s_!h_AU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 424w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 848w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 1272w, https://substackcdn.com/image/fetch/$s_!h_AU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee57b81-f3be-4573-b192-723951d859ca_1200x943.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The five steps for growing your regression suite, a process known as error analysis.</em></figcaption></figure></div><p>Formalized, the loop has 5 steps:</p><ol><li><p><strong>Observe</strong>: trace every session.</p></li><li><p><strong>Diagnose</strong>: group bad runs by signature via Opik&#8217;s <a href="https://www.comet.com/docs/opik/tracing/diagnostics?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Diagnostics</a> or by building a custom clustering script</p></li><li><p><strong>Fix</strong>: using your coding agent, or <a href="https://www.comet.com/docs/opik/ollie?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Ollie</a>.</p></li><li><p><strong>Capture</strong>: one pass/fail case per failure group (use only pass/fail scores because LLMs are terrible at 1-5 likert scores, much like humans)</p></li><li><p><strong>Gate</strong>: re-run on every change.</p></li></ol><p>This process is also known as error analysis, a technique loved by the king of evals: Hamel Husain.</p><div class="pullquote"><p>&#128161; <em>Now, how are regression tests truly different from running a benchmark?</em></p></div><p>A benchmark task grades an artifact; in our use case, how well it implemented the code. A <strong>regression case</strong> grades a trajectory (how the agent behaved), which means we can no longer treat the agent as a black box, isolating it and looking only at its output, but have to look at its internals, such as whether, for read-only permissions, it used the bash/edit tool or not. If this is confusing, bear with me for a couple more paragraphs.</p><p><em>A benchmark task vs. a regression case side by side.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IhhM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IhhM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 424w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 848w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 1272w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IhhM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png" width="1200" height="573" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:573,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Benchmark Task versus Regression Case: the same seed-run-grade skeleton, a different thing measured&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Benchmark Task versus Regression Case: the same seed-run-grade skeleton, a different thing measured" title="Benchmark Task versus Regression Case: the same seed-run-grade skeleton, a different thing measured" srcset="https://substackcdn.com/image/fetch/$s_!IhhM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 424w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 848w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 1272w, https://substackcdn.com/image/fetch/$s_!IhhM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44aa7cfb-4baf-4740-ac7b-d2ad04a8fd66_1200x573.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>There are <strong>two main ways</strong> in which you can design a regression test. The <strong>first one</strong> is based solely on LLM Judges that inspect the agent&#8217;s output relative to its input, context, and a set of assertions (no ground-truth label needed). In Opik, this can be done via <a href="https://www.comet.com/docs/opik/evaluation/advanced/building-test-suites?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Test Suites</a> which automatically run a metric called G-Eval, a fancy name for the LLM judge described above. In the image below, you can see a test suite defined in Opik, with its difficulty, prompt, assertions and number of trials.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nTCf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nTCf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 424w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 848w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 1272w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nTCf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png" width="1456" height="1004" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1004,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:304647,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/216358812?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nTCf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 424w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 848w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 1272w, https://substackcdn.com/image/fetch/$s_!nTCf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fae3d9e-1ad2-46da-8619-c271d44978a3_2416x1666.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The second</strong> option uses plain datasets, similar to what we used for the benchmark above, where you have full control over the metric that validates the agent&#8217;s behavior. In this scenario, you can define metrics that check if a particular tool was called in a given scenario or if the output of the LLM is formatted as expected. But with great power comes great responsibility: you need to implement all of it yourself. <br></p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4OB1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 424w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 848w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 1272w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4OB1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png" width="1456" height="335" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:335,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4OB1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 424w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 848w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 1272w, https://substackcdn.com/image/fetch/$s_!4OB1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3a40ae9-d255-417d-b0fc-f27ff870a67c_2544x586.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>In the example below, you can see a simple test suite that includes an assertion (for the first version) and a mix of multiple metrics (for the second version). Note that <code>make_judge()</code> uses the G-Eval metric, which outputs a pass/fail value using an LLM under the hood. The second option incorporates the metrics from the first one. Keep in mind that in addition to the LLM usage required to run the agent for this task, you also need to run the LLM judge.</p><p><em>From </em><code>evals/regression/cases/read_vs_cat.py</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from evals.harness.metrics import MaxStepsMetric, ToolCalledMetric, ToolNotCalledMetric
from evals.regression.case import RegressionCase


CASE = RegressionCase(
    id="01-read-vs-cat",
    prompt="Show me the contents of notes.txt.",
    fixture=lambda ws: (ws / "notes.txt").write_text("The release train departs at 06:45.\n"),
    difficulty="easy",
    symptom="harness invariant: 'show me this file' is a read-tool call, not a `bash cat` shell-out.",
    assertion="The response shows the contents of the file the user named.",   # judged in the Test Suite
    metrics=[
        ToolCalledMetric("read"),          # code check: 1.0 iff `read` appears in the tool calls
        ToolNotCalledMetric("bash"),       # code check: 1.0 iff `bash` never does
        MaxStepsMetric(),                  # code check: steps &lt;= max_requests
        make_judge("You are grading whether the answer is grounded in the file.", "Correct when it quotes the file's line; incorrect when it guesses."),
    ],                                     # G-Eval judge: only for what code cannot score
    max_requests=6,
)</code></pre></div><p>Each deterministic check is an implementation of Opik&#8217;s <code>BaseMetric</code> class with a <code>score()</code> method returning 0 or 1. Theoretically, it supports a float, but remember, we want only binary results so it&#8217;s easier for the LLM to decide.</p><blockquote><p>&#128161;This can be an interesting use case for Jev, the new decision model from TypeSafe! It&#8217;s cheap and optimized for these types of decisions.</p></blockquote><p><em>From </em><code>evals/harness/metrics.py</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class ToolCalledMetric(BaseMetric):
    """1.0 when `tool_name` appears in the run's tool calls, else 0.0."""

    def __init__(self, tool_name: str) -&gt; None:
        super().__init__(name=f"tool_called_{tool_name}", track=False)
        self.tool_name = tool_name

    def score(self, tool_calls=None, **_) -&gt; ScoreResult:
        names = [call["name"] for call in tool_calls or []]
        called = self.tool_name in names
        return ScoreResult(
&#9;        name=self.name,
&#9;        value=1.0 if called else 0.0,
&#9;        reason=f"{self.tool_name!r} {'was' if called else 'was NOT'} called; tools used: {names}."
&#9;        )</code></pre></div><p>In the image below, you can see what an Opik experiment run from the test suite looks like, containing a bunch of tests with pass/fail results. From a final-outcome point of view, this looks very similar to running classic tests, but instead of computing them via pytest, you compute the score with LLM Judges.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EQSO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EQSO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 424w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 848w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 1272w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EQSO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png" width="1456" height="936" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:936,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!EQSO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 424w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 848w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 1272w, https://substackcdn.com/image/fetch/$s_!EQSO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a90bf6-707e-42db-8fe2-9627de6d4eee_2652x1704.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And in this image, you can see an Opik experiment run over the same dataset but using the custom metrics that look at JSON structure, tool calls, file diffs, and other checks that make sense for our coding agent:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CNDl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CNDl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 424w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 848w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 1272w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CNDl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png" width="1456" height="953" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:953,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CNDl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 424w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 848w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 1272w, https://substackcdn.com/image/fetch/$s_!CNDl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6a484df-f4a9-489e-b505-bf13f7547c2a_2590x1696.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>What&#8217;s different from classic tests is that the agent doesn&#8217;t have to pass all the tests! The idea is to add hard errors within your evals dataset: some might be fixable right away, others might not, but what matters is capturing all that signal in your dataset. So when the time comes, you know exactly what needs to be fixed. Running evals on easy tests only burns tokens.</p><p>Another difference is that as you progress with your application, you should consider deleting tests to keep the signal as high as possible. Remember that even if the check itself is made via code, running the trial costs money. So you need to keep only the tasks that are worth it. For a mature application, checking whether it can append a string to a file isn&#8217;t worth it. But checking a multi-step scenario where it needs to write, edit and execute might be.</p><p>The idea is that the regression dataset is a living object where you constantly have to add or delete items. That&#8217;s the true pain of doing evals.</p><p>In Decode, we have 7 easy tests, 7 medium, and 8 hard (22 in total), on which Qwen3.6-35B has a pass rate of 68%.</p><p>You can run them with:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">make eval-regression</code></pre></div><p>Or run a single difficulty:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">make eval-regression ARGS='--difficulty hard'</code></pre></div><h2>How can you apply this to your own agents?</h2><p>Never trust generic benchmarks. Always build your own with your tasks, your environment, and your agent, not a generic leaderboard. Nineteen tasks calibrated to my harness showed that a 120B model scores 53%, while the 35B scores 95%. A question no public benchmark could answer. Draw inspiration from the Term-Bench or DeepSWE tasks (or other benchmarks tailored to your domain), and build your own benchmark. Then either execute it via Harbor or build your own custom eval.</p><p>Do not design the regression suite up front. Grow it by capturing real production failures when error signatures repeat. Aka do error analysis on your production data. That requires the infrastructure first: tracing on every run and running diagnostics on them, via <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a> or one of the alternatives named in the article.</p><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Lesson 8</a> adds the missing piece for optimizing your agent on steroids: replays via <a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a>. You re-execute a recorded run with one change, diff it against the untouched run, and compare</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; Clone the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/tree/main">course repo</a>, follow the evals <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">runbook</a> (<code>running_the_code/05_evals.md</code>), run <code>make eval-benchmark</code> once, make a change, re-run the benchmark and compare!</p></div><p><em>Here is the course roadmap, lesson by lesson (<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a>):</em></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><strong>Agent Evals 101</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What are you currently doing AI evals for: benchmarks, regression tests or both?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images and videos are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Stop Babysitting Your Coding Agents]]></title><description><![CDATA[Run the harness remotely on Modal, triggered by your CLI, a webhook, or a nightly cron.]]></description><link>https://www.decodingai.com/p/coding-agents-in-remote-headless</link><guid isPermaLink="false">https://www.decodingai.com/p/coding-agents-in-remote-headless</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Thu, 10 Sep 2026 05:02:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!C2kP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3384caa7-94f2-4525-92da-1b089007dcb9_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);"> </span></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a> </p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><strong><span>Swarm of Remote Agents</span></strong> <strong>&#8592; </strong><em><strong>You are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 6: Swarm of Remote Agents</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PKQ2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PKQ2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PKQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9a7063de-4375-455e-9186-a287c9020433_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;You went to bed. The work did not.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="You went to bed. The work did not." title="You went to bed. The work did not." srcset="https://substackcdn.com/image/fetch/$s_!PKQ2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!PKQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a7063de-4375-455e-9186-a287c9020433_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>While building automations for Decoding AI and the personal assistant for my next Manning book, I ended up with five coding agents running in parallel. After three hours, I was completely exhausted, losing clarity and forgetting what they were doing and what their scope was. The real issue wasn&#8217;t running five agents. It was babysitting them, each needing me present in a terminal.</p><p>The goal is to have background agents running in your CI/CD pipeline or proactive agents pulling Linear tickets overnight that launch parallel attempts and pick the best PR for you to review. The goal is to switch from having your work blocked behind a TUI to proactive agents that analyze your KPIs overnight, waking up with the final report to review.</p><p>That&#8217;s <em>&#8220;the goal&#8221;,</em> the ideal I am still trying to achieve. But my best attempt to truly understand how these background agents integrate into my daily workflows without throwing money at the problem is to build a simple solution from scratch.</p><p>Thus, we will take Decode, the coding harness we built during this course, and deploy it to the cloud as a background agent through three steps:</p><ol><li><p>Switch from a TUI to a CLI headless interface</p></li><li><p>Ship it to Modal to run it as remote serverless jobs</p></li><li><p>Add support for parallel sessions to hook it to multiple projects in parallel</p></li></ol><p>By the end, you will run:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">uv run decode remote attempts "Add support to attach the agent to Slack" \
  --repo https://github.com/&lt;you&gt;/&lt;your-repo&gt;.git \
  --attempts 3 \
  --sandbox-mode modal</code></pre></div><p>That will spin off 3 independent Decode agents implementing the same feature on Modal, each shipping its own <code>decode/&lt;session-id&gt;</code> branch, which another coding agent can later compare, forwarding only the best one for your review.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Try it yourself&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Try it yourself</span></a></p><p>Before anything runs remotely, we have to drop the TUI and make the harness headless.</p><h2>Making the harness.. headless</h2><p>The <strong>headless mode</strong> runs the harness directly from the CLI and triggers the agent loop until the given goal is reached: <code>decode run "&lt;goal&gt;"</code>. It wraps the same <code>build_agent()</code> agent loop as the TUI, but under a new interface. This is easy to implement when adopting a clean architecture design that separates the app layer (the agent loop) from the serving layers (the TUI and CLI).</p><p><em>Exposing the harness as a CLI will open up tons of possibilities, as you will soon see!</em> A CLI is also scriptable, which is what lets Mario Zechner run subagents as plain <code>pi</code> calls under <code>tmux</code> in <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">his minimal coding agent</a>.</p><p>Because the agent runs in the background, everything defaults to bypass permission mode, and the <code>ask_user</code> tool becomes a no-op. On top of that, stdout prints only the final answer, while the full traces are redirected only to <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, our observability platform.</p><p>This design is extremely similar to Claude Code&#8217;s <code>claude -p "&lt;goal&gt;"</code> interface.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6idL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6idL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!6idL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!6idL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!6idL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6idL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The harness interface &#8212; a TUI, a CLI, an evals harness, and a remote launcher each drive the same loop by filling the same six fields; the loop has no opinion about any of them.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The harness interface &#8212; a TUI, a CLI, an evals harness, and a remote launcher each drive the same loop by filling the same six fields; the loop has no opinion about any of them." title="The harness interface &#8212; a TUI, a CLI, an evals harness, and a remote launcher each drive the same loop by filling the same six fields; the loop has no opinion about any of them." srcset="https://substackcdn.com/image/fetch/$s_!6idL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!6idL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!6idL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!6idL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F47b2533c-0dca-4aa9-9308-711cc7101aee_1200x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The headless harness has four modes: TUI, CLI, an evals harness, and the remote launcher.</em></figcaption></figure></div><p>The <strong>harness interface</strong> is two things: <code>build_agent()</code> (the model, the tools, the instructions) and <code>AgentDeps</code> (the tool scope, an event sink, the gate, and two resolvers for when the loop needs a human). We can add a new serving layer by implementing this interface. As shown in the image above, we will use this design to support 4 modes: the TUI, the local CLI, remote background jobs, and an eval harness (built with <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a> and <a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a>).</p><div class="callout-block" data-callout="true"><p>&#128161; <em>The remote background jobs and eval harness will be layers on top of the CLI.</em></p></div><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/agent/deps.py">src/decode/agent/deps.py</a> and <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/agent/factory.py">src/decode/agent/factory.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">@dataclass(slots=True)
class AgentDeps:
    cwd: Path                                    # the tool scope
    emit: EventSink                              # stream events (eg, TUI)
    gate: PermissionGate                         # allow / ask / deny, per tool call
    resolve_permission: PermissionResolver       # who answers an "ask"
    resolve_user_question: UserQuestionResolver  # who answers the ask_user tool
    harness_home: Path | None = None             # sessions, memory, skills

def build_agent(*, model: str | None = None) -&gt; Agent[AgentDeps, str | DeferredToolRequests]:
    agent = Agent(
        _build_model(model=model),               # gemini | openrouter | modal
        deps_type=AgentDeps,
        output_type=[str, DeferredToolRequests],
    )
    register_tools(agent)                        # read, edit, bash, agent, etc.
    _register_instructions(agent)
    return agent</code></pre></div><p>Under the CLI, when running <code>decode run</code>, we implement the <code>AgentDeps</code> interface as follows: a sink that only logs, a gate in bypass mode, resolvers that deny any human interaction, and one <code>agent.run</code> agent loop in a single Python async loop.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/runtime/headless.py">src/decode/runtime/headless.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def _build_headless_deps(cwd: Path, model: str | None = None) -&gt; AgentDeps:
    return AgentDeps(
        cwd=cwd,
        harness_home=Path.cwd(),
        emit=_headless_emit,                              
        gate=PermissionGate(mode=PermissionMode.BYPASS),
        resolve_permission=_deny_permission_resolver,      
        # never reached under BYPASS
        resolve_user_question=deny_user_question_resolver, 
        # ask_user is a no-op
    )

async def _run_task(task: str, *, model: str | None, repo: str | None, max_requests: int | None) -&gt; str:
    tool_scope = await _prepare_headless_tool_scope(repo, local)  
    # the Workspace in a sandbox mode, else cwd
    agent = build_agent(model=model)                       
    # the SAME agent the TUI builds
    deps = _build_headless_deps(tool_scope, model)
    result = await agent.run(task, deps=deps, usage_limits=UsageLimits(request_limit=max_requests))
    return result.output

def run_headless_task(task: str, ...) -&gt; str:
    try:
        return asyncio.run(_run_task(task, ...))
    finally:
        ...</code></pre></div><p>In retrospect, here is how we implemented the <code>AgentDeps</code> interface within the interactive mode plugged into the TUI: a sink that renders in the terminal, a gate loaded from your configs, resolvers that await the user, and a Runner that implements a steering queue that pours messages into the agent loop at the right time (<a href="https://www.decodingai.com/p/the-coding-agent-loop">full implementation in Lesson 2</a>).</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tui/app.py">src/decode/tui/app.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">decisions = DecisionChannel()                 # mid-turn surface for permissions + ask_user
agent = build_agent()
gate = PermissionGate(user_rules=rules.load_rule_set(permissions_file))
deps = AgentDeps(
    cwd=tool_scope,
    harness_home=harness_home,
    emit=_make_event_sink(console),           # events render live in the terminal
    gate=gate,
    resolve_permission=_make_permission_resolver(decisions, console, gate=gate, ...),
    resolve_user_question=_make_user_question_resolver(decisions, console),
)

handler = AgentTurnHandler(agent, deps=deps, session_log=session_log, ...)
runner = Runner(handler, on_event=_on_event)  # steering queue</code></pre></div><p>The two upcoming serving layers share this same clean architecture: an evals harness running <code>decode run</code> across benchmarks, and the remote background agents we build next.</p><p>In this CLI design, one key option is <code>--max-requests N</code>, which limits the maximum number of iterations in a single Pydantic AI agent loop to prevent it from running indefinitely. When running agents interactively, adding a limit is more of a curse than a blessing, but when not monitoring them at all, you want to avoid getting the agent stuck in a doom loop that just burns tokens &#8212; one of the failure modes Anthropic covers in its guide on <a href="https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents">effective harnesses for long-running agents</a>.</p><p>Next stop: taking the laptop out of the loop via remote background agents on Modal.</p><h2>Running the headless harness remotely</h2><p>The problem with running coding agents locally is that when you close your laptop lid, you are done. I&#8217;ve been trying to work around this issue with programs such as Amphetamine that hijack the sleeping processes of my Mac, but they don&#8217;t work properly. You always end up with your session stuck.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UGNq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UGNq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 424w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 848w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 1272w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UGNq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png" width="640" height="668" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/85d91781-c24c-43b3-919e-7d409eda0941_640x668.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:668,&quot;width&quot;:640,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!UGNq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 424w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 848w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 1272w, https://substackcdn.com/image/fetch/$s_!UGNq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F85d91781-c24c-43b3-919e-7d409eda0941_640x668.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Instead of maintaining a server, we create a clear boundary between who triggers the harness and where it executes. Your laptop, a cron job, or a webhook only <em>launches</em> it, and <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a> <em>executes</em> in fire-and-forget containers with zero idle cost. Modal already served our models and sandboxes. Now it also hosts the harness under serverless functions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9BWK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9BWK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 424w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 848w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1272w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png" width="1200" height="563" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:563,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The headless harness in the middle &#8212; a CLI, a cron and a webhook all start the same loop; the sandbox is optional.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The headless harness in the middle &#8212; a CLI, a cron and a webhook all start the same loop; the sandbox is optional." title="The headless harness in the middle &#8212; a CLI, a cron and a webhook all start the same loop; the sandbox is optional." srcset="https://substackcdn.com/image/fetch/$s_!9BWK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 424w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 848w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1272w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The remote system design of the headless harness that can be triggered via the local CLI, cron jobs or webhooks. All the options start the same headless harness while the agent loop runs its tool calls in an optional sandbox.</em></figcaption></figure></div><p>Which means that now we have three ways to trigger the harness:</p><ol><li><p>via <code>decode remote run</code> or <code>decode remote attempts</code> when we want to either manually trigger the harness or hook it into the CI/CD (or any other shell script)</p></li><li><p>a webhook POST that we can use from Slack, Discord or Telegram messages</p></li><li><p>a cron scheduler that we can connect to our Linear or Notion project manager to implement our tickets overnight for us to review them in the morning</p></li></ol><p>All three are implemented as different entry points into the same Modal app:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KX-K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KX-K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 424w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 848w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 1272w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KX-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png" width="1456" height="383" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:383,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!KX-K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 424w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 848w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 1272w, https://substackcdn.com/image/fetch/$s_!KX-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0ba78b8-559c-467d-95a6-5bfb527c6d14_3032x798.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The headless harness per se runs within <a href="https://modal.com/docs/guide/apps?source=decodingai&amp;campaign=harnesseng">a Modal app</a> wrapped by one Python function that Modal runs in its own container on demand, each time it&#8217;s triggered. More exactly, it runs <code>decode run</code> as a subprocess, similar to what we&#8217;ve been running locally so far, inside a gVisor container (the user-space kernel Modal runs under every container).</p><p>Because of our modular design, we can hook the headless harness to a remote Modal sandbox that runs filesystem tools such as read, edit, write and bash. Passing <code>--sandbox-mode modal</code> clones <code>--repo</code> into the sandbox workspace runs the tools there and pushes a <code>decode/&lt;session-id&gt;</code> branch to GitHub. Or, as seen in the image below, multiple branches if we choose to attempt multiple implementations of the same feature.</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!orTq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 424w, https://substackcdn.com/image/fetch/$s_!orTq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 848w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1272w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png" width="1354" height="326" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:326,&quot;width&quot;:1354,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!orTq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 424w, https://substackcdn.com/image/fetch/$s_!orTq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 848w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1272w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>We deploy the Modal app defined in the code snippet below, via <code>decode remote deploy</code>, which builds a Debian image in code with all necessary dependencies and pushes it directly to Modal&#8217;s container registry.</p><p>In the <code>execute_run()</code> function, we mostly set up the environment, clone the repository if we&#8217;re not in a sandbox, and call <code>decode run &lt;"goal "&gt;</code> as a subprocess. That&#8217;s it. Modal mostly acts as a middleman between different ways to trigger our headless harness and where to execute it.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/remote/app.py">src/decode/remote/app.py</a> and <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/remote/headless.py">src/decode/remote/headless.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">IMAGE = build_image(extra_dirs=(REPO_CLONE_DIR,), extra_packages=WEB_PACKAGES)
app = modal.App("decode-headless")

@app.function(image=IMAGE, secrets=[modal.Secret.from_name("decode-headless")], timeout=3600)
def run_task(task: str, repo: str | None = None, sandbox_mode: str = "none",
             model: str | None = None, timeout_seconds: int = 1800, max_requests: int | None = None) -&gt; dict:
    return execute_run(
&#9;    task=task, 
&#9;    repo=repo, 
&#9;    sandbox_mode=sandbox_mode, 
&#9;    model=model,
&#9;&#9;timeout_seconds=timeout_seconds,
&#9;&#9;max_requests=max_requests
&#9;&#9;)

def execute_run(*, task, repo=None, sandbox_mode="none", model=None, timeout_seconds=1800, max_requests=None) -&gt; dict:
    env = decode_run_env(os.environ, sandbox_mode=sandbox_mode)
    # inject env vars: SANDBOX_MODE, DECODE_ENV=prod, GITHUB_TOKEN, etc.
    
    if sandbox_mode == "none" and repo:
        clone_for_none_mode(repo, env)
        
    stdout, exit_code = stream_subprocess(
        decode_argv(
            task=task,
            sandbox_mode=sandbox_mode,
            repo=repo,
            model=model,
            max_requests=max_requests
        ),
        cwd=decode_cwd(sandbox_mode=sandbox_mode, repo=repo),
        env=env,
        timeout_seconds=timeout_seconds,
    ) # Run 'decode run "&lt;task&gt;" ...' within a subprocess

    return build_result(sandbox_mode=sandbox_mode, repo=repo, exit_code=exit_code, stdout=stdout, log_text=read_child_log())</code></pre></div><p>Next, we can interact with the deployed headless harness via <code>decode remote</code>, where we can start asking for specific goals via <code>decode remote run "&lt;goal&gt;"</code> or for multiple attempts via <code>decode remote attempts "&lt;goal&gt;"</code>. Which under the hood will trigger the Modal <code>run_task()</code> serverless function once or multiple times in parallel.</p><p>In the image below, we can see how each remote attempt (3 in our use case) works in its own Modal container and optional sandbox:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!65Iw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!65Iw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 424w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 848w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1272w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png" width="1456" height="625" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:625,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!65Iw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 424w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 848w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1272w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Each with its own branch and optional PR:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!orTq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 424w, https://substackcdn.com/image/fetch/$s_!orTq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 848w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1272w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png" width="1354" height="326" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:326,&quot;width&quot;:1354,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!orTq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 424w, https://substackcdn.com/image/fetch/$s_!orTq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 848w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1272w, https://substackcdn.com/image/fetch/$s_!orTq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74a94e88-c98f-4dd3-8799-226596f2e19c_1354x326.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>The deployed Modal functions form <a href="https://modal.com/docs/guide/scale?source=decodingai&amp;campaign=harnesseng">an autoscaling pool of containers</a> that sits at zero. A client <a href="https://modal.com/docs/guide/trigger-deployed-functions?source=decodingai&amp;campaign=harnesseng">looks up the Function by name</a>: <code>modal.Function.from_name("decode-headless", "run_task")</code>. It calls <code>.remote(...)</code> for a synchronous blocking call, or <code>.spawn(...)</code> for an async one.</p><p>Modal routes inputs to warm containers or boots new ones up to <code>max_containers</code>, automatically shutting down idle instances. The only latency in <code>modal</code> mode comes from <a href="https://modal.com/blog/unpacking-sandbox-startup-latency?source=decodingai&amp;campaign=harnesseng">the started-versus-ready gap</a> while the sandbox clones your repo and installs dependencies.</p><p>Using a similar strategy, we can implement the remaining two triggers. The <strong>nightly cron</strong> calls <code>run_task.local()</code> on <a href="https://modal.com/docs/guide/cron?source=decodingai&amp;campaign=harnesseng">a schedule</a> set by the <code>DECODE_NIGHTLY_CRON</code> env var.</p><p>For the <strong>webhook</strong>, we need to expose <a href="https://modal.com/docs/guide/webhooks?source=decodingai&amp;campaign=harnesseng">a FastAPI endpoint</a> with proxy auth (a key/secret header pair Modal checks at its edge before your code runs). This time, it spawns a <code>run_task</code> in the background as an async job and returns a call ID in milliseconds.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/remote/app.py">src/decode/remote/app.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">@app.function(image=IMAGE, secrets=[...], schedule=nightly_schedule(os.environ))
def nightly() -&gt; dict:
    return run_task.local(**nightly_run_kwargs(os.environ))   # same container, same subprocess

@app.function(image=IMAGE)
@modal.fastapi_endpoint(method="POST", requires_proxy_auth=True)
def webhook(request: WebhookRequest) -&gt; dict:
    call = run_task.spawn(**webhook_spawn_kwargs(request))    # start it, don't wait for it
    return webhook_response(call.object_id, request)          # the call id + where to watch</code></pre></div><p>Below, you can see how the webhook triggered the <code>run_task</code> serverless function:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FP-K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FP-K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 424w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 848w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 1272w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FP-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png" width="1456" height="598" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:598,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!FP-K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 424w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 848w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 1272w, https://substackcdn.com/image/fetch/$s_!FP-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F348bf7d9-ce20-4a91-8771-07e8db7563f2_3046x1252.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Deploy once to publish <code>run_task</code>, <code>nightly</code>, and <code>webhook</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">uv run decode remote deploy</code></pre></div><p>Fire a single synchronous run from your laptop:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">uv run decode remote run "&lt;task&gt;" --repo &lt;url&gt; --sandbox-mode modal</code></pre></div><p>Launch N parallel attempts with <code>--detach</code> to exit immediately:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">uv run decode remote attempts "&lt;task&gt;" --repo &lt;url&gt; --attempts 3 --sandbox-mode modal --detach</code></pre></div><p>Schedule a nightly cron via a UTC crontab. Without <code>DECODE_NIGHTLY_CRON</code> no schedule registers:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">DECODE_NIGHTLY_CRON="0 2 * * *" \ 
DECODE_NIGHTLY_TASK="&lt;task&gt;" \ 
DECODE_NIGHTLY_REPO=&lt;url&gt; \
DECODE_NIGHTLY_SANDBOX_MODE=modal \
DECODE_NIGHTLY_MAX_REQUESTS=120 \
uv run decode remote deploy</code></pre></div><p>Trigger the webhook over HTTP via authenticated POST:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">curl -X POST "$WEBHOOK_URL" \
-H "Modal-Key: $MODAL_PROXY_TOKEN_ID" \
-H "Modal-Secret: $MODAL_PROXY_TOKEN_SECRET" \
-H 'content-type: application/json' \
-d '{"task": "&#8230;", "repo": "&lt;url&gt;", "sandbox_mode": "modal", "max_requests": 60}'</code></pre></div><p>Read every run&#8217;s answer and summary line, from anywhere:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">uv run decode remote logs</code></pre></div><p>Looking at the logs in the terminal can be super helpful for detecting build and runtime errors and warnings. But when we have to understand what&#8217;s going on inside the agent, a better way to look at its model and tool calls is to use an observability tool like <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G71x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G71x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 424w, https://substackcdn.com/image/fetch/$s_!G71x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 848w, https://substackcdn.com/image/fetch/$s_!G71x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!G71x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G71x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png" width="1190" height="1668" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1668,&quot;width&quot;:1190,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!G71x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 424w, https://substackcdn.com/image/fetch/$s_!G71x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 848w, https://substackcdn.com/image/fetch/$s_!G71x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 1272w, https://substackcdn.com/image/fetch/$s_!G71x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdf79093-66fa-45a8-88c6-a7c8861c674d_1190x1668.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Which can quickly become super useful when running <code>decode remote attemps</code> and comparing their differences in costs (if using an API), latency and token usage:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c4Ye!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 424w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 848w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 1272w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c4Ye!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png" width="1456" height="348" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:348,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!c4Ye!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 424w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 848w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 1272w, https://substackcdn.com/image/fetch/$s_!c4Ye!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c3205e-d445-4f88-9545-3ea19fafd825_2348x562.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>Because we deployed the whole coding agent to Modal (serving the LLM, the sandbox, and the harness), a pertinent question is whether it&#8217;s worth going full serverless versus choosing good old providers such as GCP or AWS.</p><p>As always, it depends.</p><h2>When should we go serverless?</h2><p>First, <strong>serverless simplifies infrastructure</strong>: one command to deploy, automatic scale up and down, nothing billed while idle, and CPUs or GPUs one argument away.</p><p>Under <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>, you own no machines. On a hyperscaler like GCP or AWS, you maintain virtual machines plus managed services for scaling and monitoring. Bare-metal GPU clouds like RunPod and Lambda provide the cheapest hourly compute and full control, leaving every orchestrator and daemon for you to build.</p><p>In other words, if you choose an option other than serverless, you need to be prepared to invest time and resources in setting up and monitoring your infrastructure. For many small teams or early projects, that&#8217;s simply not worth it.</p><p><strong>Now what about pricing?</strong> Isn&#8217;t <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">serverless</a> a lot pricier than hyperscalers or bare metal?</p><p>Per H100-hour, on demand, at the time of writing:<br>(That can serve a 7 B to 32B model at high throughput)</p><ul><li><p><a href="https://modal.com/pricing?source=decodingai&amp;campaign=harnesseng">Modal</a> &#8776; 3.95 (<em>serverless</em>)</p></li><li><p><a href="https://www.runpod.io/pricing">RunPod</a> &#8776; $3.49 (neocloud)</p></li><li><p><a href="https://lambda.ai/service/gpu-cloud">Lambda</a> &#8776; $3.99 (neocloud)</p></li><li><p><a href="https://instances.vantage.sh/aws/ec2/p5.4xlarge">AWS p5.4xlarge</a> &#8776; $6.88 on-demand, &#8776; $2.63 spot (1&#215;H100) (hyperscaler)</p></li></ul><p>So, as you can see, only RunPod VMs are cheaper than serverless. Plus, with serverless, you pay only for what you use, as it automatically scales to 0 when idle (i.e., $0). The LLM endpoint, the remote sandboxes, the app itself. Everything. If your app mostly depends on bursty agent work, serverless fits like a glove.</p><p>On the other side of the spectrum, if you would need access only to interactive TUIs that run 24/7 by your team (hopefully!), you might want to consider other options.</p><p>As a small team, I usually start serverless and rent/buy GPUs only when I really need to invest in my own infrastructure.</p><h2>Running swarms of remote agents</h2><p>Now, how does this design map to working on multiple coding projects, each with multiple tickets?</p><p>A background job can pull tickets from Linear, implement them overnight, and leave PRs waiting for your morning review. We can model this via the cron job or a <a href="https://linear.app/developers/agents">Linear agent</a> and our webhook, which lists tickets tagged for the agent and passes along the ticket text, repo URL, and other metadata.</p><p>Modal spawns a dedicated container for each ticket. Each Decode session clones its repo into its own sandbox, implements the ticket, commits, pushes a <code>decode/&lt;session-id&gt;</code> branch, and opens a PR, so you review finished work instead of watching agents run.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o7Mz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o7Mz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o7Mz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png" width="1200" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb782f29-d603-4cd5-8772-f9438087f714_1200x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;N projects, N tickets, one agent per ticket &#8212; every agent opens its own PR against its own repo.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="N projects, N tickets, one agent per ticket &#8212; every agent opens its own PR against its own repo." title="N projects, N tickets, one agent per ticket &#8212; every agent opens its own PR against its own repo." srcset="https://substackcdn.com/image/fetch/$s_!o7Mz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!o7Mz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb782f29-d603-4cd5-8772-f9438087f714_1200x798.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Integrating the headless harness to pull and implement tickets from our Notion/Linear projects overnight.</em></figcaption></figure></div><p>Each ticket session starts from scratch and is completely independent of the others. Ten tickets run in ten containers. It is important to model dependencies between tickets to know what to implement in parallel or sequentially.</p><p><a href="https://modal.com/blog/how-ramp-built-a-full-context-background-coding-agent-on-modal?source=decodingai&amp;campaign=harnesseng">Ramp</a> uses the same strategy at production scale with a routing queue and session locks. Review-ready PRs come out, and roughly half of Ramp&#8217;s merged PRs use this strategy. Which is huge for a fintech company that needs to be really careful about what code it pushes.</p><p>On top of running multiple parallel agents, you can take this step further and run multiple parallel subagents within a single harness session.</p><h2>One orchestrator, many GPU sandboxes</h2><p>Let&#8217;s assume that we give a coding agent a task to fine-tune a Liquid LFM2.5 model.</p><p>It needs to run several fine-tuning experiments in parallel, push each to an experiment tracker, compare them, and let the next round optimize on the last until the target metric is reached. You fire one headless run on Modal, the <strong>orchestrator</strong>, with the task <em>&#8220;get eval accuracy above X on this dataset.&#8221;</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Gd6u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Gd6u!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 424w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 848w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 1272w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Gd6u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png" width="1200" height="669" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:669,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;One orchestrator on Modal, N sandboxes, one experiment tracker &#8212; a loop that repeats with the best parameters.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="One orchestrator on Modal, N sandboxes, one experiment tracker &#8212; a loop that repeats with the best parameters." title="One orchestrator on Modal, N sandboxes, one experiment tracker &#8212; a loop that repeats with the best parameters." srcset="https://substackcdn.com/image/fetch/$s_!Gd6u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 424w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 848w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 1272w, https://substackcdn.com/image/fetch/$s_!Gd6u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95222bfb-fb1e-4117-b6e1-95009979c6d4_1200x669.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Using an orchestrator agent and multiple subagents plugged into remote sandboxes to fine-tune LLMs.</em></figcaption></figure></div><p>It plans a batch of experiments (learning rates, LoRA ranks, data mixes) and fans it out into multiple subagents. Each child&#8217;s tools run in its own Modal remote sandbox created with a GPU spec (eg <code>gpu="H200:4"</code>), so <code>bash</code> trains on an H200 while the orchestrator stays on a CPU container.</p><p>The orchestrator reads each run&#8217;s metrics, keeps the best configuration, plans the next batch, and stops when it meets the target or hits other thresholds, such as cost or max iterations. You wake up to a leaderboard and a winning checkpoint, not five terminals.</p><p>More on this in <a href="https://www.decodingai.com/p/run-coding-agents-safely">Lesson 3</a> and <a href="https://www.decodingai.com/p/subagents-are-context-engineering">Lesson 5</a>.</p><h2>Next steps</h2><p>Now that we&#8217;ve seen how to run swarms of agents in the cloud, it&#8217;s time to evaluate the coding agent and build the evals harness. In <a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Lesson 7</a>, we will leverage this infrastructure to run benchmarks, regression tests, and online evals at scale.</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; <strong>Clone the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/tree/main">course repo</a></strong>, follow the <strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code">deploy runbook</a></strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code"> </a>(<code>running_the_code/04_deploy.md</code>), deploy the agent via <strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">decode remote deploy once</span></strong> and then put it to work.</p></div><p>Here is the course roadmap, lesson by lesson (see all in <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">GitHub</a>):</p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><strong>Swarm of Remote Agents</strong> <strong>&#8592; </strong><em><strong>You are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What would you give a coding agent to do overnight, without wasting your time and tokens?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/coding-agents-in-remote-headless/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/coding-agents-in-remote-headless/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/coding-agents-in-remote-headless?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/coding-agents-in-remote-headless?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images and videos are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[From 1 Bloated Context Window to 6 Scoped Subagents]]></title><description><![CDATA[The harness determines what your orchestrator agent never sees, not the model.]]></description><link>https://www.decodingai.com/p/subagents-are-context-engineering</link><guid isPermaLink="false">https://www.decodingai.com/p/subagents-are-context-engineering</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 01 Sep 2026 05:00:29 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!EEH_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);"> </span></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a> </p></li><li><p><strong>Subagents Are Context Engineering</strong> <strong>&#8592; </strong><em><strong>You are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 5: Subagents Are Context Engineering</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EEH_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EEH_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EEH_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;One ship, six scouts, every line runs home.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="One ship, six scouts, every line runs home." title="One ship, six scouts, every line runs home." srcset="https://substackcdn.com/image/fetch/$s_!EEH_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!EEH_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c70a646-9a17-4434-83e2-9aee44333ec3_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When I first built the deep-research setup for my Second Brain, I was passing up to 200 notes, transcripts, and PDFs to a single Claude Code session. It read them into its window 1 by 1, taking minutes and draining my weekly subscription.</p><p>So I split that into 6 researcher subagents per query, running in parallel, each dropping its internal state and returning only the final results to the orchestrator agent to avoid exploding the context window with noise. Each researcher subagent rephrased previous searches to ensure it explored new perspectives.</p><p><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Subagents are context engineering!</span></strong> For everyone serious about becoming a power user (or builder!) of coding agents or harnesses in general &#8212; Claude Code, Codex, Cursor, or a custom-built one &#8212; learning how to operate subagents is an essential skill. Plus, you get the intuition to understand when subagents are actually worth it, without adding useless complexity!</p><p>In Lesson 4, we explored Decode&#8217;s essentials (memory, skills, LSP servers, and compaction). Now it&#8217;s time to go into <strong>subagents</strong>, <strong>the Agents Catalog</strong> of personas, and <strong>parallel fan-out</strong>.</p><p>You will walk away understanding and building from scratch:</p><ul><li><p>Designing the protocol between the subagent and the parent agent.</p></li><li><p>Configuring a registry of agents.</p></li><li><p>Spinning out a swarm of agents without hitting your LLM provider&#8217;s rate limits.</p></li></ul><h2>Subagents baked into the harness</h2><p>A <strong>subagent</strong> is a child agent spawned by the primary agent for 1 scoped task, exploring in its own context and returning 1 compressed report. As Anthropic notes in their <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">guide on effective context engineering</a>, a subagent can burn tens of thousands of tokens reading code and hand back only a distilled 1,000- to 2,000-token summary, keeping search noise out of the parent agent&#8217;s context window (the shape Claude Code uses, judging by its leaked implementation).</p><p>There are <strong>2 ways to spawn a subagent</strong>: calling an in-harness tool, or spawning the CLI via <code>bash</code> and <code>tmux</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FLqL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FLqL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 424w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 848w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 1272w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FLqL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png" width="1200" height="558" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aef57500-c424-4efc-8062-e86deb05606d_1200x558.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:558,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Where the child runs decides everything else &#8212; in-harness, the orchestrator and its Explore children live in one harness; with tmux, every child is a second harness of its own. Either way, each agent carries its own config.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Where the child runs decides everything else &#8212; in-harness, the orchestrator and its Explore children live in one harness; with tmux, every child is a second harness of its own. Either way, each agent carries its own config." title="Where the child runs decides everything else &#8212; in-harness, the orchestrator and its Explore children live in one harness; with tmux, every child is a second harness of its own. Either way, each agent carries its own config." srcset="https://substackcdn.com/image/fetch/$s_!FLqL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 424w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 848w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 1272w, https://substackcdn.com/image/fetch/$s_!FLqL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faef57500-c424-4efc-8062-e86deb05606d_1200x558.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Where the subagent runs: in-harness vs spinning up a different process using the harness&#8217;s CLI and tmux.</em></figcaption></figure></div><p>Decode uses a read-only tool: <code>agent(prompts: list[str]) -&gt; str</code>. It runs deterministic guards before spawning children, returning a <code>ModelRetry</code> (the tool&#8217;s way of sending the model a correction instead of a result) if the prompts are empty or if the number of concurrent requests exceeds 6.</p><p>The prompt steers the subagent toward a specific goal. That prompt is the only dynamic part. Everything else the child gets &#8212; its system prompt and its permissions &#8212; is static configuration that decides what it is allowed to do (exploration, code review, software engineering, etc.). More on this soon.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/agent.py">src/decode/tools/agent.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def agent(ctx: RunContext[AgentDeps], prompts: list[str]) -&gt; str:
    if not prompts:
        raise ModelRetry("The agent tool needs at least one exploration prompt. ...")
    if len(prompts) &gt; MAX_FANOUT_PROMPTS:
        raise ModelRetry(f"You asked for {len(prompts)} subagents; the limit is {MAX_FANOUT_PROMPTS} per call. ...")
    _check_substance(prompts)

    child_max_bytes = 16_000 // len(prompts)
    sections = await asyncio.gather(
        *(
            _spawn_child(ctx, prompt, index=index, max_bytes=child_max_bytes)
            for index, prompt in enumerate(prompts, start=1)
        )
    )

    fold = "\n\n".join(
        f'## Subagent {index} &#8212; "{_label(prompt)}"\n\n{section}'
        for index, (prompt, section) in enumerate(zip(prompts, sections, strict=True), start=1)
    )

    return fold + SYNTHESIS_FOOTER</code></pre></div><p>When you run the <code>/demo-4-review-swarm</code> skill, 3 read-only <strong>Explore</strong> subagents review different sections of the active codebase and aggregate everything into a final report:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VQb0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 424w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 848w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 1272w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VQb0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png" width="728" height="164.07877461706784" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:206,&quot;width&quot;:914,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:71537,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!VQb0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 424w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 848w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 1272w, https://substackcdn.com/image/fetch/$s_!VQb0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94d40e7c-3d5b-4321-858d-4a2af49406c6_914x206.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>In <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, our observability tool, the whole call shows up as 1 <code>agent</code> tool span with 3 input prompts:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iV6B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iV6B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 424w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 848w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 1272w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iV6B!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:826,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iV6B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 424w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 848w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 1272w, https://substackcdn.com/image/fetch/$s_!iV6B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa28ab92-e46f-4b9c-baa6-19ce8c0f4060_2838x1610.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The subagent report</strong> contract requires the subagent to make at least one tool call or return a non-empty result. If that&#8217;s not respected, the harness retries it. On the second failure, it returns a warning message.</p><p>All the surviving reports are truncated to <code>subagent_result_max_bytes // N</code> (16,000 bytes shared).</p><p>The harness appends the <code>SYNTHESIS_FOOTER</code> after the last section, instructing the parent to compile the N reports into 1 answer using prose plus an ASCII diagram (Mermaid only for genuine graphs, since the TUI renders Mermaid as raw source).</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/agent.py">src/decode/tools/agent.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def _spawn_child(
    ctx: RunContext[AgentDeps], prompt: str, *, index: int, max_bytes: int
) -&gt; str:
    from decode.tools.truncate import truncate

    report = await _run_attempt(ctx, prompt, index=index)
    if report is None:
        logger.warning("subagent %d returned an unusable report; retrying once", index)
        report = await _run_attempt(ctx, prompt + _RETRY_NUDGE, index=index)

    if report is None:
        logger.warning("subagent %d returned an unusable report twice; giving up", index)
        return _NO_USABLE_REPORT_NOTE

    return truncate(report, max_lines=2000, max_bytes=max_bytes).text</code></pre></div><p>A child is the same Pydantic AI <code>Agent</code> re-entered with fresh, narrowed agent dependencies <code>AgentDeps</code>. It cannot recurse without the <code>agent</code> tool, cannot stop to ask you a question without <code>ask_user</code>, and runs in bypass permission mode because it is read-only. Its messages are ephemeral, as the parent&#8217;s history keeps only the spawn call and the report.</p><p>What is not built is an in-flight queue that lets the parent agent talk to the subagent mid-run, similar to how we design the dynamics between the TUI and the main runtime. To implement it, we can repeat the same architecture as in <a href="https://www.decodingai.com/p/the-coding-agent-loop">Lesson 2</a>.</p><p>Alternatively, there is the approach from Mario Zechner&#8217;s <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">post on building Pi</a>, which treats subagents as black boxes and runs them by calling <code>pi</code> from <code>bash</code> under <code>tmux</code>. The orchestrator is simply the session that manages the <code>tmux</code> windows. State is passed between the agents via Markdown files. When you opt for this option, you usually need to manage the tmux-related business logic in a <code>/subagent-tmux</code> skill.</p><blockquote><p>&#128161;<a href="https://github.com/tmux/tmux">tmux</a> is a terminal multiplexer. It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal.</p></blockquote><p>Decode supports this too: the headless entrypoint <code>decode run "&lt;task&gt;"</code> is a self-spawn primitive that we illustrate in the demo skill <code>/demo-5-sandbox-feature-pr</code>, which launches a second Decode inside a sandboxed clone of its own repo &#8212; a whole harness as the child, not a nested run:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">decode run "Where is the agent tool function? Report the path with file:line."</code></pre></div><p>The 2 options are not competing versions of the same thing. The in-harness tool is a <strong>context</strong> primitive, while tmux is a <strong>process</strong> primitive.</p><p><strong>Keeping subagents in the harness gives you:</strong></p><ul><li><p><strong>The cheapest subagent.</strong> A loop re-entry, not a process: no cold start, no serialization. Claude Code goes further: because the parent and child run the same loop, the summary fork reuses the parent&#8217;s prompt cache.</p></li><li><p><strong>A context window that stays clean by construction.</strong> The child burns its tens of thousands of tokens somewhere you never see, and search noise never enters the parent&#8217;s window.</p></li><li><p><strong>The budget in 1 place.</strong> The width cap, the semaphore, the per-child request limit, the retries, and the child&#8217;s narrowed permissions are all yours to enforce in the tool &#8212; not scattered across orchestration scripts.</p></li></ul><p><strong>Spawning the CLI under </strong><code>tmux</code><strong> gives you:</strong></p><ul><li><p><strong>A real boundary.</strong> An OS process, not an allowlist. The child cannot access the parent&#8217;s memory, and it composes with <code>bwrap</code>, <code>sandbox-exec</code>, or a container without extra work.</p></li><li><p><strong>Full observability, live.</strong> You can watch the raw output in a terminal, attach, and co-drive the child mid-run instead of trusting a summary of a summary. Mario Zechner&#8217;s objection to the built-in tool is exactly this: it is <em>&#8220;a black box within a black box&#8221;</em>.</p></li><li><p><strong>Children that outlive the parent.</strong> Each is a real session on disk, resumable and inspectable, with its state stored in plain Markdown files.</p></li></ul><p>Decode uses the <code>agent</code> tool by default because read-only exploration does not need separate process overhead, and runs as a CLI program (with or without tmux) when the parent needs a remote sandbox or you need to watch the child work.</p><p>Every child above ran as an exploration agent, which is configurable via the agent catalog alongside our other <strong>personas</strong>.</p><h2>The agents catalog</h2><p>Depending on which agent you run, you need a mechanism to configure it.</p><p>Decode scopes a few of its core agents in <strong>the Agents Catalog</strong>. Each persona is a bundled Markdown file with YAML front matter (name, description, a tools allowlist, a default mode, optional allow/deny rules, and a subagent flag) plus the agent-specific system prompt in the file&#8217;s body. This list can be extended with your own agents, similar to Claude Code.</p><p>You can spin up the harness with different agents steering the agent loop by running:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">decode --agent build # or plan, code-reviewer</code></pre></div><p>Or switch directly from the TUI:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9Do7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 424w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 848w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 1272w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9Do7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png" width="829" height="124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:124,&quot;width&quot;:829,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!9Do7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 424w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 848w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 1272w, https://substackcdn.com/image/fetch/$s_!9Do7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18fd2419-711c-4d4c-b2cd-7c9b9f4ce3d2_829x124.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>This resets the agent&#8217;s system prompt and the set of allowed tools. A more nuanced change, strictly correlated with its tool set, is its permission mode (default, edit, plan, bypass). The toolset configures which tools the agent sees in the system prompt, while its permission mode controls which tools are allowed to run without a human accepting them. If a tool is not present in the system prompt, the permission mode has no effect, as that tool will never be called.</p><p>The <code>build</code> persona is our default primary agent: all 15 tools, <code>mode: default</code>, and a generic coding assistant prompt.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/agents/builtin/build.md">src/decode/agents/builtin/build.md</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">---
name: build
description: A capable coding agent that reads, edits, runs commands, and ships changes.
tools:
  - read
  - glob
  - grep
  - lsp
  - write
  - edit
  - bash
  - todo_write
  - web_fetch
  - ask_user
  - enter_plan_mode
  - exit_plan_mode
  - sleep
  - skill
  - agent
mode: default
---
You are the build agent &#8212; a capable, hands-on coding assistant working inside the user's project.

You have the full tool set: read and search the codebase, write and edit files, run shell commands,
fetch web pages, and track multi-step work with a todo checklist. Use them to actually make the change the user asked for, not just to describe it.

Work like a careful engineer:

- Understand before you act. Read the relevant files and search the codebase before editing, so your
  change fits the existing patterns and conventions.
- Delegate broad exploration. For a broad, multi-area question about the codebase ("explore this repo", "how does X work end to end"), make ONE `agent` call carrying at least 3 distinct angles

... # Rest of the prompt

If the task is large or risky enough to warrant a plan first, call `enter_plan_mode`, research and present the plan, and call `exit_plan_mode` to get the user's approval before implementing.

Be concise. Explain what you changed and why, not every step you took.</code></pre></div><p>The <code>plan</code> agent drops <code>write</code>, <code>edit</code>, and <code>bash</code>, starting in <code>mode: plan</code>, so any writes are denied. <code>code-reviewer</code> drops <code>write</code> and <code>edit</code> but keeps <code>bash</code> with <code>allow: ["bash(git *)"]</code>, auto-allowing <code>git diff</code>, <code>git log</code>, and <code>git show</code> while prompting on other shell commands. Both delegate exploration to subagents.</p><p><code>explore</code> is the only configuration we will use for the subagent, via <code>subagent: true</code>. Thus, the only way it runs is as a child of the <code>agent</code> tool. Its allowlist is exactly <code>read</code>, <code>glob</code>, <code>grep</code>, and <code>lsp</code> &#8212; no <code>bash</code>, <code>web_fetch</code>, or <code>ask_user</code> (which would deadlock the fan-out), and no <code>agent</code> (to avoid recursion):</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/agents/builtin/explore.md">src/decode/agents/builtin/explore.md</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;markdown&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-markdown">---
name: explore
description: Reads the codebase and answers questions about it without changing anything.
tools:
  - read
  - glob
  - grep
  - lsp
subagent: true
mode: default
---
You are the explore agent &#8212; a read-only subagent spawned to investigate one scoped question about
the codebase and report back. You never change anything.

You have only read-only tools: read files, search with `glob` and `grep`, and look up symbols with
`lsp`. You cannot write files, run shell commands, fetch the web, or ask a question back &#8212; your whole
job is to read the code and explain what it actually does.

Your final message IS your report. Nothing else you do reaches the caller, so that last message must be the whole deliverable, in three parts:

... # Rest of the prompt</code></pre></div><p>Now, instead of running the exploration agents 1 by 1, let&#8217;s see how we can run 6 of them in parallel via the fan-out algorithm without hitting your provider&#8217;s rate limits or flooding the context window.</p><h2>Parallel fan-out</h2><p>When building the memory-extraction pipeline for my digital twin&#8217;s GraphRAG system, I found the 100-document batch processor written as a serial loop: <code>for doc in docs: await extract_document_task(...)</code>. That ran 1 document at a time, dragging out the run for hours. Wrapping those 100 extractions under <code>asyncio.gather()</code> and a <code>Semaphore(5)</code> meant 5 ran at a time. Whenever a job splits into independent pieces, serial execution wastes wall-clock time.</p><p><strong>Fan-out</strong> is 1 <code>agent(prompts=[...])</code> call that spawns N Explore children concurrently and folds everything back into a single aggregate &#8212; parallelism the harness guarantees, not a courtesy the model may or may not extend by emitting N tool calls.</p><p>This strategy works incredibly well with similar independent tasks, where each agent minds its own business, such as reading documents from a dataset, conducting in-depth research, or exploring different segments of a codebase (as we do).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dmBx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dmBx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 424w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 848w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 1272w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dmBx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png" width="1200" height="638" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:638,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The fan-out path &#8212; the orchestrator spawns N children, four run while the rest wait, each returns one compressed report, and the reports fold into a single aggregate that comes back as one tool result.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The fan-out path &#8212; the orchestrator spawns N children, four run while the rest wait, each returns one compressed report, and the reports fold into a single aggregate that comes back as one tool result." title="The fan-out path &#8212; the orchestrator spawns N children, four run while the rest wait, each returns one compressed report, and the reports fold into a single aggregate that comes back as one tool result." srcset="https://substackcdn.com/image/fetch/$s_!dmBx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 424w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 848w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 1272w, https://substackcdn.com/image/fetch/$s_!dmBx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02529a97-390b-4fca-8ac4-a5c5632cd359_1200x638.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The fan-out algorithm: The orchestrator spawns N children, four run while the rest wait, each returns one compressed report, and the reports fold into a single aggregate that comes back as one tool result.</em></figcaption></figure></div><p>We have to chain 3 functions: <code>agent</code> gathers the <code>_spawn_child</code> calls, <code>_spawn_child</code> handles the retries, and <code>_run_attempt</code> runs the child itself.</p><p>Inside the tool, <code>asyncio.gather</code> (run these coroutines concurrently and return their results in order) runs <code>_spawn_child</code> for each prompt under an <code>asyncio.Semaphore</code> (a counter that lets at most N coroutines through at once) set to <code>subagent_max_parallel</code> = 4. We need the semaphore so a single fan-out does not hit the provider&#8217;s rate limits with too many requests at once.</p><p>When you own your infra, such as hosting your open-weight models like Qwen on <a href="https://modal.com/blog/introducing-auto-endpoints?source=decodingai&amp;campaign=harnesseng">Modal Auto Endpoints</a>, the bottleneck is your infra, but when using an LLM API such as OpenRouter, OpenAI, or Gemini, you have strict limits on how many requests you can make per minute. Usually you need to contact them to negotiate higher request limits. Owning the endpoint skips that negotiation entirely, and bursty fan-outs are the exact workload <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">serverless GPU pricing</a> was designed for.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/agent.py">src/decode/tools/agent.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def agent(ctx: RunContext[AgentDeps], prompts: list[str]) -&gt; str:
    ...
    sections = await asyncio.gather(
        *(
            _spawn_child(ctx, prompt, index=index, max_bytes=child_max_bytes)
            for index, prompt in enumerate(prompts, start=1)
        )
    )
    ...


async def _spawn_child(
    ctx: RunContext[AgentDeps], prompt: str, *, index: int, max_bytes: int
) -&gt; str:
    ...
    try:
        report = await _run_attempt(ctx, prompt, index=index)
        if report is None:
            ...
            report = await _run_attempt(ctx, prompt + _RETRY_NUDGE, index=index)
    ...</code></pre></div><p>Inside <code>_run_attempt</code>, the child receives its narrowed <code>AgentDeps</code>, acquires the semaphore, and re-enters the primary <code>Agent</code>.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/agent.py">src/decode/tools/agent.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def _run_attempt(ctx: RunContext[AgentDeps], prompt: str, *, index: int) -&gt; str | None:
    explore = load_agent(_SUBAGENT_PERSONA)

    child_emit = _make_child_emit(ctx.deps, index)
    child_deps = AgentDeps(
        cwd=ctx.deps.cwd,
        harness_home=ctx.deps.harness_home,
        emit=child_emit,
        gate=PermissionGate(mode=PermissionMode.BYPASS),
        resolve_permission=_deny_permission_resolver,
        resolve_user_question=deny_user_question_resolver,
        active_agent=explore,
        context_window_tokens=ctx.deps.context_window_tokens,
    )

    async with _semaphore():  # bound the fan-out to the concurrency ceiling
        result = await _require_main_agent().run(
            prompt,
            deps=child_deps,
            usage_limits=UsageLimits(request_limit=25),
        )

    return _usable_report(result)</code></pre></div><p>Let&#8217;s see in <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, based on our demo, where we explicitly chose to spawn 3 subagents, how each child nests inside the parent turn, showing its own spans with token counts and latency.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!L6BO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!L6BO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 424w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 848w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 1272w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!L6BO!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:640,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!L6BO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 424w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 848w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 1272w, https://substackcdn.com/image/fetch/$s_!L6BO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd194e30b-467e-4df3-9867-f72358b46dd2_2908x1278.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Our implementation via the <code>agent</code> tool currently works only by spinning up exploration agents on the same harness as the parent. But you can easily take this further by attaching different types of agents from the catalog, or by attaching them to remote sandboxes with a preconfigured setup or a GPU-enabled machine for inference/fine-tuning jobs, as we explained in <a href="https://www.decodingai.com/p/run-coding-agents-safely">Lesson 3</a> on sandboxing via Modal. In this <a href="https://modal.com/blog/how-ramp-built-a-full-context-background-coding-agent-on-modal?source=decodingai&amp;campaign=harnesseng">background agent&#8217;s case study</a>, Ramp uses this model to spawn child sessions via Modal remote sandboxes across all their repositories.</p><p>To implement a similar strategy with <code>tmux</code>, you would spin up N windows, each running a <code>decode run</code>, while the logic for gathering, budgeting, and retries that sits between the parent and subagents is yours to write.</p><h2>Next steps</h2><p>In my day-to-day workflow with Claude Code, I use the <code>.claude/agents/*.md</code> protocol via <a href="https://code.claude.com/docs/en/sub-agents">its agent tool</a> for small setups. My <a href="https://github.com/iusztinpaul/squid">Squid software factory</a> runs 1 software engineer agent and 1 tester agent at a time.</p><p>For real fan-outs with more than 10 agents on 1 task, I use Claude Code&#8217;s dynamic workflows feature, which spins up <code>.claude/agents/*.md</code> in parallel and manages all the glue logic. For repeatable use cases where I want to avoid keeping my business logic locked into Anthropic&#8217;s ecosystem, I move the code into dedicated Python CLI programs that I fully control, while using skills only as a thin wrapper on top to plug them into the harness.</p><p>I rarely reach for <code>tmux</code>, but since I want to own more of my harness, it&#8217;s a pattern I want to get better at.</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; <span>We encourage you to&nbsp;</span><strong>clone our&nbsp;<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">course repo</a></strong><span>, open your terminal, type </span><strong><span data-color="#38761d" style="color: rgb(56, 118, 29);">&#8221;decode&#8221;</span></strong>,<strong> </strong>and test out the coding agent.</p></div><p>In the <a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">next lesson</a>, we&#8217;ll strip the TUI and deploy it to Modal, triggering it via the CLI, cron jobs, and webhooks.</p><p><span>Here is the</span><strong> course roadmap, </strong><span>lesson by lesson </span><em><span>(</span><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a></em><span>):</span></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a> </p></li><li><p><strong>Subagents Are Context Engineering</strong> <strong>&#8592; </strong><em><strong>You are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>When you need ten agents on the same job, do you use your harness&#8217;s subagent tool, or tmux?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/subagents-are-context-engineering/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/subagents-are-context-engineering/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/subagents-are-context-engineering?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/subagents-are-context-engineering?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images and videos are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Context Engineering for Coding Agents]]></title><description><![CDATA[The 4 harness components that keep your context window high-signal.]]></description><link>https://www.decodingai.com/p/context-engineering-for-coding-agents</link><guid isPermaLink="false">https://www.decodingai.com/p/context-engineering-for-coding-agents</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 25 Aug 2026 05:01:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BvUU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39d1f394-e419-4ab6-a9f1-da5a0425a6f6_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);"> </span></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><strong>Context Engineering for Coding Agents</strong> <strong>&#8592; </strong><em><strong>You are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 4: Context Engineering for Coding Agents</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7tX-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7tX-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7tX-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What you carry is what you can move with. The craft is in what you leave on the bench.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What you carry is what you can move with. The craft is in what you leave on the bench." title="What you carry is what you can move with. The craft is in what you leave on the bench." srcset="https://substackcdn.com/image/fetch/$s_!7tX-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!7tX-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F544e7250-15d4-4cc8-bc3d-b30f3e8e16db_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I got hooked on running Claude Code agents 24/7. Getting things done while answering emails, cooking, or watching a movie. Until my subscription maxed out mid-turn with the agent halfway through a feature. Sounds familiar?</p><p>Complaining to your employer, buying a bigger subscription, changing the model, or switching harnesses only treats the symptom. Doesn&#8217;t solve the root cause. You spend money while the window stays noisy, degrading output no matter whose model is behind it.</p><p>The actual solution is to better understand harnesses and the context engineering behind them. Improve planning, develop stronger skills and memory, and know when to drop your context.</p><p>So far in the course, we have focused on harness engineering and building a sandboxed agent loop. Now it&#8217;s finally time for some context engineering for coding agents: memory, skills, LSP servers and compaction.</p><p>The whole problem resolves to what to put into context, what not to put, how to trim it down, plus creating as many feedback loops as possible for the agent, as Anthropic frames it as <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">finding the smallest possible set of high-signal tokens</a>.</p><p>You will walk away understanding and building from scratch:</p><ul><li><p>What the agent should carry between sessions.</p></li><li><p>How skills load nothing until needed.</p></li><li><p>The cheapest feedback loop in the system.</p></li><li><p>How the window gets trimmed before it rots.</p></li></ul><h2>The context lifecycle of a session</h2><p>To see how the 4 components cooperate, look at the <code>demo-5-sandbox-feature-pr</code> skill from the course repo (<code>.decode/skills/demo-5-sandbox-feature-pr</code>), where we encoded a demo where <strong>Decode</strong> writes a new feature into Decode by spinning up a background sandboxed session, where the host agent acts as the orchestrator and the sandboxed one as the feature executor. The final artifact from the demo will be a PR containing the new feature.</p><p>Go to <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">repository</a>, run <code>decode</code>, type <code>/demo-5-sandbox-feature-pr</code>, and enter. Let Decode do the rest of the work.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!U0HN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!U0HN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 424w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 848w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 1272w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!U0HN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png" width="1200" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;skill demo&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="skill demo" title="skill demo" srcset="https://substackcdn.com/image/fetch/$s_!U0HN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 424w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 848w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 1272w, https://substackcdn.com/image/fetch/$s_!U0HN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa54ad14-87da-4731-bd5e-b3e2d310f634_1200x374.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here is a snapshot of the skill, where Decode spawns another Decode subagent:</p><pre><code><code>...

## 1. Launch decode against a sandboxed clone of the course repo

Launch the local Docker run (Docker must be running):

"""
SANDBOX_MODE=docker decode --repo git@github.com:decodingai-magazine/building-a-coding-agent-from-scratch-course.git
"""

...</code></code></pre><p>At session start, the system prompt is assembled from four parts: the base prompt, the active agent&#8217;s prompt, memory files (<code>AGENTS.md</code> + <code>.decode/MEMORY.md</code>), and the skills catalog (one line per skill). Pydantic AI adds each tool&#8217;s schema, paying off <a href="https://www.decodingai.com/p/the-coding-agent-loop">Lesson 2&#8217;s warning</a> that every tool costs tokens. This assembled prompt enters context, shaping the probabilities of the model&#8217;s next steps.</p><p>The run fills the window. Invoking the skill loads its <code>SKILL.md</code> body (tier 2 of progressive disclosure). Plan mode dumps repo files as <code>read</code> outputs. During the build loop, each <code>edit</code> lands, the Diagnostics Enricher appends type errors for free, and <code>bash</code> runs tests until green output signals completion.</p><p><em>Now, from the context window point of view, what happens within the harness?</em></p><p>As in the image below, as soon as we open the agent, the context window is filled with its system prompt, tool and skill descriptions and memory files. After invoking the <code>/demo-5-sandbox-feature-pr</code> skill, it gets filled with tool inputs and outputs, plus the SKILL.md file containing the specific instructions.</p><p>Next, through progressive disclosure, the agent begins reading the relevant files and scripts associated with the skills. Ultimately, it starts writing new Python files or editing existing ones that are statically checked for syntax issues via our <code>ty</code> Language Server Protocol (LSP) server.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pnf_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pnf_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 424w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 848w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 1272w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pnf_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png" width="1200" height="455" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:455,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The context lifecycle &#8212; what each iteration of one session appends to the window.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The context lifecycle &#8212; what each iteration of one session appends to the window." title="The context lifecycle &#8212; what each iteration of one session appends to the window." srcset="https://substackcdn.com/image/fetch/$s_!pnf_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 424w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 848w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 1272w, https://substackcdn.com/image/fetch/$s_!pnf_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc59b6055-6ca8-49b1-b716-c8a8f023f987_1200x455.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The context lifecycle of a coding agent</figcaption></figure></div><p>On Modal&#8217;s self-hosted <code>Qwen3.6-35B</code>, the window is 262,144 tokens. Usually, microcompaction fires at 60%, while full compaction is at 80%. After compaction, usage drops back to roughly 5&#8211;10%, so the session continues instead of crashing.</p><p>In the video below, you can see part of the 219 spans trace in <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, clearly monitoring the LLM tool calls, token counts, and latency of the harness and LLM calls:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;764baba6-361a-4c1f-9249-14735e9987cc&quot;,&quot;duration&quot;:null}"></div><p>Every component in this lifecycle has specific mechanics: memory, skills, the LSP server, and compaction. Let&#8217;s explore each.</p><h2>Memory: Stop repeating your instructions</h2><p>In my early agent runs, the agent kept writing naive datetime objects instead of timezone-aware ones and added type hints inconsistently, forcing me to retype the same corrections session after session. The fix was to write the preference down once into the <code>AGENTS.md</code>, where the agent reads it every turn.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mNNY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mNNY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 424w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 848w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 1272w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mNNY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png" width="1200" height="600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The two memory files &#8212; one you write by hand, one that writes itself.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The two memory files &#8212; one you write by hand, one that writes itself." title="The two memory files &#8212; one you write by hand, one that writes itself." srcset="https://substackcdn.com/image/fetch/$s_!mNNY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 424w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 848w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 1272w, https://substackcdn.com/image/fetch/$s_!mNNY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5fa3410-408d-4668-a13b-5bdeb47650f5_1200x600.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><code>AGENTS.md</code><em> (the one you write by hand) vs. </em><code>.decode/MEMORY.md</code><em> (the one the agent extracts from each session).</em></figcaption></figure></div><p><code>AGENTS.md</code> injects project context: business logic, why components exist, the tech stack, and the processes around it (docs, deploy, review, testing). The code is the source of truth, so avoid duplicating it. Add metadata and references the agent can discover without heavy reasoning.</p><p>Keep it under 300 lines, with a guardrail of around 600 lines. Write each line in response to an observed mistake so the agent avoids repeating it, following <a href="https://mitchellh.com/writing/my-ai-adoption-journey">Mitchell Hashimoto&#8217;s rule</a>.</p><p>Decode recursively looks within all the project directories for <code>AGENTS.md</code> files (root-most first, so the nearest file takes precedence), appends <code>.decode/MEMORY.md</code> last, stamps each with a <code># From &lt;path&gt;</code> provenance header, and dumps the result into the system prompt.</p><p>If <code>AGENTS.md</code> is what you manually define, <code>.decode/MEMORY.md</code> is what the agent automatically extracts from your conversations, replicating Claude Code&#8217;s auto-memory</p><p>At the end of each session &#8212; on quit and on <code>/clear</code> &#8212; one cheap LLM call summarizes the session into a single plain sentence, appended as a dated bullet (<code>- 2026-06-26: &#8230;</code>), as an append-only log. As this can grow big fast, the file has a hard cap of 200 lines or 25,000 bytes, dropping the oldest lines first.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/memory/extract.py">src/decode/memory/extract.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def extract_on_exit(messages: list[ModelMessage], cwd: Path) -&gt; None:
    summary = await summarize_session(messages, model_or_settings=settings)
    append_session_summary(cwd, summary, now=_utc_now())

    if settings.memory_compression_enabled:
        await compress_memory_file(cwd, model_or_settings=settings)</code></pre></div><p><code>summarize_session</code> is the single LLM call that distills the conversation into one sentence (or <code>None</code> if it&#8217;s not worth saving). <code>append_session_summary</code> writes that sentence into <code>.decode/MEMORY.md</code> and enforces the hard cap.</p><p><code>compress_memory_file</code> runs <strong>Memory Compression</strong> to rewrite the file in place, merging duplicate or superseded notes while preserving dated bullets.</p><h2>Skills: Never load what you can reference</h2><p>My Python testing and PR conventions used to live directly in my memory file, bloating the context of every session. Moving them into skills left behind just a few lines, as references, that specify when to access each one.</p><p>Skills prevent context rot from 2 directions. On the tools side, upfront schemas burn budget: <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">Mario Zechner measured that popular MCP servers consume 7&#8211;9% of the context window</a> before any work begins. On the memory side, stuffing review guides and workflow templates into <code>AGENTS.md</code> pollutes every turn. Skills solve both: each phase-specific behavior lives in its own skill, referenced from a one-line catalog entry, and loads only when that workflow phase runs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zEr0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zEr0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 424w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 848w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 1272w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zEr0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png" width="1200" height="600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The three tiers of progressive disclosure, seen inside the context window.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The three tiers of progressive disclosure, seen inside the context window." title="The three tiers of progressive disclosure, seen inside the context window." srcset="https://substackcdn.com/image/fetch/$s_!zEr0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 424w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 848w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 1272w, https://substackcdn.com/image/fetch/$s_!zEr0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d0163ba-5206-4477-a774-4a2593499b42_1200x600.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The 3 tiers of loading a skill and its bundled files into the context window</figcaption></figure></div><p>Skills follow the <a href="https://agentskills.io/home">Agent Skills standard</a>. In Decode, skills live in <code>.decode/skills/</code>, or you can open the TUI, type <code>/</code>, and pick one. A separate public registry lives at <a href="https://www.skills.sh/">skills.sh</a> (<code>npx skills install &lt;skill&gt;</code>):</p><pre><code><code>my-skill/
&#9500;&#9472;&#9472; SKILL.md          # Required: metadata + instructions
&#9500;&#9472;&#9472; scripts/          # Optional: executable code
&#9500;&#9472;&#9472; references/       # Optional: documentation
&#9500;&#9472;&#9472; assets/           # Optional: templates, resources
&#9492;&#9472;&#9472; ...               # Any additional files or directories</code></code></pre><p><strong>Progressive disclosure</strong> operates across <strong>3 tiers</strong>. In <strong>tier 1</strong>, only the skills catalog stays in context: one <code>name + description</code> line per skill. As your library grows, an optional guard can cap the catalog at ~1% of the context window.</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xhAh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 424w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 848w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 1272w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xhAh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png" width="1200" height="292" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:292,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The tier-1 skills pipeline &#8212; descriptions gathered into a catalog, optionally capped, wrapped into the system prompt.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The tier-1 skills pipeline &#8212; descriptions gathered into a catalog, optionally capped, wrapped into the system prompt." title="The tier-1 skills pipeline &#8212; descriptions gathered into a catalog, optionally capped, wrapped into the system prompt." srcset="https://substackcdn.com/image/fetch/$s_!xhAh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 424w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 848w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 1272w, https://substackcdn.com/image/fetch/$s_!xhAh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd4e626a-873a-40a9-8ca8-9255652381cb_1200x292.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption"><em>Loading the skills catalog into the system prompt.</em></figcaption></figure></div><p>A common strategy Decode doesn&#8217;t have yet is user-invocable-only skills, where you flag a skill as callable only. This means you can remove its name and description from the catalog, leaving it with zero context until explicitly invoked by the user.</p><p>In <strong>tier 2</strong>, invoking a skill via the <code>skill</code><strong> dispatcher tool</strong> or <code>/&lt;skill-name&gt;</code> loads only its <code>SKILL.md</code> body and any other files packed within the skill.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/skills.py">src/decode/tools/skills.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def skill(ctx: RunContext[AgentDeps], name: str) -&gt; str:
    home = ctx.deps.harness_home or ctx.deps.cwd
    catalog = load_skills(home)
    found = catalog.get(name)

    return format_skill_payload(found, cwd=home)</code></pre></div><p>In <strong>tier 3</strong>, because within <code>format_skill_payload</code> we properly format and expose all the available resources (files, scripts, docs, assets) from a skill to the agent, if it considers them necessary, it will load them via its read tool or execute the containing scripts via the bash tool.</p><p>This is the core idea of progressive disclosure. It&#8217;s mostly just exposing a manifest of bundled files with exact cwd-relative paths, making it super clear to the agent how to access them. The key here is that the LLM is properly trained for tool calling to make the right decisions about whether to call read or bash tools.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/skills/payload.py">src/decode/skills/payload.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def format_skill_payload(skill: SkillDef, *, cwd: Path) -&gt; str:
    if skill.resource_dir is None:
        return f"{skill.body}\n\n{_OUTPUTS_TRAILER}"
    rel_dir = os.path.relpath(skill.resource_dir, cwd)
    files = _bundled_files(skill.resource_dir)
    
    listing = "\n".join(f"- {rel_dir}/{name}" for name in files)
    trailer = (
        f"Bundled files for this skill (all under `{rel_dir}/` &#8212; use these EXACT paths):\n"
        f"{listing}\n"
        "Read them with the `read` tool; run `scripts/` files with `bash`."
    )

    return f"{skill.body}\n\n{trailer}\n\n{_OUTPUTS_TRAILER}"</code></pre></div><p>Now let&#8217;s look at the cheapest feedback loop in the whole coding agent.</p><h2>The LSP server: Replace guessing with precision</h2><p>In my multi-agent setup, each turn between the engineer and tester agents re-ran the linter, type checker, formatter, and test suite. My Prefect orchestrator integration tests took 15 minutes on their own, so I split them to speed up the feedback loop.</p><p>The takeaway was clear: the most important part of your agentic flow is to always give as many feedback loops as possible. <strong>The LSP server is the fastest way to feed in code-related signal.</strong></p><p>An LSP server is one of the most underrated components, particularly for coding harnesses. It maintains a live index of symbols across your codebase: variables, functions, classes, definitions, references, and type errors. Your IDE already runs one per language. You need one for each programming language. Decode uses <a href="https://github.com/astral-sh/ty">ty by Astral</a>, an extremely fast type checker and language server written in Rust, to support Python. Made by the same guys behind uv and ruff.</p><p>The server feeds the agent signal through 2 channels.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!N2P_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N2P_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 424w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 848w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 1272w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!N2P_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png" width="1200" height="515" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:515,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Two ways into one LSP server &#8212; the agent asks, or the edit asks on its behalf.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Two ways into one LSP server &#8212; the agent asks, or the edit asks on its behalf." title="Two ways into one LSP server &#8212; the agent asks, or the edit asks on its behalf." srcset="https://substackcdn.com/image/fetch/$s_!N2P_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 424w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 848w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 1272w, https://substackcdn.com/image/fetch/$s_!N2P_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fffa5c0a8-ed47-4023-8ba1-6537bf9ba0a3_1200x515.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The two LSP channels. 1. The agent queries the </em><code>lsp</code><em> tool on demand 2. Every Python edit/write passively pulls diagnostics.</em></figcaption></figure></div><p><strong>Channel 1</strong> is the <code>lsp</code><strong> tool</strong>, which handles active queries with 4 ops: <code>definition</code>, <code>references</code>, <code>hover</code>, and <code>diagnostics</code>. One call returns a precise <code>file:line:column</code> answer instead of 3 speculative file reads. It&#8217;s read-only, so the permission gate auto-allows it across all modes.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/lsp.py">src/decode/tools/lsp.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def lsp(
    ctx: RunContext[AgentDeps],
    op: str,
    path: str,
    line: int | None = None,
    column: int | None = None,
) -&gt; str:
    if op == "definition":
        return await _run_definition(ctx, path, line, column)
    if op == "references":
        return await _run_references(ctx, path, line, column)
    if op == "hover":
        return await _run_hover(ctx, path, line, column)
        
    return await _run_diagnostics(ctx, path)

async def _run_definition(ctx: RunContext[AgentDeps], path: str, line: int, column: int) -&gt; str:
    result = await lsp_service.definition(ctx.deps.cwd, path, line, column)

    return _format_location(result)</code></pre></div><p>The server runs as a background process at each project root, communicating via JSON-RPC (a plain request/response protocol over standard input/output). Decode&#8217;s <code>LspClient</code> initializes the session, negotiates capabilities, and sends requests:</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/services/lsp/service.py">src/decode/services/lsp/service.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from decode.services.lsp.client import LspClient


process = await asyncio.create_subprocess_exec(
    "ty", "server",
    stdin=PIPE, stdout=PIPE, cwd=root,
)
client = LspClient(process, root)
await client.initialize()</code></pre></div><p>In the <code>demo-5</code> session, the agent resolves the entry point via <code>lsp("definition", "src/decode/cli.py", &lt;line&gt;, &lt;column&gt;)</code> over JSON-RPC <code>textDocument/definition</code>. On the next turn, the model targets its edit tool call at that exact location, rather than blindly exploring the codebase first.</p><p><strong>Channel 2</strong> is the <strong>Diagnostics Enricher</strong>, which runs passively on every successful <code>.py</code> write or edit to append an errors-only block to the tool result. It displays at most 10 errors, and stays silent on clean files or when the server is unavailable, matching the pattern in <a href="https://github.com/anomalyco/opencode">OpenCode</a>.</p><p><code>_enrich</code> wraps the return value of file modification tools without requiring extra turns or tools.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/files.py">src/decode/tools/files.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def _enrich(base: str, cwd: Path, path: str) -&gt; str:
    summary = _format_lsp_errors(lsp_service.diagnostics_on_edit(cwd, path))
    if summary is None:
        return base
    return f"{base}\n\n{summary}"

def _format_lsp_errors(diagnostics: list[Diagnostic] | None) -&gt; str | None:
    ...
    errors = [d for d in diagnostics if d.severity == _LSP_ERROR_SEVERITY]
    shown = errors[:_LSP_DIAGNOSTICS_LIMIT]
    lines = [f"LSP diagnostics ({settings.lsp_server_command}) &#8212; fix these:"]
    ...
    return "\n".join(lines)</code></pre></div><p>In the <code>demo-5</code> session, when the agent updates <code>src/decode/cli.py</code> with an unimported reference, the file writes successfully, but the enricher appends <code>LSP diagnostics (ty) &#8212; fix these: ...</code> with the error details. The model sees this feedback immediately and fixes the import on the next <code>edit</code> before running any tests.</p><p>In the video below, you can clearly see in <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a> how the LLM outputs LSP tool calls and how they are executed in the harness:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;88759aa0-fa9a-469e-a237-03c62c9bb762&quot;,&quot;duration&quot;:null}"></div><p>Memory, skills, and the LSP all shape what enters the window. Now let&#8217;s see how we can trim it down.</p><h2>Compaction: Delete before the window rots</h2><p>Back in Nov 2025, when building the writing agent for my agent engineering course, requests started degrading around 180,000 input tokens on Gemini Pro, taking&gt;3 minutes per request or directly returning timeout errors and disconnections. Considering that on paper Gemini handles up to 1M input tokens.</p><p>A full window degrades model performance and reliability long before hitting the hard token ceiling, following the <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">degradation curves documented by Anthropic</a>. That&#8217;s why you need compaction to continually reduce your context window while minimizing context loss.</p><p>Compaction handles this in 3 ways. The simplest is <code>/clear</code>, which wipes the entire window after running the on-exit memory write-back so key learnings persist in <code>.decode/MEMORY.md</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!apDX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!apDX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 424w, https://substackcdn.com/image/fetch/$s_!apDX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 848w, https://substackcdn.com/image/fetch/$s_!apDX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 1272w, https://substackcdn.com/image/fetch/$s_!apDX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!apDX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png" width="1200" height="815" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63c3ab58-49a6-4264-a317-249b97680134_1200x815.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:815,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The three compaction modes and what each one leaves in the window.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The three compaction modes and what each one leaves in the window." title="The three compaction modes and what each one leaves in the window." srcset="https://substackcdn.com/image/fetch/$s_!apDX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 424w, https://substackcdn.com/image/fetch/$s_!apDX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 848w, https://substackcdn.com/image/fetch/$s_!apDX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 1272w, https://substackcdn.com/image/fetch/$s_!apDX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c3ab58-49a6-4264-a317-249b97680134_1200x815.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The three compaction modes: </em><code>/clear</code><em> keeps only the system prompt, </em><code>/compaction</code><em> rebuilds it as summary plus tail, and </em><code>/microcompaction</code><em> swaps old tool outputs for placeholders in place.</em></figcaption></figure></div><p>The second option is <strong>full compaction</strong>, triggered automatically at 80% capacity or manually via <code>/compact</code>. An LLM summarizes the conversations into a six-part template (goal, constraints &amp; preferences, progress, key decisions, next steps, critical context), and older messages are dropped. The window becomes <code>[system prompt] + [summary] + [recent tail]</code>, where the tail retains &#8776;20,000 tokens of recent messages snapped cleanly to a <strong>Compaction Boundary</strong> so tool calls remain paired with their results, matching <a href="https://github.com/earendil-works/pi">Pi&#8217;s implementation</a>.</p><p>Both tiers evaluate <code>should_compact</code> using the provider&#8217;s reported token window against reserve thresholds (80% full compaction -&gt;20% empty, 60% microcompaction -&gt; 40% empty):</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/context/compaction.py">src/decode/context/compaction.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def should_compact(usage: RunUsage, *, window: int, reserve: float, enabled: bool) -&gt; bool:
    if not enabled:
        return False
    if usage.input_tokens &lt;= 0:
        return False
    return usage.input_tokens &gt;= reserve_threshold(window, reserve)</code></pre></div><p>Everything happens within the <code>compact()</code> method from <code>AgentTurnHandler</code>. <code>split_tail</code> walks backward through message history estimating token counts to locate the Compaction Boundary. <code>summarize_for_compaction</code> generates the summary, <code>build_summary_message</code> wraps it as a synthetic user message that is itself part of the history the next compaction summarizes (so successive compactions merge for free), and the handler sends <code>[summary_message, *tail]</code> on the next loop iteration. The harness owns the list it feeds the model, so replacing the list IS the compaction:</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/agent/loop.py">src/decode/agent/loop.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class AgentTurnHandler:
    ...

    async def compact(self) -&gt; CompactOutcome:
        split = split_tail(
            self.message_history, keep_recent_tokens=settings.compaction_keep_recent_tokens
        )
        skeleton = await summarize_for_compaction(
            self.message_history, model=self._compaction_model
        )

        before_tokens = self._last_input_tokens
        summary_message = build_summary_message(skeleton)
        tail = self.message_history[split:]

        self.message_history = [summary_message, *tail]

        return CompactOutcome.COMPACTED</code></pre></div><p>The 3rd and last option is <strong>microcompaction</strong>, which runs without LLM calls at 60% capacity. It replaces tool outputs outside the recent tail with a placeholder string by inspecting each <code>ToolReturnPart</code> (the message part that holds a tool&#8217;s output). Because tool outputs are consumed each turn, conclusions live on in subsequent messages. Nothing is lost because the tool input remains available in the messages, allowing the agent to rerun the tool if necessary. That is why <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">Anthropic calls tool-result clearing the safest, lightest touch of compaction</a>.</p><p>After every completed turn, the handler checks the same number against both thresholds: full compaction first, then <code>microcompact</code>, replacing <code>message_history</code> through the same reassignment.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/context/compaction.py">src/decode/context/compaction.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">_MICRO_PLACEHOLDER = "[tool output elided by microcompaction]"

def microcompact(
    messages: list[ModelMessage],
    *,
    keep_recent_tokens: int,
    placeholder: str = _MICRO_PLACEHOLDER,
) -&gt; list[ModelMessage]:
    boundary = split_tail(messages, keep_recent_tokens=keep_recent_tokens)

    new_messages: list[ModelMessage] = []
    for index, message in enumerate(messages):
        if index &gt;= boundary or not isinstance(message, ModelRequest):
            new_messages.append(message)
            continue

        new_parts = list(message.parts)
        changed = False
        for position, part in enumerate(message.parts):
            if not isinstance(part, ToolReturnPart | RetryPromptPart):
                continue
            new_parts[position] = dataclasses.replace(part, content=placeholder)

        new_messages.append(dataclasses.replace(message, parts=new_parts))

    return new_messages</code></pre></div><p>When saving the session to JSONL files, there is no compaction. The file is a simple snapshot of the entire message history. To save a compacted session, you either have to run it before exiting the session or resume, run it and then exit.</p><p>In the image below, you can see how the <code>/compact</code> command reduced the context window from <code>&#9681; 57%</code> (~149539) to 8% of the context window.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_ExA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_ExA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 424w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 848w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 1272w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_ExA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png" width="1173" height="445" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:445,&quot;width&quot;:1173,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_ExA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 424w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 848w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 1272w, https://substackcdn.com/image/fetch/$s_!_ExA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa16b6e09-7ab9-48e7-a208-c20bb0ac32e4_1173x445.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Next steps</h2><p>There are other components we haven&#8217;t touched on in this article, such as an MCP client or an auto-mode permission layer. Still, these are the 4 harness components that are omnipresent in every coding harness you will use. Maybe Pi, with its minimalist design, is the only exception.</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; <span>We encourage you to&nbsp;</span><strong>clone our&nbsp;<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">course repo</a></strong><span>, open your terminal, type </span><strong><span data-color="#38761d" style="color: rgb(56, 118, 29);">&#8221;decode&#8221;</span></strong>,<strong> </strong>and test out the coding agent.</p></div><p>Within the <a href="https://www.decodingai.com/p/subagents-are-context-engineering">next lesson</a>, we will add the final harness piece to the puzzle: creating an agent&#8217;s catalog used to fan out subagents whose work never pollutes your window.</p><p><span>Here is the</span><strong> course roadmap, </strong><span>lesson by lesson </span><em><span>(</span><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a></em><span>):</span></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><strong>Context Engineering for Coding Agents &#8592; You are here</strong></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p>Or watch the <strong>video version</strong> of the lesson:</p><div id="youtube2-dx77BRFZ0_M" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;dx77BRFZ0_M&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/dx77BRFZ0_M?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>When your coding agent&#8217;s window fills up mid-task, what do you actually do today: </strong></em><code>/clear</code><em><strong> and lose the thread, </strong></em><code>/compact</code><em><strong> and hope the summary gets the job done, or just keep going until it degrades?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/context-engineering-for-coding-agents/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/context-engineering-for-coding-agents/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/context-engineering-for-coding-agents?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/context-engineering-for-coding-agents?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[From a Raw Shell to a Sandboxed Coding Agent]]></title><description><![CDATA[The guide to isolating your harness and safely executing its commands, locally or remotely.]]></description><link>https://www.decodingai.com/p/run-coding-agents-safely</link><guid isPermaLink="false">https://www.decodingai.com/p/run-coding-agents-safely</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 18 Aug 2026 11:02:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!k1Xr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><strong>From a Raw Shell to a Sandboxed Coding Agent</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 3: From Raw Shell to a Sandboxed Coding Agent<em>.</em></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k1Xr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k1Xr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k1Xr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The agent keeps all of its power. The room is what changes.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The agent keeps all of its power. The room is what changes." title="The agent keeps all of its power. The room is what changes." srcset="https://substackcdn.com/image/fetch/$s_!k1Xr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!k1Xr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F97e3b938-fb2a-462c-923f-fbd591667a65_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Mid-session, Claude Code was running inside my Obsidian Second Brain when it fired off a cleanup command that deleted half my notes. If I hadn&#8217;t been backing them up with Obsidian Sync, two years of work would have been gone.</p><p>Even if you carefully isolate your agent, it can still reach the internet and go off the rails. In July 2026, <a href="https://www.scientificamerican.com/article/openai-admits-its-agent-went-rogue-and-hacked-ai-startup-hugging-face/">OpenAI&#8217;s agents</a> hacked Hugging Face. A week later, Anthropic <a href="https://www.anthropic.com/news/investigating-incidents-cybersecurity-evals">disclosed</a> that, after analyzing 141,006 eval runs from an isolated harness, their Claude models had gained unauthorized access to production infrastructure across 3 real organizations.</p><p>Still, for normal people who care about protecting their data, sandboxing is THE containment solution.</p><p>In Lesson 2, we saw how to implement an agent loop that controls your computer through 4 core tools: <code>read</code>, <code>write</code>, <code>edit</code>, and <code>bash</code>. In this article, we will learn how to isolate every computer-use tool from the rest of your system inside a <strong>sandbox</strong>.</p><p>We will hook it to two types of sandbox backends &#8212; local Docker and remote Modal &#8212; plus explore the other options and their trade-offs.</p><p>The cherry on top? GPU compute and scaling out of the box, plugged straight into your harness as a control center.</p><p>By the end, you will run:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">SANDBOX_MODE=modal decode --repo https://github.com/&lt;your-repo&gt;.git "Swap from Gemini to Kimi K3."</code></pre></div><p>Which will spin up a remote Modal sandbox hooked to Decode &#8212; the educational harness we are building throughout this course &#8212; set up the given repo, implement the requested feature, and end with a PR for review as the final artifact.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Try it yourself&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Try it yourself</span></a></p><h2>The tools you love already use a sandbox</h2><p>Locally, every <code>bash</code> command Claude Code or <a href="https://github.com/openai/codex">Codex CLI</a> runs is wrapped in an OS-level jail &#8212; Seatbelt on macOS, bubblewrap on Linux (kernel features that block a process&#8217;s filesystem reach and syscalls).</p><p>In the cloud, Codex isolates <a href="https://blog.bytebytego.com/p/how-openai-codex-works">every task in its own environment (aka sandbox) preloaded with your repo</a>.</p><p><strong>In that case, what&#8217;s a sandbox?</strong> It&#8217;s an execution boundary: the agent runs every tool that can alter the host inside a &#8220;jail&#8221;, so a wrong command runs inside a container, not your host.</p><p>Ok&#8230; That&#8217;s abstract. So how does a harness actually run its tools in this &#8220;jail&#8221;?</p><h2>How do sandboxes actually work?</h2><p>In <a href="https://www.decodingai.com/p/the-coding-agent-loop">Lesson 2</a>, we learned that the core tools the agent uses to interact with your computer are <code>read</code>, <code>write</code>, <code>edit</code>, and <code>bash</code>. The rest (<code>web_fetch</code>, <code>todo_write</code>, <code>ask_user</code>, plan mode) never touch the filesystem &#8212; they are meta tools for fetching context and planning. That&#8217;s why, following Pi&#8217;s philosophy, they are optional.</p><p>Thus, our problem reduces to isolating the execution of the core tools from the rest of the harness. There are two main approaches.</p><p>In <strong>option 1,</strong> we run the whole harness in a Docker container or a remote Modal sandbox. It is straightforward and gives complete isolation, but it forces you to work in an environment different from your machine, with little flexibility to isolate specific tasks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7A90!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7A90!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 424w, https://substackcdn.com/image/fetch/$s_!7A90!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 848w, https://substackcdn.com/image/fetch/$s_!7A90!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 1272w, https://substackcdn.com/image/fetch/$s_!7A90!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7A90!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png" width="1200" height="498" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:498,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The one decision that defines the architecture &#8212; put the whole harness in the box, or keep it home and send only its tools across.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The one decision that defines the architecture &#8212; put the whole harness in the box, or keep it home and send only its tools across." title="The one decision that defines the architecture &#8212; put the whole harness in the box, or keep it home and send only its tools across." srcset="https://substackcdn.com/image/fetch/$s_!7A90!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 424w, https://substackcdn.com/image/fetch/$s_!7A90!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 848w, https://substackcdn.com/image/fetch/$s_!7A90!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 1272w, https://substackcdn.com/image/fetch/$s_!7A90!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a626466-af9c-4245-a046-b7b1c11819cf_1200x498.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The one decision that defines the architecture: Put the whole harness in the sandbox, or keep it local and only execute tools inside the sandbox.</em></figcaption></figure></div><p>In <strong>option 2</strong>, we run the computer-use tools in a sandbox while the harness and the rest of the tools stay on the host. You keep your harness as your control center while executing tools inside the sandbox.</p><p>Option 1 is as simple as SSH-ing into a remote machine and running <code>claude</code>. Option 2 is where the real harness engineering happens.</p><p>The second dimension we have to think about is where the sandbox runs: locally in Docker or remotely on Modal.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7aEX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7aEX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 424w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 848w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 1272w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7aEX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png" width="1200" height="484" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:484,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Where a bash tool call actually runs &#8212; remote on Modal, locally in Docker, or raw on the host.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Where a bash tool call actually runs &#8212; remote on Modal, locally in Docker, or raw on the host." title="Where a bash tool call actually runs &#8212; remote on Modal, locally in Docker, or raw on the host." srcset="https://substackcdn.com/image/fetch/$s_!7aEX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 424w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 848w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 1272w, https://substackcdn.com/image/fetch/$s_!7aEX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde23dee8-a770-4dd1-9d50-4ea4dfb6a1e9_1200x484.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The core idea behind sandboxing computer-use tools such as bash.</em></figcaption></figure></div><p>Regardless of where the sandbox runs, every computer-use tool call gets wrapped in an <code>inSandbox(command)</code> call. In our educational coding harness, Decode, we defined a <code>CommandExecutor</code> interface with 2 implementations (<code>LocalExecutor</code> for the host, <code>SandboxExecutor</code> for a backend), powered by 2 <strong>sandbox backends</strong>: <code>DockerBackend</code> or <code>ModalBackend</code>.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/sandbox/__init__.py">src/decode/sandbox/__init__.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def select_executor(mode: str) -&gt; CommandExecutor:
    if mode == "docker":
        return SandboxExecutor(DockerBackend())
    if mode == "modal":
        return SandboxExecutor(ModalBackend())
    from decode.tools.exec import LocalExecutor

    return LocalExecutor()</code></pre></div><p>The tool never knows where the command runs. The LLM emits the command, while the harness takes care of executing it in the selected environment. Once we build the right executor, we just call <code>executor.run(command)</code>, completely abstracted away from the sandbox &#8212; which means we can extend it with sandboxes beyond Docker or Modal.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/tools/bash.py">src/decode/tools/bash.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def bash(
    ctx: RunContext[AgentDeps],
    command: str,
    timeout: float | None = None,
) -&gt; str:
    if needs_approval(ctx):
        raise ApprovalRequired  # Permission gate &#8212; before anything runs

    if not command.strip():
        raise ModelRetry("command is empty; provide a shell command to run.")
    timeout_s = _resolve_timeout(timeout)

    executor = await _get_executor() # sandbox (powered by Docker or Modal) or local
    result = await executor.run(command, cwd=ctx.deps.cwd, timeout_s=timeout_s)

    return _render(result, timeout_s=timeout_s)</code></pre></div><p>We adopt a similar strategy for the <code>read</code>, <code>write</code>, and <code>edit</code> tools, plus optional ones such as <code>glob</code> and <code>ls</code>. That way the agent sees a single filesystem: when <code>write</code> creates a file, <code>bash</code> sees it immediately.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uAaO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uAaO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 424w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 848w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 1272w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uAaO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png" width="1200" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The executor seam in motion &#8212; the agent loop keeps emitting bash calls on your machine, and each one runs as a command inside the sandbox.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The executor seam in motion &#8212; the agent loop keeps emitting bash calls on your machine, and each one runs as a command inside the sandbox." title="The executor seam in motion &#8212; the agent loop keeps emitting bash calls on your machine, and each one runs as a command inside the sandbox." srcset="https://substackcdn.com/image/fetch/$s_!uAaO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 424w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 848w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 1272w, https://substackcdn.com/image/fetch/$s_!uAaO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1215db45-22b7-45ea-a80d-ce91ae11cda2_1200x592.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The executor logic: The agent loop keeps emitting bash calls on your machine, and each one runs as a command inside the sandbox.</em></figcaption></figure></div><p>Now, let&#8217;s zoom in on how local sandboxes work via Docker.</p><h2>Local sandboxes via Docker</h2><p>Run &#8220;<code>SANDBOX_MODE=docker decode --repo git@github.com:you/project.git"</code> to start a new Decode session inside a Docker sandbox, which contains 5 main steps:</p><ol><li><p><code>DockerBackend</code> launches one long-lived <strong>keeper container</strong> running <code>sleep infinity</code>.</p></li><li><p>Injects all the environment variables from <code>.env</code> into the container.</p></li><li><p>Attaches a local volume at <code>.decode/sandbox</code>.</p></li><li><p>Prepares <strong>the Workspace</strong> by cloning <code>--repo</code> into <code>.decode/sandbox</code> at HEAD.</p></li><li><p>Installs the dependencies by running <code>uv sync</code> on the given <code>--repo</code>.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gae9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gae9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 424w, https://substackcdn.com/image/fetch/$s_!gae9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 848w, https://substackcdn.com/image/fetch/$s_!gae9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 1272w, https://substackcdn.com/image/fetch/$s_!gae9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gae9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png" width="1200" height="309" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:309,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Session start in Docker mode is a straight line &#8212; create the container, inject the env vars, bind the Workspace volume, download the repo, install dependencies.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Session start in Docker mode is a straight line &#8212; create the container, inject the env vars, bind the Workspace volume, download the repo, install dependencies." title="Session start in Docker mode is a straight line &#8212; create the container, inject the env vars, bind the Workspace volume, download the repo, install dependencies." srcset="https://substackcdn.com/image/fetch/$s_!gae9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 424w, https://substackcdn.com/image/fetch/$s_!gae9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 848w, https://substackcdn.com/image/fetch/$s_!gae9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 1272w, https://substackcdn.com/image/fetch/$s_!gae9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbd37a1cb-ef55-4cf9-b5e4-8d823e392358_1200x309.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Docker sandbox lifecycle: Create the container, inject the env vars, bind the Workspace volume, download the repo, install dependencies.</em></figcaption></figure></div><p>Within the <code>DockerBackend</code> class, plugged into <code>SandboxExecutor</code>, we have 2 functions to implement: <code>create</code> and <code>exec</code>. <code>create</code> mostly goes through the 5 steps outlined above. In <code>exec</code>, each <code>bash</code> call translates to a <code>docker exec &lt;command&gt;</code> against its associated container.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/sandbox/docker_backend.py">src/decode/sandbox/docker_backend.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">_WORKSPACE = "/workspace"  # container-side path of the Workspace

class DockerBackend:
    async def create(self, workspace: Path) -&gt; None:
        # once, at session start
        # `workspace` is the host-side clone of your
        # --repo at .decode/sandbox

        args = ["run", "-d", "--rm", "-v", f"{workspace}:{_WORKSPACE}", "-w", _WORKSPACE]
        if sandbox_git_token():
            args += ["-e", GIT_TOKEN_ENV]
        args += ["ghcr.io/astral-sh/uv:python3.12-bookworm-slim", "sleep", "infinity"]
        proc = await asyncio.create_subprocess_exec(
            "docker", *args,
            stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
            env=_run_env(), 
        )
        stdout, _ = await proc.communicate()
        container_id = stdout.decode().strip()  # `docker run -d` prints the container id

    async def exec(self, *args: str, timeout_s: float) -&gt; ExecResult:
        # for every bash tool call &#8212; a fresh exec
        proc = await asyncio.create_subprocess_exec(
            "docker", "exec", "-w", _WORKSPACE, container_id, *args,
            stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
            start_new_session=True,  # own process group &#8594; kill as a unit on timeout
        )
        ...  # gather stdout/stderr &#8594; ExecResult</code></pre></div><p>Docker is easy to set up, works out of the box with container tooling, and the same containers can later be hosted remotely via Kubernetes or other orchestrators. As good as that sounds, it isn&#8217;t truly secure. Container processes are <a href="https://www.youtube.com/watch?v=wsFd22SL1s8">native processes on your kernel</a>. As Abhishek Bhardwaj, on OpenAI&#8217;s RL and agent-infrastructure team, puts it, a container process can exploit that boundary and take the host &#8212; a kernel exploit is <a href="https://www.youtube.com/watch?v=OqM67QG_Ikk">&#8220;a New York Times article waiting to happen&#8221;</a>.</p><p>Docker sits on a spectrum:</p><ol><li><p><strong>fork/exec</strong> &#8212; straightforward to implement, no boundary. The command talks straight to your kernel.</p></li><li><p><strong>Containers</strong> &#8592; <strong>we are here.</strong> A namespace-and-cgroup boundary. Shared kernel. Another option is Podman, which doesn&#8217;t use a daemon, saving latency.</p></li><li><p><strong>gVisor</strong> &#8212; a user-space &#8220;sentry&#8221; kernel answers the syscalls, turning a direct kernel exploit into a two-hop chain (sentry &#8594; host kernel). Costs little: near-container performance. It&#8217;s what <a href="https://modal.com/docs/guide/security?source=decodingai&amp;campaign=harnesseng">Modal runs underneath its sandboxes</a>. Not perfect. If the agent gets past the sentry, you&#8217;re back on the shared kernel.</p></li><li><p><strong>microVMs</strong> &#8212; <a href="https://github.com/firecracker-microvm/firecracker">Firecracker</a> or <a href="https://www.cloudhypervisor.org/">Cloud Hypervisor</a> on KVM, the Linux kernel&#8217;s own hypervisor (Linux hosts only). The guest kernel runs in a separate CPU execution context from the host, so even if the agent fully compromises it, it can&#8217;t reach yours. Cheaper than it sounds: <a href="https://github.com/abshkbh/arrakis">Arrakis</a> boots one in under 7s, against ~40s for a traditional VM.</p></li></ol><p><strong>Seatbelt and bubblewrap sit on the same layer as containers.</strong> They are OS jails. They wrap one command instead of the whole machine, deriving the filesystem profile from the permission rules the agent already uses. No image, no daemon. Still sharing your host&#8217;s kernel. That&#8217;s what Claude Code and Codex CLI run locally. Cheaper than Docker, not stronger.</p><p>So which one? If you trust the code and just want your own files safe, go with <strong>containers</strong> (as we did in Decode). Otherwise, for full isolation, go with <strong>microVMs</strong>. Bhardwaj&#8217;s verdict, after building OpenAI&#8217;s sandbox cloud: <a href="https://www.youtube.com/watch?v=OqM67QG_Ikk">&#8220;in the end, everyone always wants a VM&#8230; let me save you the story and two years of grief, just please use microVMs from the start&#8221;</a>.</p><p>To run it on your own machine, follow the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code">&#8220;Running the Code&#8221; setup steps</a> in the course repo, then launch:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">SANDBOX_MODE=docker decode --repo https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course.git</code></pre></div><p>This clones the repo into the isolated Workspace (<code>/workspace</code> &#8801; host <code>.decode/sandbox</code>) and opens a new TUI session wired to the Docker container. To test it out, pick any feature, plan it, ask for a PR, and let Decode do the rest.</p><p>For a quick test, we prepared a demo wrapped as the <code>/demo-5-sandbox-feature-pr</code> skill. It uses Decode to spin up a new sandboxed Decode session and instructs it to implement a small feature from a pool of available ones (e.g. a <code>decode --version</code> CLI command), then open a PR with it. Creating feature PRs is essential when working in sandboxes, as you have no direct access to where the code actually runs.</p><p>The real win, though, is when the box isn&#8217;t on your machine at all.</p><h2>Remote sandboxes via Modal</h2><p><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>&#8216;s core primitive is <a href="https://modal.com/docs/guide/sandboxes?source=decodingai&amp;campaign=harnesseng">the sandbox</a> &#8212; an isolated, serverless runtime that starts in under half a second.</p><p>Run &#8220;<code>SANDBOX_MODE=modal decode --repo git@github.com:you/project.git"</code> and here is what happens through Modal&#8217;s 5-event lifecycle:</p><ol><li><p><strong>Created</strong>: <code>ModalBackend</code> requests a sandbox under <code>decode-sandbox-&lt;env&gt;</code>.</p></li><li><p><strong>Scheduled</strong>: Modal finds capacity on its infra.</p></li><li><p><strong>Started</strong>: the container is live and can execute commands (but the app is not ready yet).</p></li><li><p><strong>Ready</strong>: the tar containing the app files is uploaded into <code>/workspace</code> (making the app env ready).</p></li><li><p><strong>In use</strong>: <code>bash</code> and the other computer-use tools exec successfully against the remote.</p></li></ol><p>Modal&#8217;s sandbox infra boots fast. Preparing the app dependencies is what takes a while.</p><p>That&#8217;s why, as you can see in the image below, we mount a volume that already contains the app dependencies, so they are ready when the container starts. On top of that, to avoid the cold start problem &#8212; you want the sandbox ready as soon as the harness starts &#8212; we prepare a sandbox pool modeled as a queue. We populate it with application-agnostic sandboxes and turn them into application-specific ones by attaching a volume. This combination of sandbox pool plus volume mounting gives us application-ready sandboxes on demand. More on this <a href="https://modal.com/blog/unpacking-sandbox-startup-latency?source=decodingai&amp;campaign=harnesseng">here</a>.</p><blockquote><p>Check <a href="https://modal.com/blog/scaling-to-1-million-concurrent-sandboxes-in-seconds?source=decodingai&amp;campaign=harnesseng">this blog post</a> if you want to learn more about how Modal dropped Kubernetes and built its sandbox architecture from scratch to start 1 million concurrent sandboxes in under a minute.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uvba!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uvba!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 424w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 848w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 1272w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uvba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png" width="1200" height="618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:618,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The Modal backend &#8212; the harness stays local, every tool call crosses into a remote sandbox that mounts its repository volume, and sandboxes come pre-provisioned from a pool.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The Modal backend &#8212; the harness stays local, every tool call crosses into a remote sandbox that mounts its repository volume, and sandboxes come pre-provisioned from a pool." title="The Modal backend &#8212; the harness stays local, every tool call crosses into a remote sandbox that mounts its repository volume, and sandboxes come pre-provisioned from a pool." srcset="https://substackcdn.com/image/fetch/$s_!Uvba!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 424w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 848w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 1272w, https://substackcdn.com/image/fetch/$s_!Uvba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fbbf5d8-c0e6-45ff-95c3-5c9555da65a2_1200x618.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The Modal backend: The harness stays local, every tool call crosses into a remote sandbox that mounts its repository volume, and sandboxes come pre-provisioned from a pool.</em></figcaption></figure></div><p>The <code>ModalBackend</code> class looks similar to the <code>DockerBackend</code> one. Inside <code>create</code>, we create the sandbox from a pre-built <code>uv</code> Docker image. We inject a git token to get access to our private repositories. Finally, we launch it with the <code>sleep infinity</code> command to keep it running &#8212; now on Modal&#8217;s infrastructure, which takes care of our security concerns.</p><p><strong>Modal puts zero risk on your host.</strong> It&#8217;s remote, and it runs gVisor to intercept syscalls before they reach the kernel. Even when OpenAI&#8217;s agents hacked Hugging Face, as reported <a href="https://www.aljazeera.com/news/2026/7/29/openais-rogue-agent-hacked-an-account-at-a-second-technology-firm-report">here</a>, their code was running on one of Modal&#8217;s sandboxes &#8212; the agent exploited Hugging Face&#8217;s code running there, not the Modal infrastructure itself.</p><p>Within the <code>exec</code> method, we execute the command that comes from the LLM and return the output and exit code.</p><p><em>From <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/src/decode/sandbox/modal_backend.py">src/decode/sandbox/modal_backend.py</a>:</em></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class ModalBackend:
    async def create(self, workspace: Path) -&gt; None:
        app = await modal.App.lookup.aio(_app_name(), create_if_missing=True)
        image = modal.Image.from_registry(
            "ghcr.io/astral-sh/uv:python3.12-bookworm-slim"
        ).apt_install("git", "curl", "ca-certificates")

        secrets = []
        if token := sandbox_git_token():
            image = image.run_commands(GIT_CREDENTIAL_HELPER)
            secrets = [modal.Secret.from_dict({GIT_TOKEN_ENV: token})]

        sandbox = await modal.Sandbox.create.aio(
            "sleep", "infinity",
            app=app, image=image,
            timeout=int(settings.sandbox_timeout_s),
            secrets=secrets,
        )

        ...  # tar-upload the Workspace into /workspace &#8212; the "Ready" step

    async def exec(self, *args: str, timeout_s: float) -&gt; ExecResult:
        proc = await sandbox.exec.aio(*args, workdir=workdir, timeout=timeout, text=False)
        stdout, stderr = await asyncio.gather(proc.stdout.read.aio(), proc.stderr.read.aio())
        exit_code = await proc.wait.aio()

        ...  # &#8594; ExecResult</code></pre></div><p>From <a href="https://modal.com/pricing?source=decodingai&amp;campaign=harnesseng">Modal&#8217;s pricing page</a> at the time of writing: a CPU sandbox at 2 cores + 4 GiB runs &#8776; 0.38/<em>hr</em>, <em>a</em> <em>B</em>200 <em>GPU</em> <em>bills</em> &#8776;6.25/hr, and an H200 &#8776; $4.54/hr. For pure agentic work, the CPU sandbox gets the job done, while the GPU ones let you run inference or fine-tuning jobs directly from your harness.</p><p>The default is using the CPU sandbox. To configure it with x4 H200 we would do:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">sandbox = await modal.Sandbox.create.aio(
    ...,              # Same parameters as the CPU sandbox
    gpu="H200:4",     # 4&#215; H200 attached to this sandbox
)</code></pre></div><p>As discussed in <a href="https://www.decodingai.com/i/208432780/the-llm-providers">Lesson 2</a> on pay-per-token vs. serverless, for ad-hoc data processing serverless can come out ~80-90% cheaper.</p><p>The trade-offs of a remote sandbox over a local one: network latency, sandbox management, and extra costs.</p><p>You can run the same test as for the Docker sandbox by following the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code">&#8220;Running the Code&#8221; Modal extra setup steps</a> and swapping <code>SANDBOX_MODE=docker</code> for <code>modal</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">SANDBOX_MODE=modal decode --repo https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course.git</code></pre></div><p>After running it, Modal&#8217;s dashboard shows how many sandboxes are live (5 in our case):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5yvV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5yvV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 424w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 848w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 1272w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5yvV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png" width="1456" height="433" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:433,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Number of running sandboxes in Modal&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Number of running sandboxes in Modal" title="Number of running sandboxes in Modal" srcset="https://substackcdn.com/image/fetch/$s_!5yvV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 424w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 848w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 1272w, https://substackcdn.com/image/fetch/$s_!5yvV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb61bc42-9973-4655-8108-40308b5a9a8c_3288x978.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And if you open the sandbox app and click &#8220;Sandboxes&#8221;, you get the full list:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0AC-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0AC-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 424w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 848w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0AC-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png" width="1456" height="512" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:512,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The list of running sandboxes inside the Modal sandbox app&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The list of running sandboxes inside the Modal sandbox app" title="The list of running sandboxes inside the Modal sandbox app" srcset="https://substackcdn.com/image/fetch/$s_!0AC-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 424w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 848w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!0AC-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccdaad8d-8c2a-4918-9513-5cd9abb6c812_3088x1086.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>These sandboxes are created when you enter a new Decode session and automatically cleaned up when you exit via the <code>/quit</code> command.</p><h2>The wanted side effects of remote sandboxes</h2><p>Remote sandboxes give you 2 powerful side effects beyond safety.</p><p><strong>The first is compute.</strong> Modal sandboxes accept a <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">GPU spec like </a><code>gpu="B200:8"</code><a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng"> at creation</a>, letting you agentically fine-tune models or process large datasets (eg extracting knowledge graphs from 1000+ documents) with open-weight LLMs such as Qwen3.6, Gemma 4, K3, or GLM5.2.</p><p><strong>The second is scale.</strong> An orchestrator agent running directly on the host (no sandbox) can hand work to background agents running on Modal remote sandboxes. Put them on a CPU if you just need a bunch of parallel agents hitting an LLM API to pull tickets from your Linear backlog, or on a GPU if you need to squeeze out more juice.</p><p>In <a href="https://modal.com/blog/how-ramp-built-a-full-context-background-coding-agent-on-modal?source=decodingai&amp;campaign=harnesseng">this case study</a>, Ramp, a fintech company, runs every agent session in its own Modal sandbox with a full dev environment inside. Modal&#8217;s own conclusion from the case study is that with cheap isolation, the bottleneck shifts from &#8220;can the agent write correct code&#8221; to &#8220;how many agents can you run in parallel&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vi-q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vi-q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 424w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 848w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 1272w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vi-q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png" width="1200" height="551" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:551,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The scaling shape the seam makes possible &#8212; an unsandboxed orchestrator on your machine fans work out to N background agents, each contained in its own sandbox.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The scaling shape the seam makes possible &#8212; an unsandboxed orchestrator on your machine fans work out to N background agents, each contained in its own sandbox." title="The scaling shape the seam makes possible &#8212; an unsandboxed orchestrator on your machine fans work out to N background agents, each contained in its own sandbox." srcset="https://substackcdn.com/image/fetch/$s_!Vi-q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 424w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 848w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 1272w, https://substackcdn.com/image/fetch/$s_!Vi-q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e446570-e1bb-4559-a85a-e95d6bcb4795_1200x551.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Scaling: An unsandboxed orchestrator on your machine fans work out to N background agents, each contained in its own sandbox.</em></figcaption></figure></div><h2>Next steps</h2><p>Should you sandbox all the time? No. As a Claude Code power user, to keep it simple, I still run directly on my machine in folders versioned by git or Obsidian Sync.</p><p>Sandboxes are non-negotiable for:</p><ul><li><p>24/7 personal assistants that control your whole computer like <a href="https://openclaw.ai/">OpenClaw</a> or Hermes;</p></li><li><p>non-engineers using tools like <a href="https://www.anthropic.com/product/claude-cowork">Claude Cowork</a>;</p></li><li><p>unmonitored remote jobs like <a href="https://openai.com/research/codex">Codex</a>;</p></li><li><p>or when chasing GPUs and parallel scale.</p></li></ul><p>Is this the only way to add sandboxes to your harness? As we are just getting started, surely not. For another perspective, <a href="https://www.youtube.com/watch?v=OqM67QG_Ikk">here is Abhishek Bhardwaj&#8217;s talk</a>, explaining how OpenAI runs agent workloads in a cloud of microVM sandboxes instead of containers.</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; <span>We encourage you to&nbsp;</span><strong>clone our&nbsp;<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">course repo</a></strong><span>, open your terminal, type </span><strong><span data-color="#38761d" style="color: rgb(56, 118, 29);">&#8221;decode&#8221;</span></strong>,<strong> </strong>and test out the coding agent.</p></div><p>In the <a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">next lesson</a>, we will explore the key context-engineering techniques that coding harnesses use: memory, compaction, skills, and LSP servers.</p><p>Here is the<strong> course roadmap, </strong>lesson by lesson <em>(<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a></em>):</p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop </a></p></li><li><p><strong>From a Raw Shell to a Sandboxed Coding Agent</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p><span>Or watch the </span><strong><span>video version</span></strong><span> of the lesson:</span></p><div id="youtube2-7CHMb8jWs6A" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;7CHMb8jWs6A&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/7CHMb8jWs6A?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>Do you run your coding agent raw on your machine, or sandboxed?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/run-coding-agents-safely/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/run-coding-agents-safely/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/run-coding-agents-safely?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/run-coding-agents-safely?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; videos</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[11 Tips to Run Coding Agents 24/7 on One Subscription]]></title><description><![CDATA[Context engineering techniques to avoid wasting tokens on what doesn't matter]]></description><link>https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens</link><guid isPermaLink="false">https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 04 Aug 2026 11:04:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-mAQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-mAQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-mAQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-mAQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The archive is enormous. What sits under the lamp is three cards.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The archive is enormous. What sits under the lamp is three cards." title="The archive is enormous. What sits under the lamp is three cards." srcset="https://substackcdn.com/image/fetch/$s_!-mAQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!-mAQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff89ec8d0-4fe0-4c4e-be76-04cb2528a742_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I&#8217;m on vacation, so today I will keep it short.</p><p>Since February 2026, when I got my $200 Anthropic subscription, I maxed it out only once. It happened when Fable was released, and I started using it the way I used previous models such as Opus. After 4-5 queries through my content and software factories, I was running out of tokens.</p><p>Since then, I still use Fable, but only where it&#8217;s worth it. Never hitting my weekly token limit. At least not by surprise. I still have those moments where I am aware that if I press Enter, it will cost me tokens. But sometimes it&#8217;s worth it.</p><p>Anyway, I wanted to share with you 11 context/harness engineering tips that I use in my daily workflows and that work like a charm for me.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Pwe9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Pwe9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 424w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 848w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 1272w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Pwe9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png" width="1200" height="626" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/974dd521-5303-4f87-8903-73775563f70a_1200x626.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:626,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The 11 tips at a glance.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The 11 tips at a glance." title="The 11 tips at a glance." srcset="https://substackcdn.com/image/fetch/$s_!Pwe9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 424w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 848w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 1272w, https://substackcdn.com/image/fetch/$s_!Pwe9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F974dd521-5303-4f87-8903-73775563f70a_1200x626.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>1. Progressive disclosure is the foundation everything else sits on</h2><p>I use references in my <code>AGENTS.md</code> files, LLM wikis, and Obsidian to build hierarchies, so the model walks a table of contents and pulls a file only when something resolves to it. Anthropic frames it as a finite <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">attention budget</a>: every token you add competes with every other one.</p><p>OpenAI rebuilt its <code>AGENTS.md</code> into a roughly 100-line table of contents pointing into a linted docs tree, and shipped about a million lines of Codex-written code that way. Quote: <em><a href="https://openai.com/index/harness-engineering-leveraging-codex-in-an-agent-first-world/">&#8220;give Codex a map, not a 1,000-page instruction manual&#8221;</a>.</em></p><h2>2. Plan like crazy, then let a cheaper model execute</h2><p>Token-wise, planning is cheaper than executing. I use the most powerful model available (currently Fable) to produce a plan, then hand it to a cheaper one. I never say &#8220;implement X&#8221;. Instead, I build an extremely detailed plan going through the system design, architecture, components, interfaces and data flow. When a smaller model executes that, it&#8217;s hard to make a mistake.</p><p>I work the plan through 4 dimensions (known knowns, known unknowns, unknown knowns, unknown unknowns) and let the model grill me with questions to surface blind spots.</p><h2>3. For greenfield work, an LLM wiki is the context you point at</h2><p>A wiki lets a plan reference 30 documents without loading 30 documents. When I start working on a new project, I always build one first: a light context layer built via files instead of a database. The plan cites the index that describes the documents, not the corpus, so it stays grounded at near-zero cost. I wrote a <a href="https://www.decodingai.com/p/llm-wiki-agent-memory">full piece</a> on this.</p><h2>4. Send a cheap subagent to read the whole thing</h2><p>The subagent pays the reading cost. You only receive the summary. When I&#8217;m parsing data, I spin up Haiku or Sonnet subagents that hand back only an executive summary to Opus or Fable. A subagent can <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">burn tens of thousands of tokens</a> and return a distilled 1,000-2,000. I clustered my entire Decoding AI archive this way and my main agent&#8217;s context barely grew.</p><h2>5. An ADR and a glossary per feature</h2><p>For every new feature my planning step outputs a task list, an architecture decision record (ADR), and a glossary update. The ADR caches the why behind each decision; the glossary pins down what each term means. Both act as context for later features. OpenAI recommends the same artifact &#8212; <em><a href="https://openai.com/index/harness-engineering-leveraging-codex-in-an-agent-first-world/">&#8220;exec-plans checked into the repo&#8221;</a></em> with progress and decision logs.</p><h2>6. I don&#8217;t graph-index my codebase</h2><p>I don&#8217;t build graphs to index my codebase. The code and the docs drift apart almost immediately, and then you burn tokens keeping an artifact in sync with the thing it describes. That violates clean code principles before it&#8217;s a token problem.</p><p>Note that keeping a glossary and a log of ADRs is different from building a graph out of your code. The glossary and ADRs are orthogonal to the codebase, tracking your domain conventions and design decisions over time. If you change the code, the ADR log doesn&#8217;t need to be changed. It just gets a new entry.</p><p>Worth being precise, because Cursor is a live counterexample: it <a href="https://read.engineerscodex.com/p/how-cursor-indexes-codebases-fast">diffs its embedding index against file hashes every few minutes</a> and re-uploads only what changed. A strategy that adds a lot of complexity. Meanwhile, Claude Code and Codex just parse the codebase at runtime via glob and grep.</p><h2>7. Your modules are already the graph</h2><p>Instead of indexing, I think hard about how to modularize my code, how to shape the interfaces, and how data moves between components. That is your graph, and progressive disclosure parses it really well.</p><p>My sanity check: can I paste this module into another project and have it work?</p><h2>8. Trim the payload you never see</h2><p>Tools like Claude Code become a Swiss army knife that puts a ton of stuff into the system prompt that you never use. They fill it with references to all their features, such as push notifications, remote triggers, scheduling, etc. The logic is simple: for the harness to work with all those features, they need to be mentioned in the system prompt.</p><p>The solution is either to go with a minimalistic approach such as Pi, which ships a bare-bones coding agent you can extend via plugins, or to trim down your Claude Code/Codex harness via a <code>settings.json</code> like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cFex!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cFex!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 424w, https://substackcdn.com/image/fetch/$s_!cFex!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 848w, https://substackcdn.com/image/fetch/$s_!cFex!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 1272w, https://substackcdn.com/image/fetch/$s_!cFex!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cFex!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png" width="1456" height="1334" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1334,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!cFex!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 424w, https://substackcdn.com/image/fetch/$s_!cFex!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 848w, https://substackcdn.com/image/fetch/$s_!cFex!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 1272w, https://substackcdn.com/image/fetch/$s_!cFex!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0b2baeb-57ed-43bc-95b9-689611b7a519_2360x2163.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Inspired by Matt Pocock&#8217;s <a href="https://www.aihero.dev/how-to-kill-the-bloat-in-claude-codes-system-prompt">aihero.dev guide</a></figcaption></figure></div><p>Here is how my context window looks now. Hooked into my content &amp; software factory on a 1M-token window, my payload is 21.4k tokens: 4.3k system prompt, 11.6k system tools, 2.7k across 17 skills, and 46 MCP tools costing literally zero because they load on demand.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X3z4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X3z4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 424w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 848w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 1272w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X3z4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png" width="493" height="490" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3402bf29-a721-4cda-9880-bebe63e085af_493x490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:490,&quot;width&quot;:493,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;My /context breakdown after trimming &#8212; 21.4k tokens of standing payload, 46 MCP tools at 0 tokens.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="My /context breakdown after trimming &#8212; 21.4k tokens of standing payload, 46 MCP tools at 0 tokens." title="My /context breakdown after trimming &#8212; 21.4k tokens of standing payload, 46 MCP tools at 0 tokens." srcset="https://substackcdn.com/image/fetch/$s_!X3z4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 424w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 848w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 1272w, https://substackcdn.com/image/fetch/$s_!X3z4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3402bf29-a721-4cda-9880-bebe63e085af_493x490.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>9. Turn auto-memory off &#8212; under one condition</h2><p>Auto-memory files, like <code>MEMORY.md</code>, reload into the system prompt every session.</p><p>I set Claude Code&#8217;s auto-memory to false.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HODb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HODb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 424w, https://substackcdn.com/image/fetch/$s_!HODb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 848w, https://substackcdn.com/image/fetch/$s_!HODb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 1272w, https://substackcdn.com/image/fetch/$s_!HODb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HODb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png" width="684" height="251" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba175013-89f9-434c-ab1e-02613800a8dc_684x251.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:251,&quot;width&quot;:684,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Auto-memory switched off in Claude Code's memory panel.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Auto-memory switched off in Claude Code's memory panel." title="Auto-memory switched off in Claude Code's memory panel." srcset="https://substackcdn.com/image/fetch/$s_!HODb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 424w, https://substackcdn.com/image/fetch/$s_!HODb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 848w, https://substackcdn.com/image/fetch/$s_!HODb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 1272w, https://substackcdn.com/image/fetch/$s_!HODb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba175013-89f9-434c-ab1e-02613800a8dc_684x251.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Turning memory off is correct when your continuity already comes from committed artifacts you control (<code>AGENTS.md</code>, ADRs, glossaries, LLM wikis).</p><h2>10. The Caveman plugin</h2><p>I also use the Caveman plugin to cut token usage. LLMs tend to be overly verbose. This plugin transforms the messages from full sentences into &#8220;caveman talk.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Xec!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Xec!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 424w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 848w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Xec!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png" width="1456" height="1062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1062,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Caveman plugin in action.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Caveman plugin in action." title="Caveman plugin in action." srcset="https://substackcdn.com/image/fetch/$s_!8Xec!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 424w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 848w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!8Xec!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21063347-30a0-436a-92ba-afb5eeb716c5_1750x1276.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Caveman plugin in action. Screenshot from their <a href="https://github.com/juliusbrussee/caveman">GitHub repository</a>.</em></figcaption></figure></div><h2>11. The principles that keep every AGENTS.md small</h2><p>Again, to keep the LLM from being overly verbose and to make it support each instruction with examples, I keep these 3 rules in every <code>AGENTS.md</code> file:</p><blockquote><ul><li><p>Always prefer removing instructions over adding more.</p></li><li><p>Always use minimum words that still achieve goal &#8212; explanations, docs, code.</p></li><li><p>New rule in memory (such as AGENTS.md), resources, skills or other files &#8594; always support with clear, concise explanation + good and bad examples. Good examples: &#8220;a 200-token chunk size&#8221;, &#8220;sub-100ms latency&#8221;. Bad examples: &#8220;a powerful architecture&#8221;, &#8220;a robust pipeline&#8221;.</p></li></ul></blockquote><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What technique are you using that is not on this list?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/11-context-engineering-tips-cut-coding-agent-tokens?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[The Bare-Bones Coding Agent Loop]]></title><description><![CDATA[One agent loop, 9 tools, and a terminal you can steer.]]></description><link>https://www.decodingai.com/p/the-coding-agent-loop</link><guid isPermaLink="false">https://www.decodingai.com/p/the-coding-agent-loop</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 28 Jul 2026 13:54:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!jhJo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a><strong> </strong></p></li><li><p><strong>The Bare-Bones Coding Agent Loop</strong> <strong>&#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 2: The Bare-Bones Coding Agent Loop</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jhJo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jhJo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jhJo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The loop runs on its own. The whole trick is staying able to steer it.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The loop runs on its own. The whole trick is staying able to steer it." title="The loop runs on its own. The whole trick is staying able to steer it." srcset="https://substackcdn.com/image/fetch/$s_!jhJo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!jhJo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72c58efe-e07c-42af-9fbe-e8a231384e46_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When I first tried to implement the code for this course I got greedy. I tried to one-shot the harness in Python: a TUI, an agent, and a handful of tools like bash, read, write, and edit. It worked, until I started adding skills, memory, and compaction. That&#8217;s when everything started to fall apart. No &#8220;fix this &#8220; prompt could have saved it. That&#8217;s when I realized that building a harness for a coding agent is a lot more strategic than just: <em>&#8220;Hey, look at OpenCode&#8217;s open-source code and build a replica for me.&#8221;</em></p><p>So, I took a step back, deleted everything and started researching how Claude Code, OpenCode, Aider and Pi work. Only after I pinned down the whole architecture, with its components, interfaces and data flow I started to build Decode. The coding agent I will teach you how to build in this series.</p><p>In this article, lesson 2 from the <strong>open-source course Building a Coding Agent From Scratch</strong>, we will learn <strong>how to build a bare-bones coding agent from scratch</strong>. At feature parity with the popular <a href="https://github.com/earendil-works/pi">Pi</a> agent harness.</p><p>We will build the coding agent loop. See how the loop decomposes a goal into a plan and executes it. Understand which tools are critical for a coding agent, and which ones are nice to have. Build a TUI. See why naively sending messages from the terminal to the agent can corrupt the loop. For the full architecture of <code>Decode</code>, what we will build throughout this series, we recommend reading <a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Lesson 1</a>.</p><p>On top of that, we will plug in 3 LLM providers (Modal, OpenRouter, and Gemini) and understand when serverless computing such as <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a> beats token-based APIs. Also, to easily debug the agent, we will integrate trace monitoring via <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>.</p><p><em>Example of running Decode (our coding agent) powered by Qwen 3.6 35B:</em></p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;0042fe85-84be-40a0-ae28-397aa76ee582&quot;,&quot;duration&quot;:null}"></div><p>Let&#8217;s start with an end-to-end walkthrough of the coding agent harness.</p><h2>One Turn, End to End</h2><p>Our expectations from Decode&#8217;s coding agent loop are similar to any other coding agent you&#8217;re already used to: Claude Code, Codex, Pi, OpenCode, etc. You open it in a repository or any other folder, give it a goal, and let it loop until it completes the goal.</p><p>In our <code>.decode/skills/demo-6-article-kg</code> demo, managed as a skill, we ask Decode to pull data from multiple sources, extract key entities and concepts and render a KG in HTML.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WjR5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WjR5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WjR5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png" width="1456" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;TUI&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="TUI" title="TUI" srcset="https://substackcdn.com/image/fetch/$s_!WjR5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!WjR5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c7cbb63-1eb0-41f3-8479-ea984adb9f4a_1816x855.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The agent kept looping until we got the graph below. Pretty cool, right?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!N80t!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N80t!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 424w, https://substackcdn.com/image/fetch/$s_!N80t!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 848w, https://substackcdn.com/image/fetch/$s_!N80t!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 1272w, https://substackcdn.com/image/fetch/$s_!N80t!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!N80t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png" width="1456" height="847" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:847,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The knowledge graph Decode built from three live articles, rendered as one HTML page.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The knowledge graph Decode built from three live articles, rendered as one HTML page." title="The knowledge graph Decode built from three live articles, rendered as one HTML page." srcset="https://substackcdn.com/image/fetch/$s_!N80t!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 424w, https://substackcdn.com/image/fetch/$s_!N80t!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 848w, https://substackcdn.com/image/fetch/$s_!N80t!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 1272w, https://substackcdn.com/image/fetch/$s_!N80t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F164c2b96-6e40-42f2-bd83-9f546e9195fc_3324x1934.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is a great example where the agent had to break a goal into multiple steps and execute each one independently until the goal is reached.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OA6z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OA6z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 424w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 848w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 1272w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OA6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png" width="1200" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The interactive mode: one turn's machinery, end to end.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The interactive mode: one turn's machinery, end to end." title="The interactive mode: one turn's machinery, end to end." srcset="https://substackcdn.com/image/fetch/$s_!OA6z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 424w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 848w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 1272w, https://substackcdn.com/image/fetch/$s_!OA6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1428edd7-7b87-45c8-9d55-149a682ab5c2_1200x686.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The interactive mode</em></figcaption></figure></div><p>More concretely, this is the agent&#8217;s whole lifecycle: <strong>plan &#8594; explore &#8594; apply &#8594; execute &#8594; observe &#8594; next task</strong>, repeated until the goal is met.</p><p>Everything starts with you typing your goal into the TUI and pressing Enter. The request goes into the steering queue and then into a fresh turn, and the loop sends the prompt and tools to the model, a Qwen3.6 served on Modal. It kicks off planning. Via <code>todo_write</code> it records 4 tasks (fetch &#8594; extract &#8594; render &#8594; verify). Via <code>web_fetch</code> Decode fans out in one step and scrapes all the sources. The model reads the scraped output and extracts the KG triplets into a <code>graph.json</code> file via its <code>write</code> tool &#8212; the first call that can change your disk, so the run stops and asks. You type <code>y</code>. Ultimately it generates the HTML code that loads the data from the JSON files and beautifully renders it by calling the <code>write</code> tool to create the <code>kg.html</code> file. Finally, it calls <code>todo_write</code> to update the TODO list and mark the goal as done.</p><p>Based on our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">open-source GitHub</a>, here are all the components of the agent loop that transform a simple Pydantic AI agent into the foundations of any coding agent you are using out there:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">src/decode/
&#9500;&#9472;&#9472; agent/          # loop.py (the agent loop), factory.py
&#9500;&#9472;&#9472; harness/        # runner.py (single-flight turns), queue.py (steering/follow-up)
&#9500;&#9472;&#9472; tools/          # registry.py, files.py (read/write/edit/glob/grep), bash.py, askuser.py
&#9500;&#9472;&#9472; context/        # session_log.py (append-only JSONL)
&#9500;&#9472;&#9472; observability/  # tracing.py (Opik via OTLP)
&#9492;&#9472;&#9472; tui/            # app.py (prompt_toolkit input), render.py (Rich output)</code></pre></div><p>In this course, we will mostly follow Claude Code/OpenCode&#8217;s design, where we have a larger set of tools, memory and agent features built into the harness. Mostly for educational reasons, to explore all the options out there. But there is also a beautiful, minimalist approach to this, based on the philosophy of Mario Zechner, creator of the Pi harness: strip the agent loop back to its bare bones, keeping only the essential logic, to avoid adding noise into the context window and keep everything observable and in control. If you want more features, you add them explicitly as plugins, instead of getting new &#8220;space ship&#8221; cool-but-useless features with every version. Thus, to understand both perspectives, we will keep drawing parallels to Pi&#8217;s architecture.</p><h2>The Agent Loop</h2><p>In Lesson 1, we said that the agent loop is <em>the good old ReAct pattern</em>. The model reasons, picks a tool, the harness executes it, and the observation feeds the next step &#8212; an agent is just <a href="https://www.anthropic.com/research/building-effective-agents">an LLM using tools on environmental feedback in a loop</a>.</p><p>ReAct in the abstract is reason &#8594; act &#8594; observe. Give it a set of tools it can operate on a codebase and voil&#224;, it becomes a coding agent.</p><p><strong>Plan</strong>: <code>todo_write</code> the task list before touching anything.<br><strong>Explore</strong>: <code>read</code>, <code>glob</code>, <code>grep</code> the codebase.<br><strong>Apply</strong>: <code>write</code> and <code>edit</code>, stopping for your verdict.<br><strong>Execute</strong>: <code>bash</code> the tests, the linter.<br><strong>Observe</strong>: a failure is the next observation, and the repair is another Apply &#8594; Execute pass on the same task. Tick it off, re-enter.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KVlk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KVlk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KVlk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92b11633-a282-4fec-9129-e573664754a4_1200x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The coding agent loop: one goal, one repeating cycle, until the goal is achieved.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The coding agent loop: one goal, one repeating cycle, until the goal is achieved." title="The coding agent loop: one goal, one repeating cycle, until the goal is achieved." srcset="https://substackcdn.com/image/fetch/$s_!KVlk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!KVlk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b11633-a282-4fec-9129-e573664754a4_1200x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In Claude Code&#8217;s leaked source the core loop is ~150 lines. To emphasize the harness around the agent, we will use Pydantic AI for the &#8220;core agent&#8221; and focus on everything around it (from <code>build_agent</code> in <code>src/decode/agent/factory.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def build_agent(*, model: str | None = None) -&gt; Agent[AgentDeps, str | DeferredToolRequests]:
    built_model = _build_model(model=model)
    agent = Agent(
        built_model,
        deps_type=AgentDeps,                       # cwd, task store, event emitter &#8212; the harness state
        output_type=[str, DeferredToolRequests],   # a step ends in text &#8212; or pauses on approvals
        output_retries=3,                          # empty / thinking-only turns get another attempt
        tool_retries=5,                            # only resets on success &#8212; the plan-survival budget
    )
    register_tools(agent)                          # the coding tool set
    _register_instructions(agent)                  # ONE merged system prompt

    return agent</code></pre></div><p>The <code>Agent</code> owns one step: one model request, the tool executions it triggers as &#8220;actions&#8221;, and the results it gets back as &#8220;observations&#8221;, ending in either text or <code>DeferredToolRequests</code>. <strong>The agent loop</strong> is operated by the <code>AgentTurnHandler</code> (<code>src/decode/agent/loop.py</code>) class chaining steps together through <code>agent.iter</code>.</p><p><code>AgentTurnHandler.__call__</code> is an async generator that streams tokens in real time via Python generators. It runs a <code>while True</code> loop with two boundaries: <code>yield Boundary.MODEL_REQUEST</code> and <code>yield Boundary.WOULD_STOP</code>. Via <code>Boundary.MODEL_REQUEST</code>, we can inject (steer) new messages into the loop before it finishes reaching its goals.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class AgentTurnHandler:

    ...                 # ONE instance per session; owns the turn + history

    async def __call__(self, ctx: TurnContext) -&gt; AsyncGenerator[Boundary, list[str]]:
        while True:
            steering = yield Boundary.MODEL_REQUEST
            if pending_results is not None:
                self._append_steering(steering)
                output = await self._run_turn(ctx, deferred_results=pending_results)
                pending_results = None
            else:
                output = await self._run_turn(
                    ctx, prompt=self._compose_prompt(next_prompt, steering)
                )
            if isinstance(output, DeferredToolRequests):
                pending_results = await self._resolve_deferred(ctx, output)
                continue
            self._persist_turn()
            follow_ups = yield Boundary.WOULD_STOP
            if not follow_ups: return
            next_prompt = "\n".join(follow_ups)</code></pre></div><p>The whole action happens inside the <code>self._run_turn</code> method, which makes the actual model call, and based on the results from the model, via the <code>run</code> object, it either emits answers from the model or executes a tool request.</p><p>In more detail, this is what happens:</p><ol><li><p>A fresh step passes <code>prompt</code>, a resumed step passes <code>deferred_tool_results</code>, never both.</p></li><li><p>The <code>async for</code> streams each node to the TUI as an event, so you watch tokens arrive live.</p></li><li><p>The <code>finally</code> carries <code>run.all_messages()</code> forward, so a step that dies keeps everything it accomplished in memory.</p></li></ol><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class AgentTurnHandler:

    ...                         # ...same class as above

    async def _run_turn(self, ctx, *, prompt=None, deferred_results=None) -&gt; str | DeferredToolRequests:
        async with self._agent.iter(
            prompt,
            deps=self._deps,
            message_history=self.message_history,
            deferred_tool_results=deferred_results,
        ) as run:
            try:
                async for node in run:
                    if Agent.is_model_request_node(node):
                        await self._stream_model_node(ctx, node, run)
                    elif Agent.is_call_tools_node(node):
                        await self._stream_tool_node(ctx, node, run)
            finally:
                self.message_history = run.all_messages()
                self._last_input_tokens = _leg_input_tokens(self.message_history)
        return run.result.output</code></pre></div><blockquote><p>&#128161; The loop has no max-steps knob, based on Pi&#8217;s principles: <em>&#8220;the loop just loops until the agent says it&#8217;s done.&#8221;</em> A cap is a guess about how many steps a task needs, and the model already signals completion by returning text instead of a tool call. The signal you should be careful about is the context window.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qpse!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qpse!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 424w, https://substackcdn.com/image/fetch/$s_!qpse!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 848w, https://substackcdn.com/image/fetch/$s_!qpse!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 1272w, https://substackcdn.com/image/fetch/$s_!qpse!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qpse!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png" width="1200" height="725" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:725,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;One turn's lifecycle: steps, pauses, and the two boundaries.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="One turn's lifecycle: steps, pauses, and the two boundaries." title="One turn's lifecycle: steps, pauses, and the two boundaries." srcset="https://substackcdn.com/image/fetch/$s_!qpse!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 424w, https://substackcdn.com/image/fetch/$s_!qpse!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 848w, https://substackcdn.com/image/fetch/$s_!qpse!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 1272w, https://substackcdn.com/image/fetch/$s_!qpse!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca03aacb-f307-4302-b341-d40d28b90b6c_1200x725.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>A turn as a chain of steps</em></figcaption></figure></div><p>The first thing every step does is call a model, and picking that model should always be a one-line config choice.</p><h2>The LLM Providers</h2><p>It&#8217;s an architectural mistake to couple your design to a single provider. The loop shouldn&#8217;t know whether it talks to Gemini, <a href="https://openrouter.ai/">OpenRouter</a>, <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>, or whatever comes next.</p><p>All provider knowledge lives in <code>_build_model()</code> in <code>src/decode/agent/factory.py</code>. You pick the provider by setting the <code>LLM_PROVIDER</code> environment variable, which is picked by your Pydantic settings object from <code>src/decode/config/settings.py</code>.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def _build_model(*, model: str | None = None) -&gt; Model:
    provider = settings.llm_provider                     # explicit LLM_PROVIDER env var
    if provider == "gemini":
        return GoogleModel(
            model or settings.gemini_model,
            provider=GoogleProvider(api_key=_provider_api_key("gemini"))
        )
    if provider == "openrouter":
        return OpenAIChatModel(
            model or settings.openrouter_model,
            provider=OpenRouterProvider(api_key=_provider_api_key("openrouter"))
        )
    if provider == "modal":
        client = AsyncOpenAI(
            base_url=f"{settings.modal_endpoint_url}/v1",
            api_key=token_secret,
            default_headers={"Modal-Key": token_id, "Modal-Secret": token_secret}
        )
        return OpenAIChatModel(
            model or settings.modal_endpoint_model,
            provider=OpenAIProvider(openai_client=client)
        )
        
    raise ValueError(f"unsupported llm_provider: {provider!r}")</code></pre></div><p>So from all the options out there (we know there are tons), why these 3? And no OpenAI or Anthropic. Because between them they cover the three tiers of the build vs. buy decision: Gemini is proprietary (you buy the model), OpenRouter is open weights bought as a service (you buy the serving), and Modal is open weights you serve yourself.</p><p>We choose <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong> as our default option for 3 reasons. <strong>You pay for GPU compute, not tokens</strong>: agentic bursts fit <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">GPU-time pricing</a>. Serverless open-source models supported by Modal that we deployed are Qwen3.6 35B, Kimi K3, and GLM-5.2 via <a href="https://modal.com/blog/introducing-auto-endpoints?source=decodingai&amp;campaign=harnesseng">Modal Endpoints</a>. If you want to use a fine-tuned model, you can easily swap it in with 0 changes on the harness side. Because it&#8217;s serverless, it <strong>scales to zero</strong>: you pay only when the agent is working.</p><p>This combination makes it ideal for intermittent periods of extremely high compute demand. For example, if you want to process 1000 documents, instead of paying for each token, which is what&#8217;s typical of all the APIs out there, you just pay for the compute time. To make testing Decode extremely affordable, for most of our tests we used <code>Qwen3.6 35B</code>, which runs on a single <code>H200</code> GPU at <code>$4.54 / h</code>.</p><p>But going back to our 1000 documents example, if these 1000 documents translate to 1000 * 30000 tokens, that's 30M input tokens, plus ~500 output tokens per document. If we wanted to process all these tokens with Sonnet, that would translate to: <code>30M / 1M x 3 (input) + 500k / 1M x 15 (output) ~= $97</code>. And prompt caching doesn't save us here &#8212; every document is a different prefix, so there's nothing to reuse across calls. Considering we could process this data with Modal at ~3000 tokens/second batched, that's under 3 hours of GPU time, which would have cost only ~$13. Modal <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">benchmarked the same tradeoff</a> and found that giving up interactivity, from ~200ms to ~4s end-to-end, provided an x8 throughput increase on identical hardware. If we do this multiple times per day, it quickly adds up. This is just napkin math, but you get the idea.</p><p>Now, on the other side of the spectrum, let's assume Decode sits idle while it waits on a &#8220;y&#8221; confirmation the agent asked for. If that happens overnight, you can easily add 10 hours of idle time to your GPU billing, an extra ~$45.</p><p>Alongside the pay-per-token model, which quickly becomes inefficient at high <span>volumes,&nbsp;</span><strong><span>another dimension to</span> consider is serverless vs. reserved GPU time</strong>. When you reserve GPUs, you have to reserve your peak. If your peak needs 40 GPUs on Friday afternoon and 2 on Sunday night, you sign for 40 &#8212; and you keep paying for 40 all weekend, all month, all year. With serverless, the meter follows the demand curve, so the total cost is just the rate <code>R_s</code> times whatever you actually used at each moment. The reservation instead charges you rate <code>R_r</code> times the peak, times the entire length of the contract <code>T</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2Fua!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Fua!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 424w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 848w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 1272w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Fua!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png" width="1456" height="562" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:562,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Serverless vs. reserved GPU cost&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Serverless vs. reserved GPU cost" title="Serverless vs. reserved GPU cost" srcset="https://substackcdn.com/image/fetch/$s_!2Fua!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 424w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 848w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 1272w, https://substackcdn.com/image/fetch/$s_!2Fua!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c92b0f8-5161-491d-adf4-59d5a5538f04_1498x578.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Formula to check the costs of serverless vs. reserved infrastructure (<a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">source</a>)</figcaption></figure></div><p>In other words, if reserving is <code>5x</code> cheaper than serverless, but your peak is <code>5x</code> higher than your average, then you break even. And the further your peak climbs above that price advantage, the better off you are paying for serverless. For the full math, <a href="https://modal.com/blog/how-to-price-serverless?source=decodingai&amp;campaign=harnesseng">see this blog post</a>.</p><p><strong>OpenRouter</strong> is the most popular gateway to every hosted model: closed source (Claude, OpenAI, Gemini) or open-source (Kimi K3, Z GLM-5.2, Gemma 4, etc.) behind one key. Thanks to their huge aggregated pool of models, they also have some free defaults, such as <code>qwen/qwen3-coder:free</code>, which we used in this course. Having them integrated into your app is a powerful way to easily experiment with different models without worrying about the underlying infrastructure.</p><p>We picked <strong>Gemini</strong> mostly due to their generous free tier, to provide you a third option to run Decode without any cost. Their models are rarely the best, but relative to other API-based models, especially OpenAI &amp; Anthropic, they&#8217;re cheap and good enough to get most jobs done.</p><p>We recommend starting with <a href="https://modal.com/blog/introducing-auto-endpoints?source=decodingai&amp;campaign=harnesseng">Modal Endpoints</a>, powered by <code>Qwen3.6 35B</code> by default, that spins up in a couple of minutes a configurable <code>SGLangEndpoint</code>. <code>SGLang</code> is the right default here because it and <code>vLLM</code> land in <a href="https://modal.com/llm-almanac/summary?source=decodingai&amp;campaign=harnesseng">roughly the same place on throughput</a>, but <code>SGLang</code> boots in ~1 minute against vLLM&#8217;s ~5 for small models, which is everything when your endpoint scales to zero. Modal&#8217;s $30 in free credits each month covers ~6.5 hours of <code>H200</code> time, enough to run the whole course at no cost. And while <code>Qwen3.6 35B</code> is small next to GLM-5.2 740B or even GPT OSS 120B, it&#8217;s well tested with Decode and works well enough for our examples.</p><p>After you&#8217;ve completed the basic setup on Modal, you can start a new endpoint just by running:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">modal endpoint create --model Qwen/Qwen3.6-35B-A3B-FP8 --env main</code></pre></div><p>While trying it out, to avoid the cold start problem, we recommend setting the autoscaling limits to a minimum of 1 container:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;c4cab325-9438-4644-8a2f-8422259d4991&quot;,&quot;duration&quot;:null}"></div><blockquote><p>&#129489;&#8205;&#128187; Find the full setup docs in our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">GitHub repo</a>.</p></blockquote><p>But between Modal and OpenRouter, you can easily swap between hundreds of models. You can try out whatever you&#8217;re interested in. The only requirement is that it supports tool calling.</p><h2>The System Prompt</h2><p>The entire base system prompt is one paragraph:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">You are Decode, a terminal coding agent that helps a developer in their working
directory. You are concise and precise: answer directly, prefer running the work
over describing it, and never invent file contents or command output you have not
seen. When you do not have a tool for something yet, say so plainly rather than
pretending.</code></pre></div><p>The team behind Pi started this minimalist mentality, where you keep your system prompts, tools, and features to a minimum, to avoid filling your context window with noise that confuses the model more than it helps. This also makes maintaining and understanding the prompts, for us as humans, a lot easier. In the past months, OpenAI and Anthropic followed, trimming their system prompts by up to 70%, as more and more functionality around coding gets baked directly into the model&#8217;s weights.</p><p>Still, this paragraph is only the baseline. Pydantic AI builds a schema from every tool&#8217;s signature, which is added to the system prompt. Thus, each tool comes with a cost, meaning that the more tools you use, the more context window you consume, and the model becomes more confused about which one to pick. This becomes even more problematic when we start adding memory and skills into the mix, as we will see in future lessons.</p><p>Whichever model answers, it can only touch your repo through the tools.</p><h2>The Core Tools</h2><p>In reality, the tools are 90% of why this is a coding agent and not any other kind of AI agent. The agent needs to <a href="https://mitchellh.com/writing/my-ai-adoption-journey">read files, execute programs, make HTTP requests</a>. <a href="https://github.com/earendil-works/pi">Pi</a> ships exactly <code>read</code>, <code>write</code>, <code>edit</code>, and <code>bash</code> &#8212; under 1,000 tokens of prompt plus definitions, <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">still respectable &#8212; top 10 on Terminal-Bench 2.0</a>.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">read   path, offset?, limit?   &#8594; file contents; first 2,000 lines by default
write  path, content           &#8594; create or overwrite; makes parent dirs
edit   path, oldText, newText  &#8594; exact-match surgical replace (whitespace included)
bash   command, timeout?       &#8594; run it in the cwd; returns stdout + stderr</code></pre></div><p>On top of these 4 core tools, we have more specialized I/O tools such as <code>glob</code> and <code>grep</code>. Then there&#8217;s <code>todo_write</code>, used to decompose the goal into a plan of TODOs, <code>web_fetch</code> to fetch web pages, and <code>ask_user</code> to interact with the user.</p><blockquote><p>&#128161; Pi doesn&#8217;t have a <code>todo_write</code> tool because it considers that the best way to store your plan is directly in a Markdown file, not in an in-memory TODO list the agent has to keep track of &#8212; <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">a PLAN.md on disk beats an in-memory list</a>.</p></blockquote><p>Every snippet below opens with <code>ctx: RunContext[AgentDeps]</code>. <code>RunContext</code> is Pydantic AI&#8217;s per-run context object: the framework injects it as every tool&#8217;s first parameter and hides it from the model&#8217;s tool schema. The model calls <code>edit(path, old_string, new_string)</code> and never knows <code>ctx</code> exists.</p><p><code>AgentDeps</code> is in our harness. We declare it once as <code>deps_type=AgentDeps</code> in <code>build_agent</code>, pass it into <code>agent.iter(deps=...)</code>, and Pydantic AI hands it to every tool call. <code>RunContext[AgentDeps]</code> reads as &#8220;this run&#8217;s context, whose <code>.deps</code> is an <code>AgentDeps</code>.&#8221; It is the harness state, arriving by injection (from <code>src/decode/agent/deps.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">@dataclass(slots=True)
class AgentDeps:                                   # every tool's ctx.deps &#8212; the harness, injected
    cwd: Path                                      # the jail: file tools + bash resolve paths here
    emit: EventSink                                # push an event &#8594; the TUI renders it
    gate: PermissionGate                           # the allow / ask / deny policy (Section 6)
    resolve_permission: PermissionResolver         # a gate "ask" &#8594; the human's verdict, awaited
    resolve_user_question: UserQuestionResolver    # ask_user's answer, on the SAME channel
    task_store: list[Task] = field(default_factory=list)      # what todo_write rewrites in place</code></pre></div><p><code>emit</code>, <code>resolve_permission</code>, and <code>resolve_user_question</code> are used for dependency injection, so tools reach the terminal without importing the TUI, and they make this code easily testable by swapping in a different <code>AgentDeps</code>.</p><p>To keep things short and sweet, I will skip how <code>read</code> and <code>write</code> work and go straight to <code>edit</code> (see them at <code>src/decode/tools/files.py</code>). <code>edit</code> is a find-and-replace with one rule: load the file&#8217;s text, find <code>old_string</code> inside it, dump <code>new_string</code> into that exact spot, write the file back. But the devil is in the details. To make this replace work, it first needs to normalize away the invisible formatting the model was never shown &#8212; a file&#8217;s line-ending convention, a leading byte-order mark &#8212; so a match never fails on characters the model had no way to guess. Then it looks for <code>old_string</code>, and only when that misses does it retry with whitespace collapsed on both sides. Either way, the match must be <strong>unique</strong>: 0 hits returns <code>not found</code>, 2+ returns <code>ambiguous, N matches</code>, and both end up with <code>ModelRetry</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def edit(ctx: RunContext[AgentDeps], path: str, old_string: str, new_string: str) -&gt; str:
    if needs_approval(ctx):
        raise ApprovalRequired
    target = _resolve_in_cwd(ctx.deps.cwd, path)
    raw = target.read_bytes().decode("utf-8")
    final = _apply_edit(raw, old_string, new_string)
    _atomic_write_bytes(target, final.encode())

    return f"Edited {path!r} (replaced 1 occurrence)."</code></pre></div><p>Within <code>todo_write</code>, the model sends the <strong>full</strong> desired list on every call and the tool overwrites the whole list &#8212; which is exactly what stops the plan from drifting out of the context window. The overwrite is in place (<code>[:] = tasks</code>, not a rebind) so the loop and the TUI keep pointing at the same list object, and every item is validated by the <code>Task</code> Pydantic model on the way in. It then emits one <code>TaskListUpdated</code> event carrying pre-rendered checklist lines: the tool maps <code>pending / in_progress / completed</code> to <code>[ ] / [~] / [x]</code> itself, so the renderer never has to learn the status vocabulary. The store is in-memory and per-run &#8212; nothing about the task list outlives the process (from <code>src/decode/tools/tasks.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def todo_write(ctx: RunContext[AgentDeps], tasks: list[Task]) -&gt; str:
    if needs_approval(ctx):
        raise ApprovalRequired
    ctx.deps.task_store[:] = tasks
    ctx.deps.emit(events.TaskListUpdated(tasks=_checklist_lines(tasks)))

    return f"Updated task list ({len(tasks)} task(s))."</code></pre></div><p>That <code>emit</code> line is the harness&#8217;s entire UI protocol. <code>events</code> is the <code>decode.entities.events</code> module of frozen dataclasses (<code>TurnStarted</code>, <code>ToolCallStarted</code>, <code>ToolResult</code>, <code>TaskListUpdated</code>, ...) joined into one union known by the renderer.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">Event = (
    TurnStarted
    | TurnFinished
    | AssistantTextDelta
    | ThinkingDelta
    | ToolCallStarted
    | ToolResult
    | PermissionRequested
    | AskUserRequested
    | TaskListUpdated
    | ContextCompacted
    | ContextMicrocompacted
    | AgentError
)</code></pre></div><p><code>ctx.deps.emit</code> is a synchronous event-based sink, injected into the harness to communicate with outer layers, in this case the TUI. This is clean architecture 101. The tool describes what happened as a typed value, and the TUI decides how to draw it.</p><p><code>web_fetch</code> makes an async httpx GET request. What comes back is filtered twice before the model sees it &#8212; non-text content types are refused outright, and the decoded body is hard-capped at 2 MB, so an enormous page can never eat your entire context window. HTML is then mapped to Markdown keeping mostly the body and other metadata such as the title. Every failure path &#8212; non-2xx, timeout, connection error, wrong content type, HTML nested too deep to parse &#8212; throws a <code>ModelRetry</code> error, so a bad fetch is an observation the model has to handle explicitly and not ignore (from <code>src/decode/tools/web.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def web_fetch(ctx: RunContext[AgentDeps], url: str) -&gt; str:
    if needs_approval(ctx):
        raise ApprovalRequired
    _validate_url(url)
    response = await _get(url)
    body = _render_body(response, _decode_body(response))

    return f"HTTP {response.status_code} {response.url}\n\n{body}"</code></pre></div><p><code>ask_user</code> lets the agent request input from the user. It emits <code>AskUserRequested</code> so the TUI renders the question, then awaits <code>ctx.deps.resolve_user_question</code>. Two things can go wrong: the agent loop can run in headless mode, where there is no interactive user at all, or the question can be dismissed (turn aborted, REPL shutting down). Both become <code>ModelRetry</code> text telling the model plainly to proceed without an answer (from <code>src/decode/tools/askuser.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def ask_user(ctx: RunContext[AgentDeps], question: str) -&gt; str:
    ctx.deps.emit(events.AskUserRequested(question=question))
    try:
        return await ctx.deps.resolve_user_question(question)
    except NoInteractiveUserError as exc:
        raise ModelRetry(str(exc)) from exc</code></pre></div><p><code>bash</code> is the most powerful. Via <code>bash</code> the agent can execute any shell command such as <code>ls</code>, <code>cd</code>, <code>mkdir</code>, <code>rm</code>, <code>cp</code>, <code>mv</code>, and <code>echo</code>. Plus, piping and everything else you can run in a terminal. Which means that via <code>bash</code> the agent can run Python, TypeScript, Rust, or any other language. Via <code>bash</code> it can manipulate all the CLIs you give it access to.</p><blockquote><p><em>Via </em><code>bash</code><em> it gets that magical feeling of being able to interact with the operating system and run any command.</em></p></blockquote><p>But this also makes it the most dangerous one. <code>rm -rf ~/</code> is always <a href="https://modal.com/llm-almanac/summary?source=decodingai&amp;campaign=harnesseng">only a few tokens away</a>. That&#8217;s why running your agent in a sandbox environment becomes so important. In a future lesson, we will get into the executor and how to run commands in local Docker and remote <a href="https://modal.com/docs/guide/sandboxes?source=decodingai&amp;campaign=harnesseng">Modal containers</a>.</p><p>Bash plus code execution is a big step toward <a href="https://blog.langchain.com/the-anatomy-of-an-agent-harness/">giving the model a computer</a> (from <code>src/decode/tools/bash.py</code>):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">async def bash(ctx: RunContext[AgentDeps], command: str, timeout: float | None = None) -&gt; str:
    if needs_approval(ctx):
        raise ApprovalRequired
    timeout_s = _resolve_timeout(timeout)
    result = await _get_executor().run(command, cwd=ctx.deps.cwd, timeout_s=timeout_s)

    return _render(result, timeout_s=timeout_s)</code></pre></div><p>As we&#8217;ve seen at the beginning, the lifecycle of the agent is based on running these tools in order: <code>todo_write</code> plans, <code>read</code> / <code>glob</code> / <code>grep</code> explore, <code>write</code> / <code>edit</code> apply, <code>bash</code> executes (<code>bash</code>&#8216;s exit code is the observation that starts the next pass).</p><p>When running <code>.decode/skills/demo-6-article-kg</code> that asks the agent to scrape 3 web pages and build a knowledge graph, the agent creates a 4-step plan, keeps track of it via <code>todo_write</code>, fetches the data via <code>web_fetch</code>, extracts the KG triplets directly, then via <code>write</code> saves them to <code>graph.json</code>. Next, it writes the HTML and CSS code that displays the KG triplets into <code>kg.html</code>. Ultimately, via <code>bash</code> it checks that the HTML code renders correctly. If not, the model <code>edit</code>s the code and retries.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!h25c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!h25c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 424w, https://substackcdn.com/image/fetch/$s_!h25c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 848w, https://substackcdn.com/image/fetch/$s_!h25c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 1272w, https://substackcdn.com/image/fetch/$s_!h25c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!h25c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png" width="1456" height="877" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:877,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Opik Plan&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Opik Plan" title="Opik Plan" srcset="https://substackcdn.com/image/fetch/$s_!h25c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 424w, https://substackcdn.com/image/fetch/$s_!h25c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 848w, https://substackcdn.com/image/fetch/$s_!h25c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 1272w, https://substackcdn.com/image/fetch/$s_!h25c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F794bbda3-92ab-43cf-9988-b5680507589f_2874x1732.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Adding Tracing to Understand What Is Going On</h2><p>We&#8217;ve seen above how the agent calls the <code>todo_write</code> tool to bake the plan into its state. The trace is logged via <a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>. Let&#8217;s see how easy it is to plug it into your own code.</p><p>Debugging your agent via the terminal is terrible. Not only is reading the full traces hard, sometimes it&#8217;s impossible, as you just don&#8217;t have access to all the spans, plus other essential metadata such as configs, token counts, tool inputs and outputs &#8212; and the list goes on. That&#8217;s why you need to plug in an observability tool like Opik from day 0 to get visibility into your agent&#8217;s behavior.</p><p>As we use Pydantic AI, it has native support for tracing via Logfire, the observability tool made by Pydantic. Logfire, like most observability tools, supports OpenTelemetry (OTLP) out of the box, which is the standard wire protocol for tracing. Thus, hooking up Opik is as easy as defining the <code>OTLPSpanExporter</code> to point to Opik&#8217;s managed servers via the <code>endpoint</code> parameter, plus authentication headers. As Opik is open-source, this would work exactly the same if you were hosting it yourself (from <code>src/decode/observability/tracing.py</code>).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def init_tracing() -&gt; bool:
    key = settings.opik_api_key.get_secret_value()
    if not key:
        return False

    exporter = OTLPSpanExporter(
        endpoint=f"{base}/v1/traces",
        headers={"Authorization": key, "Comet-Workspace": settings.opik_workspace,
                 "projectName": settings.opik_project_name})
    logfire.configure(send_to_logfire=False, console=False,
        additional_span_processors=[BatchSpanProcessor(CostAnnotatingExporter(exporter))])
    logfire.instrument_pydantic_ai()

    return True</code></pre></div><p>You can find the full setup on how to get started with Opik in our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/blob/main/running_the_code/install_and_usage.md">GitHub repository</a>. Opik is optional to get through the course, but note that it has a generous freemium plan with 25k spans/month free. You can run the whole course for free.</p><p>In the GIF below, you can see an end-to-end trace of how the agent executed the <code>.decode/skills/demo-6-article-kg</code> skill that builds the KG from 3 articles. It consists of 47 spans, covering 6 steps, 15 model calls, and 18 tool executions over ~6m.</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;e926026d-53d7-4f4f-b61e-fd291b72afe2&quot;,&quot;duration&quot;:null}"></div><p>With the following token usage (no cost per token as we ran it via Modal):</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">cache_read.input_tokens: 631424
completion_tokens: 19781
details.cache_read_tokens: 631424
details.reasoning_tokens: 2912
prompt_tokens: 655624
total_tokens: 675405</code></pre></div><h2>The TUI and the Queues</h2><p>You can build a TUI in <a href="https://mariozechner.at/posts/2025-11-30-pi-coding-agent/">2 ways</a>. <strong>Full-screen</strong> takes over the terminal&#8217;s viewport as a grid of cells (Amp, OpenCode): total layout control, but you lose scrollback, search and have to implement a bunch of features from scratch. <strong>Append-to-scrollback</strong> writes like an ordinary CLI (Claude Code, Codex, Pi). Decode takes the second approach.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3VGC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3VGC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3VGC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png" width="1456" height="791" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:791,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;TUI&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="TUI" title="TUI" srcset="https://substackcdn.com/image/fetch/$s_!3VGC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!3VGC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9441cf15-4eb2-4376-9ee6-3f6c6031b696_1815x986.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As Python packages, we use <code>prompt_toolkit</code> to read the input and <code>Rich</code> to render output in append-style. Below you can see the loop that takes events from the harness and renders them on the TUI (from <code>src/decode/tui/app.py</code>).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">with patch_stdout(raw=True):
    while True:
        submitted = await session.prompt_async(_PROMPT)   # one pinned input line
        intent, text = _interpret(submitted)              # Enter / Alt+Enter / Esc
        if decisions.pending:                             # mid-turn question? answer it
            decisions.resolve(text)
            continue
        await runner.submit(text, intent)</code></pre></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sVk_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sVk_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 424w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 848w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 1272w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sVk_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png" width="1456" height="829" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The Decode TUI on startup &#8212; the Modal-served model in the banner, Opik tracing on, and the footer naming all three input modes.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The Decode TUI on startup &#8212; the Modal-served model in the banner, Opik tracing on, and the footer naming all three input modes." title="The Decode TUI on startup &#8212; the Modal-served model in the banner, Opik tracing on, and the footer naming all three input modes." srcset="https://substackcdn.com/image/fetch/$s_!sVk_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 424w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 848w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 1272w, https://substackcdn.com/image/fetch/$s_!sVk_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67513ce7-f3d1-4d72-9116-d8965e52021e_1815x1033.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But what happens when you type a new command mid-turn, while the agent is still running your previous one? Injecting it instantly would corrupt the current tool call. Thus, you need to buffer your input on arrival and inject it only at boundaries, such as after a tool finishes running or a whole turn ends.</p><p>The input can arrive in 3 modes.</p><ul><li><p><strong>Steering</strong> (plain <code>Enter</code>): the Runner executes it within a model turn, between tool calls.</p></li><li><p><strong>Follow-up</strong> (<code>Alt+Enter</code>): the Runner holds it until the turn stops, then runs it as one more step.</p></li><li><p><strong>Cooperative abort</strong> (<code>Esc</code>): sets a flag to stop the agent turn at the next boundary. Next, it clears both queues. This avoids corrupting the history.</p></li></ul><p>As seen within the <code>InteractionQueues</code> class, for steering and follow-ups we use two different in-memory queues (from <code>src/decode/harness/queue.py</code>).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">@dataclass(slots=True)
class InteractionQueues:
    steering: asyncio.Queue[str] = field(default_factory=asyncio.Queue)
    follow_up: asyncio.Queue[str] = field(default_factory=asyncio.Queue)
    def drain_steering(self) -&gt; list[str]:  return _drain(self.steering)
    def drain_follow_up(self) -&gt; list[str]: return _drain(self.follow_up)
    def clear(self) -&gt; None:                # on abort: drop everything pending
        _drain(self.steering)
        _drain(self.follow_up)</code></pre></div><p>This loop belongs to the <code>Runner</code>, which is the facade between the TUI and the agent. Its job is to keep the agent alive as long as the TUI session is running. It also takes care of draining the queues at the right moments and sending them to the agent (from <code>src/decode/harness/runner.py</code>).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">class Runner:

    ...                 # single-flight: one turn in flight, ever

    async def _run_turn(self, turn_id: int, prompt: str) -&gt; None:
        agen = self._turn_handler(ctx)
        boundary = await agen.asend(None)
        while True:
            if self._abort:
                aborted = True
                break                                 # Esc: stop at the boundary, keep history
            if boundary is Boundary.MODEL_REQUEST:
                sent = self.queues.drain_steering()   # steering: before every model call
            elif boundary is Boundary.WOULD_STOP:
                sent = self.queues.drain_follow_up()  # follow-up: only when the turn would end
            try:
                boundary = await agen.asend(sent)     # resume the loop; get the next boundary
            except StopAsyncIteration:
                break</code></pre></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vDAk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vDAk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 424w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 848w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 1272w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vDAk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png" width="1200" height="665" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:665,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Two queues, two drain boundaries, one safe turn.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Two queues, two drain boundaries, one safe turn." title="Two queues, two drain boundaries, one safe turn." srcset="https://substackcdn.com/image/fetch/$s_!vDAk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 424w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 848w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 1272w, https://substackcdn.com/image/fetch/$s_!vDAk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F293cd381-1a60-4553-8c55-5a9b147f1815_1200x665.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Buffer instantly, inject only at boundaries</em></figcaption></figure></div><p>This is the approach implemented in Pi. Another option, implemented in OpenCode, is to keep track of the session in your database, which means you can use your database as the queue as well. But that also means that you need to complicate your solution with a database. Which raises the question, how do we keep track of sessions?</p><h2>The Session Log</h2><p>In the interactive mode the conversation is the working state. To keep track of sessions, we create a <strong>session log</strong> &#8212; an append-only JSONL file per session under <code>.decode/sessions/</code>. This simple approach kills the need for a database entirely. This is how Claude Code implements their session management.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">.decode/sessions/
&#9500;&#9472;&#9472; 20260620T132411Z_d710a5b9-28af-418b-9a15-936942a8db12.jsonl
&#9500;&#9472;&#9472; 20260620T132419Z_058cddc8-1d0f-406d-a754-098703c07cb5.jsonl
&#9500;&#9472;&#9472; 20260622T110408Z_7114fe38-d294-4c78-bbc3-c454be57082b.jsonl
&#9500;&#9472;&#9472; 20260622T111609Z_4bbf140e-3495-4d69-9a88-c7014fd77742.jsonl
&#9500;&#9472;&#9472; 20260625T152011Z_7594e9b0-6c62-421a-ad74-9918c4d0291e.jsonl
&#9492;&#9472;&#9472; ...</code></pre></div><p>Every completed turn appends one <code>messages</code> line to the log. An aborted or crashed turn persists what it finished (from <code>src/decode/context/session_log.py</code>).</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def append_turn(self, new_messages: list[ModelMessage]) -&gt; None:
    if not new_messages:
        return

    payload = json.loads(ModelMessagesTypeAdapter.dump_json(new_messages))
    entry = {"type": "messages", "messages": payload}
    with self.path.open("a", encoding="utf-8") as handle:
        handle.write(json.dumps(entry) + "\n")</code></pre></div><p>Based on the knowledge-graph example, here is how the log entries look:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">{"type": "session", "version": 1, "session_id": "48900d84&#8230;", "cwd": "&#8230;/building-a-coding-agent-from-scratch-course", "created_at": "2026-07-16T19:32:01Z"}
{"type": "messages", "messages": [
    {"role": "user", "content": "The hardcore one: turn three live articles into a knowledge graph&#8230;"},
    {"role": "tool", "name": "web_fetch", "content": "HTTP 200 &#8230;/keep-knowledge-graph-clean\n\nHow to Keep a Knowledge Graph Clean&#8230;"},
    {"role": "tool", "name": "bash", "content": "Exit code: 0.\n\nstdout:\nNode count: 28 (should be 20-35)\nEdge count: 29&#8230;"},
    {"role": "assistant", "content": "## Knowledge Graph Visualization &#8212; Complete&#8230;"}]}</code></pre></div><p>To resume the state, you can run <code>decode --resume &lt;session_id&gt;</code> to kick off a new TUI from an existing session log.</p><h2>Next Steps</h2><p>In this lesson, we&#8217;ve implemented a bare-bones version of the coding agent, adding the right tools, a TUI, and a way to manage sessions. More or less, at this point, we are at feature parity with Pi.</p><p>But as a course on harness engineering, we want to push it further. Any agent needs a headless mode (along with running it from the terminal), essential context engineering features such as memory, compaction, skills and guardrails such as the permission layer and sandboxes. That&#8217;s essentially harness engineering. So far we&#8217;ve built the agent loop. Now the real harness engineering begins.</p><div class="callout-block" data-callout="true"><p>&#129489;&#8205;&#128187; <span>We encourage you to&nbsp;</span><strong>clone our&nbsp;<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">course repo</a></strong><span>, open your terminal, type </span><strong><span data-color="#38761d" style="color: rgb(56, 118, 29);">decode</span> </strong>and test out the coding agent.</p></div><p>In the <a href="https://www.decodingai.com/p/run-coding-agents-safely">next lesson</a>, we&#8217;ll build the sandbox layer locally via Docker and remotely via Modal.</p><p>Here is the<strong> course roadmap, </strong>lesson by lesson <em>(<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a></em>):</p><ol><li><p><a href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design">Building a Coding Agent From Scratch</a></p></li><li><p><strong>The Bare-Bones Coding Agent Loop</strong> &#8592; <strong>You are here</strong></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p>Or the <strong>video</strong> lecture <strong>supporting</strong> <strong>the</strong> <strong>first two lessons</strong>:</p><div id="youtube2-sJpop1juVBQ" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;sJpop1juVBQ&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/sJpop1juVBQ?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><strong>From your perspective, as we&#8217;ve been using Claude Code, Codex, etc. for general productivity stuff, what makes a general-purpose agent a coding agent?</strong></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/the-coding-agent-loop/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/the-coding-agent-loop/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/the-coding-agent-loop?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/the-coding-agent-loop?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images &amp; Videos</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Building a Coding Agent From Scratch]]></title><description><![CDATA[Designing the harness around the model, from the agent loop to a remote swarm.]]></description><link>https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design</link><guid isPermaLink="false">https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Wed, 22 Jul 2026 11:04:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FPSt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82861d6d-5603-4f6d-b98c-1af4a96d69df_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><em><strong><span data-color="#c02f26" style="color: rgb(192, 47, 38);">Every AI application that wraps an agent is a harness!</span></strong></em></p><p>In LangChain&#8217;s Terminal-Bench experiment, changing only the harness (with the same model) moved a coding agent from ~30th place into the top 5: the harness, not the model, is what makes a coding agent good.</p><p>In the&nbsp;<strong>open-source course</strong>&nbsp;<strong><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Building a Coding Agent From Scratch</a></strong>, you&#8217;ll build that harness from scratch in Python:&nbsp;<strong>Decode</strong>, a complete coding agent that grows lesson by lesson from a bare agent loop into a swarm of remote agents running in parallel in the cloud.</p><p><strong>Why?</strong>&nbsp;You&#8217;ll be able to engineer custom harnesses for your own AI products (the skill behind that leaderboard jump), and you&#8217;ll understand what Claude Code and Codex actually do under the hood, turning you into a power user.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ge05!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1446989,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge05!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 424w, https://substackcdn.com/image/fetch/$s_!ge05!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 848w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1272w, https://substackcdn.com/image/fetch/$s_!ge05!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27ba7d81-6547-41ad-9370-e9df2dd960e1_1200x630.gif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Lessons:</strong></p><ol><li><p><strong>Building a Coding Agent From Scratch &#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course&quot;,&quot;text&quot;:&quot;Full open-source course&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course"><span>Full open-source course</span></a></p><p><em>Special thanks to <strong><a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=workshop&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p></div><h1>Lesson 1: Building a Coding Agent From Scratch</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yVLk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yVLk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yVLk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The model is the smallest part. The machine around it is what you're about to build.&quot;,&quot;title&quot;:&quot;The model is the smallest part. The machine around it is what you're about to build.&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The model is the smallest part. The machine around it is what you're about to build." title="The model is the smallest part. The machine around it is what you're about to build." srcset="https://substackcdn.com/image/fetch/$s_!yVLk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!yVLk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15bedf6a-82c7-467b-a260-9a084c6d2b5a_1376x768.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In a <a href="https://blog.langchain.com/the-anatomy-of-an-agent-harness/">test run by LangChain on Terminal-Bench</a>, changing only the harness (same model throughout) moved a coding agent from roughly 30th place into the top 5. The model isn&#8217;t what makes a coding agent good. The harness is. So that&#8217;s what we&#8217;ll build from scratch. A coding agent harness.</p><p>When I first started digging into coding agents, I couldn&#8217;t tell where the agent ended and the harness began. I wanted past that black box, so in the past months I&#8217;ve researched how the most popular coding agent tools work under the hood: Claude Code (via its leaked source), <a href="https://github.com/anomalyco/opencode">OpenCode</a>, <a href="https://github.com/earendil-works/pi">Pi</a>, and <a href="https://github.com/aider-ai/aider">Aider</a>.</p><p>That harness is the only layer you can actually engineer. And that&#8217;s why I think building your own coding agent harness from scratch is the best way to understand both how to better use coding agents to become a power user and how to build your own custom harnesses for AI agents.</p><p><em>During my research, I&#8217;ve built my own replica: <strong>&#8220;Decode: The Coding Agent&#8221;</strong>. Now, I want to <strong>show you how to build your own.</strong></em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a09O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a09O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!a09O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!a09O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!a09O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a09O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png" width="1456" height="791" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:791,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:211061,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!a09O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!a09O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!a09O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!a09O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc0acc2c8-d4bb-4730-88d1-9fa2db966e6f_1815x986.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Decode: The Coding Agent - Planning</figcaption></figure></div><p>I don&#8217;t mean a simple LLM with some tools in a loop, which is just the good old ReAct pattern. I mean building the whole coding harness from scratch. Build a coding agent once, and you&#8217;re equipped to build a custom agent for any use case.</p><p>The truth is that adding custom business logic to existing open-source harnesses such as <a href="https://github.com/earendil-works/pi">Pi</a>, <a href="https://github.com/langchain-ai/deepagents">DeepAgents</a> by LangChain, or <a href="https://github.com/pydantic/pydantic-ai-harness">Pydantic AI Harness</a> is not that hardcore. But to know what to add based on the internals of these harnesses is extremely important. Those are fundamentals. The secret sauce that still makes AI Engineers valuable.</p><p>In this <strong>8-lesson series</strong>, you&#8217;ll build a complete coding agent called <em>Decode</em> from scratch in Python. It runs as a CLI for interactive use or as a remote headless agent that lets you run a swarm of agents in parallel on a cloud platform like Modal for automation, such as picking up tasks from the backlog or handling PR reviews.</p><p>You&#8217;ll learn how to implement all of that in 3 phases. First, we will build the <strong>agent loop</strong> using Pydantic AI, powered by open-source models on <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>, <a href="https://openrouter.ai/">OpenRouter</a>, or Gemini, leveraging their free credits.</p><p>Then we will build the <strong>harness</strong> around the loop, adding context engineering, sandboxing in Docker and Modal, memory, skills, compaction, subagent support, and more! All the good stuff known as <em>harness engineering</em>.</p><p>Finally, the boring stuff that makes you a senior AI engineer: adding <strong>observability</strong> and building a <strong>custom evaluation harness</strong> similar to <a href="https://github.com/harbor-framework/harbor">Harbor</a> (the framework used to compute Terminal-Bench and DeepSWE, two of the most popular agent benchmarks). During this, we will implement a custom benchmark (because evaluating agents on public benchmarks never aligns with your business goals), agent regression tests via <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, and trace replay via <a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a>. </p><p>Before getting into the implementation, I want to kick off this lesson with the most fun part: <em>the coding agent's system design.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5g74!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5g74!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!5g74!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!5g74!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!5g74!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5g74!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png" width="1456" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:160059,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5g74!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!5g74!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!5g74!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!5g74!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc58beb8-0171-4fe3-a109-c13ddd5f0145_1816x855.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Decode: The Coding Agent - Demos as <strong>.decode/skills</strong> you can run yourself</figcaption></figure></div><p>Let&#8217;s trace the architecture end to end, following one request through every component.</p><h2>The High-Level System Design</h2><p>You pass a coding agent a request &#8212; <em>&#8220;fix the bugs that make the unit tests fail&#8221;</em> &#8212; and it loops: explore the codebase, run the tests, read the feedback, edit the code, repeat. The input is your request, while the repository is the state of the codebase. The output is tested changes done to the repo. Everything in between is the harness.</p><p>We are pretty familiar with this process. <strong>But how does it work?</strong></p><p>At the center sits the headless harness: no interface of its own. It exposes a module that interfaces connect to. At the core, it runs the agent loop every harness shares: the LLM picks an action (a tool call &#8212; run the failing test suite), the tool executes and returns an observation (2 failing tests, expected vs actual), and the loop feeds it back. Everything reads from and writes to the context window (the state of the LLM).</p><p>To highlight that the harness is independent from the LLM, we wanted to implement multiple LLM providers. The loop is powered by an LLM provider module that to support open-source models we implemented it with Modal (for self-hosting) and OpenRouter (for APIs). Also, we added support for Gemini for their free tier. <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a> is the most interesting as it allows us to either host standard open-source models or easily host our own fine-tuned models on top of their serverless infrastructure.</p><p>That cycle lets the agent correct itself: implement the code, run or compile it, read the error, fix it &#8212; or catch the mistake before anything runs, with a Language Server Protocol (LSP) server flagging broken syntax the moment an edit happens. The tighter these feedback loops, the faster the agent converges on working code. The LSP server (we used ty - made by Astral&#8217;s - the guys behind uv and ruff) is the cheapest way to get feedback on code changes.</p><p>Along with the LLM providers and LSP server, the harness contains 4 more essential modules: Memory, Skills, Sandbox, and Permissions. Essential for context engineering and security.</p><p>The context window of the LLM is a budget. The conversation accumulates in the window until it stops fitting or performance degrades. Remember that too much context confuses the model, known as context decay. Every observation the loop feeds back <a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents">spends from the same finite budget</a>. Hence, the harness needs to implement compaction techniques such as summarization, truncation, or just clearing the window.</p><p>How do we interact with the headless harness? It has <em>two core interfaces</em>: interactive mode, a terminal user interface (TUI) connected to a single live session, and remote mode, where an agent runtime (<a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>) runs N headless harnesses in parallel as serverless functions.</p><p>On top of everything, we have the AI evals &amp; observability layer, powered by <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a> and <a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a>, that records every model call and tool call and turns a bad prompt tweak into a failing regression score before your users feel it in production or a signal used to improve the agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Fnzn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Fnzn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Fnzn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156984,&quot;alt&quot;:&quot;Diagram of a coding agent harness: two interfaces (Interactive TUI with steering queue and priority gate; Remote Modal runtime running N headless harnesses via CLI, webhook, or cron) drive one Headless Harness made of a Context Window with compaction, an LLM-to-Tools Agent Loop, and six modules (LLM Providers, Memory, Skills, Sandbox, Permissions, LSP Server). An Evals &amp; Observability layer (benchmarks, regressions, replays via Opik and Kitaru) sits underneath.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Diagram of a coding agent harness: two interfaces (Interactive TUI with steering queue and priority gate; Remote Modal runtime running N headless harnesses via CLI, webhook, or cron) drive one Headless Harness made of a Context Window with compaction, an LLM-to-Tools Agent Loop, and six modules (LLM Providers, Memory, Skills, Sandbox, Permissions, LSP Server). An Evals &amp; Observability layer (benchmarks, regressions, replays via Opik and Kitaru) sits underneath." title="Diagram of a coding agent harness: two interfaces (Interactive TUI with steering queue and priority gate; Remote Modal runtime running N headless harnesses via CLI, webhook, or cron) drive one Headless Harness made of a Context Window with compaction, an LLM-to-Tools Agent Loop, and six modules (LLM Providers, Memory, Skills, Sandbox, Permissions, LSP Server). An Evals &amp; Observability layer (benchmarks, regressions, replays via Opik and Kitaru) sits underneath." srcset="https://substackcdn.com/image/fetch/$s_!Fnzn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!Fnzn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e2e6ee0-1a07-4de8-a3bf-610186bf60e8_1200x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><em>Here is how all the components fit together:</em></p><p>You type the request into the TUI. The input enters the steering queue through the priority gate and into the session&#8217;s context window. The loop sends the window (with the available tools) to the model through the LLM provider. The model answers with an action &#8212; grep for the failing assertion, then edit <code>stats.py</code>. Permissions check whether it can execute the tool, the tool executes inside the Sandbox, and the observation is added back into the context window. The loop repeats until the model stops calling tools. During the loop, events stream back to your terminal in real time via an async generator.</p><p>Next, let&#8217;s zoom into the agent loop, where the agent ends and the harness begins- the boundary that defines this entire series.</p><h2>The Headless Harness &amp; The Agent Loop</h2><p>The agent itself is a Pydantic AI agent. A ~20 line definition that composes the model, the tools, the output type and iterates until the model stops calling them. The snippet below is the distilled version of Decode&#8217;s loop:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from dataclasses import dataclass
from pydantic_ai import Agent, DeferredToolRequests

@dataclass
class AgentDeps:                # the harness state injected into every tool call
    cwd: Path                   # the repo the tools operate on
    emit: EventSink             # streams events to whatever interface is attached
    gate: PermissionGate        # allow / ask / deny, per tool call
    resolve_permission: PermissionResolver  # asks the human when the gate says "ask"

agent = Agent(
    build_model(settings.llm_provider),       # gemini | openrouter | modal
    deps_type=AgentDeps,
    output_type=[str, DeferredToolRequests],   # a turn ends as a final answer (str),
)                                              # or as tool calls paused for approval
register_tools(agent)                          # read, edit, bash, grep, ...

async with agent.iter(prompt, message_history=history) as run:
    async for node in run:                     # model request &#8594; tool calls &#8594; repeat
        stream_events(node)                    # everything else is the harness</code></pre></div><p>Through the <code>AgentDeps</code> dataclass we inject harness related components into the loop. The tools are never aware of the interface: TUI or headless. This is what I like to call &#8220;a practical clean architecture&#8221;, where you are obsessive about separating the serving and infrastructure layers from your core business logic via interfaces and composition.</p><p><code>output_type</code> names the only 2 ways a turn can end: a final answer, or tool calls suspended mid-turn waiting for human input.</p><p>We will go into all the details about the agent loop, explaining how we hook multiple closed-source/open-source models, the tools and other deps into the loop, in the next article.</p><p>These ~20 lines are the <em>entire</em> tool-calling LLM agent. The thing people call &#8220;the agent&#8221; ends here. Everything we build on top of it across 8 lessons is the <strong>coding harness</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IJV9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IJV9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 424w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 848w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 1272w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IJV9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png" width="1400" height="828" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:828,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The boundary: a tiny tool-calling agent inside a much larger harness.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The boundary: a tiny tool-calling agent inside a much larger harness." title="The boundary: a tiny tool-calling agent inside a much larger harness." srcset="https://substackcdn.com/image/fetch/$s_!IJV9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 424w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 848w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 1272w, https://substackcdn.com/image/fetch/$s_!IJV9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0db84995-d395-4854-a4c0-65be5f8915c5_1400x828.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Pydantic AI is a thin layer over the model APIs: typed tool definitions, streaming, structured outputs, with no heavy framework between us and our own logic. What makes this a <em>coding</em> agent is the tools: read and edit files, run bash, search the codebase, manage a task list, fetch the web, ask the user a question, and spawn subagents. Plus, the LLM specializes in coding. Anthropic is well known for continually optimizing their models for coding tasks. That&#8217;s why with every release their models get worse and worse at writing, while better and better at coding.</p><p>Still, almost everyone already uses coding agents such as Claude Code or Codex for completely different use cases (including myself): productivity, content creation, finance, sales, marketing. The line between a coding agent and a general-purpose agent is blurry, as any agent needs to natively interact with your computer. How would a harness specialized in writing look? Other than making the LLM sound better. Which is not the harness!</p><p>On top of the agent loop, we have 6 modules + compaction that transform the agent loop into a headless harness.</p><h3>The Six Modules + Compaction</h3><p><strong>LLM Providers</strong> &#8212; Decode ships with 3: Modal to serve any type of open-source models (pre-configured or your own fine-tuned version), deployed as <strong><a href="https://modal.com/docs/guide/endpoints?source=decodingai&amp;campaign=harnesseng">Modal endpoints</a></strong> &#8212; serverless GPU web endpoints that put the model behind a URL the harness calls like any hosted API, OpenRouter to reach any hosted model behind one API, and Gemini for Google&#8217;s free tier for following along. Also, by implementing three providers we can showcase how to swap the model only with a config change, not a rewrite. The loop should never know which model is powering the harness. Clean architecture, remember?</p><p><strong>Sandbox</strong> &#8212; an agent that runs bash can break things. We wrap the bash and file-I/O tools to execute inside a sandbox (Docker locally, <strong><a href="https://modal.com/docs/guide/sandboxes?source=decodingai&amp;campaign=harnesseng">Modal Sandboxes</a></strong> remotely) instead of on your machine.</p><p><strong>Permissions</strong> &#8212; the permission layer is the most important guardrail: it asks you before running every action, or only the risky ones, depending on the mode. For example, it pauses before a destructive bash command like <code>rm -rf</code> and waits for your approval. This is similar to Claude Code&#8217;s default, edit, and auto modes.</p><p><strong>Memory</strong> &#8212; the iconic AGENTS.md that carries your project instructions plus a MEMORY.md that encodes what the agent learns (e.g. &#8220;run the tests with <code>pytest -x</code>, never the full suite&#8221;). Plain files, deliberately no memory database and no codebase index: the repo is explored dynamically with grep. Just-in-time reads beat a stale heavy index.</p><p><strong>Skills</strong> &#8212; the omnipresent skills feature that encodes reusable workflows loaded only when invoked, so the context window doesn&#8217;t get bloated with all your instructions at once. The repo already ships a set of skills under <code>.decode/skills/</code> that you can try out of the box.</p><p><strong>LSP Server</strong> &#8212; a key component of a coding agent. It keeps an index of all your variables and functions. The loop gets syntax and semantic information about the codebase through 2 channels instead of brute-forcing through it or waiting for the code to run. On demand, the model asks where a symbol is defined, who calls it, what its real contract is, and what&#8217;s broken in a file. The model gets 1 precise <code>file:line</code> answer. After each edit, a fast syntax checker feeds its findings back into the loop. The agent fixes a type error in the same turn, before running/compiling any code. The cheapest feedback loop in the system.</p><p><strong>Compaction</strong> &#8212; not a module but a behavior of the harness itself that helps keep the context window as small as possible. The most iconic strategy is to compact the window once it goes over a threshold, squashing the window&#8217;s old head into a summary + keeping the recent interactions fresh: <code>[summary, *tail]</code>. You can also call this manually via <code>/compact</code> or simply clean the whole context window via <code>/clear</code>.</p><p>That&#8217;s the headless harness. Now, let&#8217;s plug it into the interfaces you use every day.</p><h2>The Interactive Mode</h2><p>The first is the <strong>TUI</strong>: the interactive mode, a terminal interface wired directly to one live session of the headless harness, in memory, in the same process.</p><p>We built it in Python, where <code>prompt_toolkit</code> handles input and <code>Rich</code> handles output of the terminal experience. It&#8217;s append-style, like a conversation log, rather than a full-screen app. Keystrokes go in, and the session&#8217;s event stream comes back in real-time via Python generators: streamed text, tool calls, approval prompts.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GNsc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GNsc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GNsc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png" width="1456" height="791" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:791,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The TUI: an append-style conversation log streamed live from one harness session.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The TUI: an append-style conversation log streamed live from one harness session." title="The TUI: an append-style conversation log streamed live from one harness session." srcset="https://substackcdn.com/image/fetch/$s_!GNsc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 424w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 848w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 1272w, https://substackcdn.com/image/fetch/$s_!GNsc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46cc8b77-6896-405b-ad08-feac403ea3b7_1815x986.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The TUI that we will build</em></figcaption></figure></div><p><strong>Why Python?</strong> To be honest, we picked it mostly for teaching purposes.</p><p>From my recent poll, I realized that all my audience knows Python. So this makes it accessible to you. But if I were to ship this for real, I&#8217;d reach for TypeScript (the language claude-code, OpenCode, and Pi chose) or Go, which compiles to one tidy binary. Still, Aider proves Python can carry a serious coding agent.</p><p>And in this series we will focus on the &#8220;why&#8221;, the design and architecture decisions. Thus, the programming language is not that important and you can easily swap it out for another language.</p><h3>The steering queue</h3><p>What happens when you send a new command and the agent is already mid-task?</p><p>Injecting it the moment it&#8217;s sent would corrupt a tool call already in flight. Ignoring it makes the agent unsteerable. Every serious harness hits this: Pi drains steering messages mid-turn but follow-ups only at the turn boundary, and claude-code ranks queued input so user messages never starve.</p><p>Decode&#8217;s answer is the <strong>steering queue + priority gate</strong>. Input is buffered the instant it arrives into the steering queue and injected only at a safe boundary: before the next model call, never mid-tool-call. The gate decides how to process the messages from the queue: steer now, answer later, or abort.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_MJf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_MJf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 424w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 848w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 1272w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_MJf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png" width="1456" height="510" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:510,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Mid-turn input: buffered in the steering queue, injected only at a safe boundary.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Mid-turn input: buffered in the steering queue, injected only at a safe boundary." title="Mid-turn input: buffered in the steering queue, injected only at a safe boundary." srcset="https://substackcdn.com/image/fetch/$s_!_MJf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 424w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 848w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 1272w, https://substackcdn.com/image/fetch/$s_!_MJf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f58d9ed-d1d9-4550-a8ae-bb08f071e682_2100x735.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Steering without corruption</em></figcaption></figure></div><p>The steering queue can be a simple in-memory FIFO queue. No need for a complex queue infrastructure like RabbitMQ.</p><h3>Try it out</h3><p>You can already clone the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">Decode repository</a> and try it out for yourself.</p><p>The repo has all the <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code">setup instructions</a>. There are $0 <em>costs</em> <em>to</em> <em>try</em> <em>it</em> <em>out</em>. <em>We</em> <em>recommend</em> <em>starting</em> <em>with</em> <em>Modal</em>, <em>which</em> <em>offers $</em>30 in free credit every month.</p><p>The experience is similar to what you already know: you run <code>decode</code> in any repo and the TUI opens as a fresh session.</p><p>We bundled together a few demo&#8217;s as skills under <code>.decode/skills/</code>, so you can easily try out the coding agent with 0 friction:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TsnR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TsnR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TsnR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png" width="1456" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The demo skills bundled under .decode/skills/, listed inside the TUI.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The demo skills bundled under .decode/skills/, listed inside the TUI." title="The demo skills bundled under .decode/skills/, listed inside the TUI." srcset="https://substackcdn.com/image/fetch/$s_!TsnR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 424w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 848w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 1272w, https://substackcdn.com/image/fetch/$s_!TsnR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92c62af5-78c3-4009-99f3-759c7beba3ed_1816x855.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The demo skills bundled under </em><code>.decode/skills/</code><em>, listed inside the TUI.</em></figcaption></figure></div><p>Such as creating a snake game:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!irfj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!irfj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 424w, https://substackcdn.com/image/fetch/$s_!irfj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 848w, https://substackcdn.com/image/fetch/$s_!irfj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 1272w, https://substackcdn.com/image/fetch/$s_!irfj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!irfj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png" width="854" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:854,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The snake game skill, built and running from a single prompt.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The snake game skill, built and running from a single prompt." title="The snake game skill, built and running from a single prompt." srcset="https://substackcdn.com/image/fetch/$s_!irfj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 424w, https://substackcdn.com/image/fetch/$s_!irfj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 848w, https://substackcdn.com/image/fetch/$s_!irfj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 1272w, https://substackcdn.com/image/fetch/$s_!irfj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa73cc86c-8e1c-4c1c-ac42-7299fb9cede9_854x819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Fetching data from a GitHub repo and rendering a web page:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4v2q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4v2q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 424w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 848w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 1272w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4v2q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png" width="1456" height="1190" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1190,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;GitHub repo data fetched by the agent and rendered into a web page.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="GitHub repo data fetched by the agent and rendered into a web page." title="GitHub repo data fetched by the agent and rendered into a web page." srcset="https://substackcdn.com/image/fetch/$s_!4v2q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 424w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 848w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 1272w, https://substackcdn.com/image/fetch/$s_!4v2q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff9fe14a6-8adb-4c85-ac6f-8aafbc64ae9e_2328x1902.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Or something more complex like scraping data from the internet, extracting a knowledge graph of entities and topics and rendering them into a cool visualization:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c6fZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c6fZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 424w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 848w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 1272w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c6fZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png" width="1456" height="847" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:847,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A knowledge graph of entities and topics, scraped from the web and rendered into a visualization.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A knowledge graph of entities and topics, scraped from the web and rendered into a visualization." title="A knowledge graph of entities and topics, scraped from the web and rendered into a visualization." srcset="https://substackcdn.com/image/fetch/$s_!c6fZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 424w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 848w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 1272w, https://substackcdn.com/image/fetch/$s_!c6fZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0abc6ad-61e0-4594-84c2-2f289327f8a1_3324x1934.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>What if we want to run the agent remotely?</p><h2>The Remote Mode</h2><p>In the remote mode, we run the headless harness on <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal serverless functions</a>. Now you can easily run Decode in the background without depending on your laptop and fully automate your agentic infrastructure. </p><p>You can trigger it from your CI/CD pipeline or Slack messages. A standard use case is to use cron jobs to pull tickets from Linear or Notion, launch one agent per ticket in parallel, and get notified when the implementation is done with a link to the ticket's PR.</p><p>Or even launch 3-5 implementations of the same ticket in parallel and let a frontier foundation model judge the candidates and rank them for you.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!65Iw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!65Iw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 424w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 848w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1272w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png" width="1456" height="625" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:625,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!65Iw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 424w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 848w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1272w, https://substackcdn.com/image/fetch/$s_!65Iw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F08551dc2-edcc-45b8-b163-12e3b746c669_3048x1308.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The headless harness is deployed in Modal, where the tools run in remote sandboxes and are triggered by the CLI, webhooks, or cron jobs.</figcaption></figure></div><p>As in the image above, we will deploy decode as serverless functions on <a href="https://modal.com/?source=decodingai&amp;campaign=harnesseng">Modal</a>, triggered via the CLI, webhooks, or cron jobs. The pros of this design are that you pay only for what you use, avoiding the need to run a server 24/7. Plus, because the LLM runs on a different inference endpoint and the tools execute within the sandbox, we can keep the application server extremely light.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9BWK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9BWK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 424w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 848w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1272w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png" width="1200" height="563" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:563,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Remote mode diagram: a Headless Harness with its Agent Loop runs on Modal, driven by a CLI, executing tool calls in an optional Sandbox, and triggered by a Cron job pulling nightly feature tasks from Linear or a Webhook pushing user requests from Slack.&quot;,&quot;title&quot;:&quot;The headless harness in the middle &#8212; a CLI, a cron and a webhook all start the same loop; the sandbox is optional.&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Remote mode diagram: a Headless Harness with its Agent Loop runs on Modal, driven by a CLI, executing tool calls in an optional Sandbox, and triggered by a Cron job pulling nightly feature tasks from Linear or a Webhook pushing user requests from Slack." title="The headless harness in the middle &#8212; a CLI, a cron and a webhook all start the same loop; the sandbox is optional." srcset="https://substackcdn.com/image/fetch/$s_!9BWK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 424w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 848w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1272w, https://substackcdn.com/image/fetch/$s_!9BWK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ff2b126-fc16-4e63-a738-1f713823a54c_1200x563.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The runtime split</figcaption></figure></div><p>There are two core infrastructure components:</p><ul><li><p>The <strong>execution layer</strong>, where the headless harness runs, is hosted on Modal.</p></li><li><p>The <strong>sandbox layer</strong>, where filesystem tools (read, write, edit, bash) execute, is deployed as Modal remote sandboxes. This is optional. If not configured, the filesystem tools run on the execution layer. </p></li></ul><p>If a tool isn't flagged to run within the sandbox, it executes directly within the harness, which is fine for planning tools.</p><h3>Try it out</h3><p>You can run the remote version by going to our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course">course repo</a> and setting up Modal, following our <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-running-the-code">Modal and sandboxing tutorials</a> (takes ~5-10 mins). Then everything is as easy as running:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">uv run decode remote deploy
uv run decode remote run "&lt;task&gt;" --repo &lt;url&gt; --sandbox-mode modal</code></pre></div><p><span>One question decides whether this engineering is worth it:&nbsp;</span><em><span>&#8220;Can you prove the agent works for my custom use case?&#8221;</span></em></p><h2>The Observability and AI Evals Layer</h2><p>The evals layer answers 3 questions, each with its own mechanism.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-lsB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-lsB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 424w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 848w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 1272w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-lsB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png" width="1200" height="395" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:395,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:80567,&quot;alt&quot;:&quot;Three-stage evals timeline: Internal Benchmark (does it work?), Regression Tests before you ship (does it still work?), and Production Evals after you ship (does it keep working?), all sitting on an AI Evals &amp; Observability layer powered by Opik and Kitaru.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Three-stage evals timeline: Internal Benchmark (does it work?), Regression Tests before you ship (does it still work?), and Production Evals after you ship (does it keep working?), all sitting on an AI Evals &amp; Observability layer powered by Opik and Kitaru." title="Three-stage evals timeline: Internal Benchmark (does it work?), Regression Tests before you ship (does it still work?), and Production Evals after you ship (does it keep working?), all sitting on an AI Evals &amp; Observability layer powered by Opik and Kitaru." srcset="https://substackcdn.com/image/fetch/$s_!-lsB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 424w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 848w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 1272w, https://substackcdn.com/image/fetch/$s_!-lsB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc167e2ca-f4e7-4d34-8595-b3865772f699_1200x395.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The evals layer answers three different questions</figcaption></figure></div><p>Internal <strong>benchmarks</strong> answer: <em>&#8220;Does it work?&#8221;</em> These are the metrics you try to beat with every new feature. You can use public benchmarks such as <a href="https://github.com/harbor-framework/terminal-bench">Terminal-Bench</a> to compare your agent&#8217;s performance against others. But the real deal is to build a custom benchmark suite from your own tasks that optimizes for your specific use case.</p><p>Each case is a task instruction, a fresh sandboxed environment, and a hidden oracle test that decides pass or fail. One example case is <em>&#8220;add a </em><code>--json</code><em> flag to </em><code>decode run</code><em>&#8220;</em>, with a hidden pytest asserting the output parses. It&#8217;s the same pattern <a href="https://github.com/swe-bench/SWE-bench">SWE-bench</a> applies to real GitHub issues and <a href="https://github.com/harbor-framework/terminal-bench">Terminal-Bench</a> applies to terminal tasks.</p><p>Your own tasks predict your agent&#8217;s usefulness better than any leaderboard.</p><p><strong>Regression</strong> <strong>tests</strong> answer: &#8220;D<em>oes it still work?&#8221;</em> Every new feature re-runs a regression suite and compares scores against the baseline, so a prompt tweak or a new tool can&#8217;t silently make the agent worse.</p><p><strong>Production evals:</strong> <em>&#8220;Does it keep working?&#8221;</em> Every session is traced with <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a>, Comet&#8217;s open-source LLM observability platform: each model call, tool call, and token count is a trace, while the conversation is logged as a thread. Live scoring tracks quality in production, where you run a bunch of AI eval metrics on sampled traces to detect unwanted behavior and create warnings or alarms.</p><p>To implement all three cases, plus to monitor and store all our traces, we will use <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a></strong> as our evaluation harness and observability platform. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AKa3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AKa3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 424w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 848w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 1272w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AKa3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png" width="1456" height="858" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:858,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Opik threads &#8212; every session logged as a thread, every model and tool call as a trace.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Opik threads &#8212; every session logged as a thread, every model and tool call as a trace." title="Opik threads &#8212; every session logged as a thread, every model and tool call as a trace." srcset="https://substackcdn.com/image/fetch/$s_!AKa3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 424w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 848w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 1272w, https://substackcdn.com/image/fetch/$s_!AKa3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40da9e96-3e12-46f9-97eb-4651da6e3e46_3262x1922.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Capturing all the traces within <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik</a></strong></figcaption></figure></div><h2>AI Evals on Steroids</h2><p>With tools like Opik, you can only evaluate existing traces, but you often want to answer questions like: <em>&#8220;What would have happened if I used a different model or reasoning level?&#8221;</em></p><p>That&#8217;s why a popular strategy gaining traction is <strong>replays, </strong>via tools like<strong> <a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a></strong>. You take a recorded trace, change one thing (the model, the system prompt, a parameter), and re-run the whole session from the top, then compare it against the unchanged run as your baseline.</p><p>The tools don&#8217;t execute again by default: when the replayed model makes a tool call that matches one from the original session, it gets the recorded output. When it calls something new, the policy you pick decides what happens: return an error so the model has to adapt, or run the tool for real. This way, you can isolate the impact of a single change on the model&#8217;s decisions, and replays cost no sandbox time.</p><p>Applying this strategy can drastically speed up exploration when optimizing your coding agent, whether you're trying to squeeze better scores on your benchmarks or find edge cases in your regression tests. You can also run error analysis on your results to detect and fix the most frequent and/or important errors. </p><p><strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a></strong> works in parallel with Opik. You can import all your traces from Opik or plug in a Kitaru adapter on top of your agent loop to collect them.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Hx4h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Hx4h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Hx4h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png" width="1456" height="640" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:640,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:423800,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Hx4h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 424w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 848w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 1272w, https://substackcdn.com/image/fetch/$s_!Hx4h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bf6e38-1da5-4cec-a6bd-73ad74e8262c_3344x1470.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Running replays within <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru</a></strong></figcaption></figure></div><h2>Next Steps</h2><p>You&#8217;ve seen a bird&#8217;s-eye view of what a coding agent looks like: one headless core, a small tool-calling agent inside a much larger harness, 2 modes, and an evals layer that measures performance.</p><div class="callout-block" data-callout="true"><p><span>&#129489;&#8205;&#128187; For </span><strong><span>the best results</span></strong><span> out of this series, </span>clone the<strong> <a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/tree/main">course repo</a></strong><span>, follow the </span><a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course/tree/main#-course-outline">installation steps</a>,<strong> </strong>and run it while you follow along.</p></div><p>In the <a href="https://www.decodingai.com/p/the-coding-agent-loop">next lesson</a>, we get into the code and start building the agent loop hooked into the TUI.</p><p>Here is the<strong> course roadmap, </strong>lesson by lesson <em>(<a href="https://github.com/decodingai-magazine/building-a-coding-agent-from-scratch-course#-course-outline">see all in GitHub</a></em>):</p><ol><li><p><strong>Building a Coding Agent From Scratch &#8592; </strong><em><strong>you are here</strong></em></p></li><li><p><a href="https://www.decodingai.com/p/the-coding-agent-loop">The Bare-Bones Coding Agent Loop</a></p></li><li><p><a href="https://www.decodingai.com/p/run-coding-agents-safely">From a Raw Shell to a Sandboxed Coding Agent</a></p></li><li><p><a href="https://www.decodingai.com/p/context-engineering-for-coding-agents">Context Engineering for Coding Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/subagents-are-context-engineering">Subagents Are Context Engineering</a></p></li><li><p><a href="https://www.decodingai.com/p/coding-agents-in-remote-headless">Swarm of Remote Agents</a></p></li><li><p><a href="https://www.decodingai.com/p/evaluate-ai-agents-benchmarks-regression-tests">Agent Evals 101</a></p></li><li><p><a href="https://www.decodingai.com/p/transform-agent-traces-into-regression-cases">Turn Your Agent&#8217;s Failures Into a Regression Suite</a></p></li></ol><p>Or watch the <strong>video lecture </strong>that supports<strong> the first two lessons:</strong></p><div id="youtube2-sJpop1juVBQ" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;sJpop1juVBQ&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/sJpop1juVBQ?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>Which part of your daily coding agent is still a black box to you: the loop, the sandbox, the memory, or something else?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/building-a-coding-agent-from-scratch-system-design?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <strong><a href="https://modal.com?source=decodingai&amp;campaign=harnesseng">Modal</a></strong>, <strong><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&amp;utm_content=coding_agent_course">Opik (by Comet)</a></strong>, and <strong><a href="https://www.zenml.io/product/kitaru?utm_source=decodingai&amp;utm_medium=referral&amp;utm_campaign=coding-agent-course&amp;utm_content=brand">Kitaru (by ZenML)</a></strong> for sponsoring this open-source course and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uq-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69533,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/207400663?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uq-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 424w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 848w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Uq-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98999460-8389-40b0-9dda-73f934bbf55a_1200x400.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Agent Memory From Scratch]]></title><description><![CDATA[Ingest, query, and serve a unified memory from a single database.]]></description><link>https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch</link><guid isPermaLink="false">https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 14 Jul 2026 05:01:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Cr9k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Cr9k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cr9k!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cr9k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Many sources. One record. That is what a unified memory buys you.Many sources. One record. That is what a unified memory buys you.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Many sources. One record. That is what a unified memory buys you.Many sources. One record. That is what a unified memory buys you." title="Many sources. One record. That is what a unified memory buys you.Many sources. One record. That is what a unified memory buys you." srcset="https://substackcdn.com/image/fetch/$s_!Cr9k!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!Cr9k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8b3401e-0a72-4e13-ba67-9a2863a387a2_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Agent memory is one of the hottest problems in AI engineering right now, with Graphiti, mem0, HydraDB, and cognee all racing to solve it. A race this crowded means one thing: nobody has cracked it yet.</p><p>But if you&#8217;re thinking of jumping straight into an agent memory tool without understanding how it works under the hood, read this first.</p><blockquote><p>Here is what happened in one of my tests: LangChain&#8217;s <code>MongoDBGraphStore</code> gave me a knowledge graph (KG) in 10 minutes, and from 5 documents it invented 17 node types and 34 relationship types, where <code>part_of</code>, <code>Part Of</code>, and <code>part of</code> were three different ways to express the same relationship.</p></blockquote><p>That&#8217;s why it&#8217;s incredibly important to <strong>understand how the memory layer works under the hood</strong>, so you know its limitations, how to properly configure it for your data, and how to plug it into your agent.</p><p>Or even decide if <strong>you need a unified memory at all, and if so, which tool to use.</strong></p><p>Claude Code comes with a built-in memory layer powered by files. Is this enough for you or not?</p><p>Then, if you move to a more powerful solution, should you use a vector database, a graph database, or a combination of both? Do you need temporality or versioning?</p><p>And ultimately, how should you serve your memory layer to your agent? Through an MCP server, a CLI, or plain skills?</p><p>The reality is that there is no blueprint on how to build your own unified memory layer. Too many choices, too many trade-offs.</p><p>But that&#8217;s why I want to show you how to build a unified agent memory from scratch, in the most complicated way possible: via knowledge graphs (KGs). Plus all the other moving pieces: ingestion, querying, and serving.</p><p><strong>Why?</strong> Because all the popular vendors (cognee, Graphiti, Neo4j&#8217;s agent memory, etc.) go in this direction. Plus, if you know how this works, it will be incredibly easy for you to build simpler solutions.</p><p>So, I am not saying that KGs are always the way to go. They are not. But they are definitely something you need to understand. At least to know when to stay away from them.</p><p>Let&#8217;s go!</p><h2>A Session With a Unified Memory</h2><p>First, here is what I expect a unified memory plugged into a harness to do.</p><p>I open Claude Code and ask what I need to do today. The memory already knows: building a coding agent for my next open source project.</p><p>I ask it to gather everything relevant I have on building a coding agent: Obsidian notes, Readwise highlights, starred repos, all ingested long ago. Then to build an LLM wiki on top of that as my agent memory while I implement the plan.</p><p>When I&#8217;m done, the conversation is ingested too, so the next session already knows all my decisions around the project.</p><p>Nothing in that session lived in the harness. Claude Code was just the interface.</p><p>So how do I implement a unified memory that supports this? Let&#8217;s kick off with the architecture.</p><h2>The Architecture, End to End</h2><p>Sources in, subgraphs out. In between sit 4 pieces: an ontology, a write path, one collection, and a serving layer.</p><p>The whole database layer is powered by <a href="https://www.mongodb.com/">MongoDB</a>: a document warehouse plus a knowledge-graph store doing text, vector, and graph search in one collection. Because we use a single database, lineage is free: nodes hold references to their source documents, not copies from a separate source. This works incredibly well at 2-3 hops at query time.</p><p>OG databases such as MongoDB scale really well up to millions of documents via sharding and replicas.</p><p>Writes are 2 durable pipelines. A data pipeline normalizes each source into the warehouse. A memory pipeline cleans, chunks, extracts, normalizes, embeds, and writes the knowledge-graph objects. Both pipelines are powered by an orchestrator, such as Prefect or DBOS, to serve them, scale them, and make them durable.</p><p>On the read side, we offer multiple ways to interact with the unified memory: standard graph search encoded directly into the tool, agentic search where the agent writes its own MongoDB query, and a deep-search primitive that creates an on-demand LLM wiki for exploring larger subgraphs via progressive disclosure. Reads never touch the orchestrator, as they need to be fast and don&#8217;t benefit from the orchestrator&#8217;s durability or scheduling features.</p><p>The memory is reachable only through a FastMCP server exposing agent-shaped primitives (query, deep-search, ingest), never raw database operations. The MCP server should never be an API wrapper, but directly expose business logic to the harness. A hook fires the conversation ingestion as the session runs, so what the agent learns flows back into the memory &#8212; a process known as &#8220;continual learning.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qby_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qby_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 424w, https://substackcdn.com/image/fetch/$s_!qby_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 848w, https://substackcdn.com/image/fetch/$s_!qby_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 1272w, https://substackcdn.com/image/fetch/$s_!qby_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qby_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png" width="600" height="600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:600,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The full dataflow &#8212; data pipeline, memory pipeline, one MongoDB engine, the MCP server, and the harness with its skills.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The full dataflow &#8212; data pipeline, memory pipeline, one MongoDB engine, the MCP server, and the harness with its skills." title="The full dataflow &#8212; data pipeline, memory pipeline, one MongoDB engine, the MCP server, and the harness with its skills." srcset="https://substackcdn.com/image/fetch/$s_!qby_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 424w, https://substackcdn.com/image/fetch/$s_!qby_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 848w, https://substackcdn.com/image/fetch/$s_!qby_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 1272w, https://substackcdn.com/image/fetch/$s_!qby_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ba4d2e-41d4-4847-b2ce-f95abe5ff76f_600x600.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The most interesting part is not the database, the ingestion, or the query logic, but the ontology that makes everything possible.</p><h2>The Ontology Is the Contract</h2><p>An ontology is a contract between the writer and the reader. The LLM extracts against it. The query layer reads against it. Define it once as Pydantic, serialize with <code>model_json_schema()</code>, and dump that JSON into both writing and reading system prompts. 1 artifact, 2 consumers, no drift.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k41v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k41v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 424w, https://substackcdn.com/image/fetch/$s_!k41v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 848w, https://substackcdn.com/image/fetch/$s_!k41v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 1272w, https://substackcdn.com/image/fetch/$s_!k41v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k41v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png" width="1200" height="1006" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1006,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The unified memory's three layers, with the POLE+O ontology at the core of the long-term graph.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The unified memory's three layers, with the POLE+O ontology at the core of the long-term graph." title="The unified memory's three layers, with the POLE+O ontology at the core of the long-term graph." srcset="https://substackcdn.com/image/fetch/$s_!k41v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 424w, https://substackcdn.com/image/fetch/$s_!k41v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 848w, https://substackcdn.com/image/fetch/$s_!k41v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 1272w, https://substackcdn.com/image/fetch/$s_!k41v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0df98727-adf0-400d-ae27-3e6dd3cd5177_1200x1006.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>One memory, three layers</em></figcaption></figure></div><p>The ontology defines what the knowledge graphs look like. All the KG instances are extracted by passing the input data and the ontology schema to an LLM.</p><p>The memory is 3 layers. The long-term layer is the knowledge graph: the POLE+O entities plus <code>preference</code> and <code>fact</code>. A short-term layer holds the dialogue as <code>conversation</code> and <code>session</code> nodes. A reasoning layer records the agent&#8217;s work as <code>agent</code>, <code>tool_call</code>, and <code>memory</code> nodes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iXbI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iXbI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iXbI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The ontology as a contract &#8212; data plus the POLE+O ontology go into extraction, and knowledge-graph instances come out.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The ontology as a contract &#8212; data plus the POLE+O ontology go into extraction, and knowledge-graph instances come out." title="The ontology as a contract &#8212; data plus the POLE+O ontology go into extraction, and knowledge-graph instances come out." srcset="https://substackcdn.com/image/fetch/$s_!iXbI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!iXbI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F923ca4d3-e1fc-44d4-bdc3-c1fae8391130_1200x630.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The ontology is the contract the extractor reads. The same POLE+O nouns, preferences, and facts on the left; the graph they produce on the right.</em></figcaption></figure></div><p>One powerful ontology design is based on the 5 POLE+O nouns from law-enforcement analysis: Person, Object, Location, Event, Organization, which Neo4j Labs writes up as the <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">POLE+O data model</a>. Each noun carries an optional subtype used to further refine the ontology within a specific domain. For gaming, this can look like:</p><ul><li><p>Person: Player, Character</p></li><li><p>Object: Item, Quest</p></li><li><p>Event: Raid, Battle</p></li></ul><p>Because the agent memory is often used for a personal assistant, you also need to plug <code>preference</code> and <code>fact</code> nodes into the ontology. A <strong>fact</strong> is an atomic subject-predicate-object triplet, an island no edge may touch, reachable only by similarity. A <strong>preference</strong> is the personalization layer with typed slots.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">nodes: person &#183; organization &#183; location &#183; event &#183; object
       preference &#183; fact
edges: related_to, with semantic_type &#8712; {
         knows, member_of, employed_by,
         owns, uses, located_at, resides_at,
         alias_of, has_task, ... 
       }</code></pre></div><p>Now, on top of the KG instances extracted by the LLM, we can also have structured nodes that are directly inferred via code.</p><p>Such as:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">nodes: document &#183; chunk
edges: part_of &#183; next &#183; mentions &#183; referenced &#183; has &#183; same_as &#183; superseded_by</code></pre></div><p>There is a lot more to talk about ontologies. I have a <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">full article</a> just on this.</p><p>With the contract fixed, let&#8217;s see how we can ingest KG objects into the unified memory based on the ontology schema.</p><h2>The Write Path</h2><p>There are 7 stages in one direction. Chunk the document (512-token chunks, 64 overlap). Extract nodes and edges with an LLM. Validate. Resolve names. Embed. Deduplicate. Upsert into the MongoDB unified memory.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vN7D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vN7D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 424w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 848w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 1272w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vN7D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png" width="1200" height="1009" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1009,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The extraction pipeline feeding the per-entity normalization algorithm &#8212; resolution, then deduplication, with the score thresholds that govern each.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The extraction pipeline feeding the per-entity normalization algorithm &#8212; resolution, then deduplication, with the score thresholds that govern each." title="The extraction pipeline feeding the per-entity normalization algorithm &#8212; resolution, then deduplication, with the score thresholds that govern each." srcset="https://substackcdn.com/image/fetch/$s_!vN7D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 424w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 848w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 1272w, https://substackcdn.com/image/fetch/$s_!vN7D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6298cf69-c546-42e4-8702-f0f5347ddf9b_1200x1009.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The write path. Deduplication &#8212; the &#8805;0.95 merge / &#8805;0.85 flag / else new-node branch</em></figcaption></figure></div><p>During the LLM extraction, we pass in a chunk and we receive a JSON response with nodes and edges, the same shape Neo4j Labs lands on in <a href="https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/">How Entity Extraction Works</a>.</p><p>The model sees one chunk and nothing else. It receives no IDs and no prior state. It returns JSON. Every edge endpoint points to a node&#8217;s <code>name</code> in the same record. This allows us to scale the extraction pipeline through batching to process large documents of 1,000,000+ units.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Qssu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Qssu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 424w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 848w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 1272w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Qssu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png" width="1456" height="1398" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/df5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1398,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!Qssu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 424w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 848w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 1272w, https://substackcdn.com/image/fetch/$s_!Qssu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf5826f4-ab01-4d78-b2a8-8e562f1e38fe_2120x2035.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Validation is done via Pydantic. We load the JSON response into a Pydantic model and validate it against the schema.</p><p>Name resolution only checks whether two canonical names match. It&#8217;s done purely on the name and its aliases: alias, exact, fuzzy 0.85, semantic 0.80, filtered by type.</p><p>But there is a next step, where we actually check if an entity is the same instance as another that already exists in the graph.</p><p>Deduplication runs on embeddings computed on the whole node content: &#8805;0.95 cosine merges, &#8804;0.85 makes a new node, and the gap writes a <code>same_as</code> edge for a human to judge.</p><p>So why two steps?</p><p>Name resolution simply helps us group entities by their canonical name. For example, &#8220;Demis Hassabis&#8221; and &#8220;Demis Hassabis, CEO&#8221; would both be resolved to &#8220;Demis Hassabis&#8221;. Or &#8220;Apple&#8221; and &#8220;Apple Inc.&#8221; would both be resolved to &#8220;Apple&#8221;. Super powerful for analytics and human curation.</p><p>Deduplication is the sensitive one &#8212; it decides what actually merges. It shouldn&#8217;t flag &#8220;Apple&#8221; and &#8220;Apple Inc.&#8221; as duplicates, as they are different entities with different meanings.</p><p>A wrong merge is the only unrecoverable mistake. That&#8217;s why, when the similarity score has low confidence, between 0.85 and 0.95, we don&#8217;t merge the nodes automatically, as the operation can be irreversible.</p><p>I break the full algorithm down in <a href="https://www.decodingai.com/p/keep-knowledge-graph-clean">Keep Your Knowledge Graph Clean</a>.</p><p>Which leaves the question that decides your RAM bill: once the triplets are extracted, how do we store them in the unified memory?</p><h2>Append-Only Logs vs. a Single Knowledge Graph Collection</h2><p>There are 3 designs, and the winner? Well... It depends... As always.</p><p>An <strong>append-only log plus a materialized view</strong> buys versioning and soft-delete for free, but you pay for it. <strong>Nested relationships</strong> duplicate edges and make them awkward to query. <strong>Separate edge docs</strong> give queryable edges, no duplication, and the cheapest footprint, at the cost of built-in temporal history and versioning.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pc0N!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pc0N!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 424w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 848w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 1272w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pc0N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png" width="1200" height="934" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:934,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Three ways to store the same graph in MongoDB, and what each one costs you.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Three ways to store the same graph in MongoDB, and what each one costs you." title="Three ways to store the same graph in MongoDB, and what each one costs you." srcset="https://substackcdn.com/image/fetch/$s_!pc0N!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 424w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 848w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 1272w, https://substackcdn.com/image/fetch/$s_!pc0N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab164d43-00b7-4a1c-83cb-8457cb5cf35d_1200x934.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Append-only log, nested relationships, or edges as first-class documents.</em></figcaption></figure></div><p>Because the graph is a projection of the append-only log, a bad extraction is fixed by invalidating its event. You can change the materialization logic and replay it without re-extracting a single source. Also, full-graph temporality belongs to the log alone.</p><p>The log&#8217;s real cost: a vector index is at least as large as the data it covers. Indexing both the log and the view inflates ~10 GB of data toward ~40 GB of RAM. Index only the view, leave the log cold on disk, and it collapses back toward ~10 GB. But the idea is that adding an append-only log brings a lot of engineering effort you then have to maintain.</p><p>So think three times before you sign up for it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2XrE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2XrE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 424w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 848w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 1272w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2XrE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png" width="1200" height="1031" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1031,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The two data models behind the log design &#8212; the append-only immutable log and the materialized view it projects into.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The two data models behind the log design &#8212; the append-only immutable log and the materialized view it projects into." title="The two data models behind the log design &#8212; the append-only immutable log and the materialized view it projects into." srcset="https://substackcdn.com/image/fetch/$s_!2XrE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 424w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 848w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 1272w, https://substackcdn.com/image/fetch/$s_!2XrE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98a7e08c-bd36-4811-9dc2-446e780ace5f_1200x1031.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The view is a projection of the log &#8212; dedup is one aggregation that squashes events by entity ID (an early run: 244 log entries &#8594; 70 nodes + 104 edges). Roadmap, not shipped; the build writes separate edge docs instead.</em></figcaption></figure></div><p>At query time, the agents see the materialized view, not the log itself. Given the RAM cost, reach for the log only when versioning or the time dimension is core to your business logic. Otherwise, keep it simple and stick to a single knowledge graph collection.</p><p>Within the data model, Node IDs are <code>{user_id}:{type}:{name}</code>. Edge IDs are <code>{source}|{type}|{target}</code>. Because the key is content-derived, every write is idempotent.</p><p>The reality? You can get temporality even without a dedicated append-only log. Preferences and facts carry <code>valid_from</code> / <code>valid_until</code>, and a superseding preference writes a <code>superseded_by</code> edge.</p><h2>Three Ways to Read the Memory</h2><p>The 3 retrieval methods below are the serving layer&#8217;s search primitives, the tools the MCP server exposes to the agent.</p><p><strong>Graph search</strong> is the default retrieval, baked into a single function. It runs <code>$vectorSearch</code> and <code>$text</code> in parallel over the KG collection. Fuse the <em>ranks</em> with <a href="https://cormack.uwaterloo.ca/cormacksigir09-rrf.pdf">Reciprocal Rank Fusion (RRF)</a>. Keep the fused top 10 as seed nodes, then expand with a bidirectional <code>$graphLookup</code> at 2 hops by default. That multi-hop step is the entire difference between RAG and GraphRAG.</p><p><strong>Deep search</strong> widens the walk to 3 hops and persists the result to disk as a memory wiki the agent can access via progressive disclosure. The LLM wiki is a mini-graph of its own: you keep the (entity, relationship, entity) triplets by cross-referencing files, where each file is an entity. You can see it as a local cache that is either discarded between sessions or kept in sync with the KG collection.</p><p><strong>NL query</strong> is agentic search that lets the LLM write its own MongoDB queries based on the ontology. Here you have to validate that the query is syntactically correct, and especially guard it against harmful intents such as deleting or modifying data. It&#8217;s safer to use this mode purely for read operations.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LJc3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LJc3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 424w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 848w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LJc3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png" width="1245" height="1036" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1036,&quot;width&quot;:1245,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The three retrieval methods &#8212; graph search, deep search, and NL query &#8212; plugged into the agent through the MCP server.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The three retrieval methods &#8212; graph search, deep search, and NL query &#8212; plugged into the agent through the MCP server." title="The three retrieval methods &#8212; graph search, deep search, and NL query &#8212; plugged into the agent through the MCP server." srcset="https://substackcdn.com/image/fetch/$s_!LJc3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 424w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 848w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!LJc3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cf6f9b0-9519-4135-b923-c88bd051390d_1245x1036.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Three ways in: graph search fuses then walks one hop; deep search walks three hops and writes a wiki; NL query lets the LLM author the aggregation against the ontology.</em></figcaption></figure></div><p>RRF replaces a reranker (a second model that re-scores the retriever&#8217;s top candidates) you don&#8217;t need yet. It is 20 lines of Python, needs no model, and runs in microseconds. Reach for a cross-encoder (a heavier model that compares the query against each candidate) when you search millions of heterogeneous documents.</p><p><strong>When do you need to switch from a single database (MongoDB) to a graph database (Neo4j)?</strong> Past 4 hops, past ~100M to 1B vectors, when graphs <em>are</em> your business logic, or purely to visualize them: that is where you leave MongoDB for Neo4j. It&#8217;s common to use a single database in production (MongoDB) and a graph database as an internal tool for data exploration and analysis (Neo4j). This is a powerful combo, because for an internal tool you don&#8217;t care that much about 99.99% SLAs, while you can fully leverage Neo4j&#8217;s Cypher query language to explore and analyze your graph data.</p><h2>Open, Closed, and Small</h2><p>Extraction (from ingestion) and query translation (from agentic search) use <code>gemini-3.1-flash-lite</code>. Embeddings are Voyage <code>voyage-3.5</code> at 1024 dimensions. Both are closed APIs.</p><p>You can take this further and fine-tune an open-source SLM (such as the Liquid family of models) as an extractor, query translator, or embedding model on your own data.</p><p>The issue with SLMs is that without fine-tuning they perform poorly on new data. But the beautiful part about them is that after fine-tuning they perform as well as a frontier model on a scoped task, while being much cheaper and faster to run.</p><p>I won&#8217;t go too much into fine-tuning here, but the idea is that at first you always want to start with an API that quickly gets stuff done, and then slowly replace the most important parts with your own fine-tuned models. You usually have to decide this based on cost, latency, performance, data privacy, or other dimensions important to your use case.</p><h2>Build vs Buy: When Not To Build This</h2><p>Everything above assumed you build everything yourself. But in reality, there are 3 levels to choose from.</p><p><strong>Level 1:</strong> build the memory, the logic, and the serving layer yourself on one database.</p><p><strong>Level 2:</strong> keep only the business logic and serving layer on top of a memory SDK, such as <a href="https://github.com/getzep/graphiti">Graphiti</a>, <code>neo4j-labs/agent-memory</code>, or <a href="https://github.com/mem0ai/mem0">mem0</a>.</p><p><strong>Level 3:</strong> run an off-the-shelf engine, such as <a href="https://github.com/topoteretes/cognee">cognee</a>, managed <a href="https://www.getzep.com/">Zep</a>, or <a href="https://hydradb.com/">HydraDB</a>.</p><p>This is a problem about owning your context layer, which I have a <a href="https://www.decodingai.com/p/the-context-layer">full article</a> on.</p><p>Buy when you don&#8217;t care that much about customization. Build when you want <em>your</em> own solution. But since building everything yourself usually isn&#8217;t worth it (or you just don&#8217;t have the time to do it &#8212; even with Claude Code), the best solution is <strong>Level 2</strong>, where you own the business logic and can customize the serving layer to your needs.</p><p>But honestly, because things move so fast and I am lazy, my long-term memory still lives in Obsidian, Readwise, and Google Drive, plus a serving layer that creates scoped LLM wikis per project as agent memory. This way, you create mini-graphs for one specific problem, powered purely by .md files, without any infrastructure hassle. The reality is that this works for personal use only, and not so much for shipping a production-ready solution. I write about that approach in <a href="https://www.decodingai.com/p/llm-wiki-agent-memory">LLM Wikis as Agent Memory</a>.</p><p>Still, I am applying the strategy based on KGs and ontologies to build <strong>Pulse</strong>, a data mining tool that runs the exact same strategy presented above on a knowledge-work ontology to extract the top 0.1% signal from the AI industry. I want it custom because I want it to be super light, powered by LadybugDB, and to leverage my Claude subscription for the extraction and deduplication part, built as a hybrid between skills and Python modules.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>If you keep dumping everything into the unified memory, where do you draw the line between what your agent should remember forever and what it should be allowed to forget?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/how-to-implement-a-unified-memory-from-scratch?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <a href="https://www.mongodb.com/">MongoDB</a> for sponsoring this article and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.mongodb.com/" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48258,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://www.mongodb.com/&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/203854945?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Explore Next</h2><ol><li><p>Iusztin, P. (n.d.). Own Your Context Layer: Portable AI Agent Memory. Decoding AI. <a href="https://www.decodingai.com/p/the-context-layer">https://www.decodingai.com/p/the-context-layer</a></p></li><li><p>Iusztin, P. (n.d.). Ship a Knowledge Graph Ontology in 5 Minutes. Decoding AI. <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes</a></p></li><li><p>Iusztin, P. (n.d.). How to Keep Your AI Agent&#8217;s Knowledge Graph Clean. Decoding AI. <a href="https://www.decodingai.com/p/keep-knowledge-graph-clean">https://www.decodingai.com/p/keep-knowledge-graph-clean</a></p></li><li><p>Iusztin, P. (n.d.). LLM Wikis as Living Memory for AI Agents. Decoding AI. <a href="https://www.decodingai.com/p/llm-wiki-agent-memory">https://www.decodingai.com/p/llm-wiki-agent-memory</a></p></li><li><p>Neo4j Labs. (n.d.). Why Neo4j? Graph-Native Memory Architecture. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/graph-architecture/">https://neo4j.com/labs/agent-memory/explanation/graph-architecture/</a></p></li><li><p>Neo4j Labs. (n.d.). POLE+O Data Model. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">https://neo4j.com/labs/agent-memory/explanation/poleo-model/</a></p></li><li><p>Neo4j Labs. (n.d.). How Entity Extraction Works. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/">https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/</a></p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Your Second Brain Is a Graveyard. Make It Agent Memory.]]></title><description><![CDATA[Turn dead notes into a living LLM wiki your AI agents can query, maintain, and grow]]></description><link>https://www.decodingai.com/p/llm-wiki-agent-memory</link><guid isPermaLink="false">https://www.decodingai.com/p/llm-wiki-agent-memory</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 07 Jul 2026 05:01:21 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qTKJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qTKJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qTKJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qTKJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Ten thousand notes sit in the dark. The handful you need light up and come to you.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Ten thousand notes sit in the dark. The handful you need light up and come to you." title="Ten thousand notes sit in the dark. The handful you need light up and come to you." srcset="https://substackcdn.com/image/fetch/$s_!qTKJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!qTKJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc983d19b-d99e-442f-9a41-3418aea2dc4c_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I spent 18 months turning my second brain into my living research memory. My digital life contains 10,994 notes: over 5,000 in Obsidian, another 5,000 in Readwise, plus more in Notion and Google Drive, growing by roughly 250 a month.</p><p>The reality is that most of my notes and bookmarks transformed into a graveyard. When I start a new article or open a codebase, I can&#8217;t recall the high-signal notes I already have, so I work without them or burn an hour digging.</p><p>The reflex is to reach for Codex or NotebookLM. But those are harnesses: they sit on top of your work, and the moment the chat ends, the context window loses all of it.</p><p>More context isn&#8217;t the fix. You re-paste the same links and re-explain the same project every session, while past research sits inert in a vault your agents can&#8217;t reach.</p><p>So <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Louis-Fran&#231;ois Bouchard&quot;,&quot;id&quot;:130571458,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!f-b9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c5d976-f699-4595-8b6d-6ffa3e42a5e5_400x400.jpeg&quot;,&quot;uuid&quot;:&quot;e78edcc8-a889-48fd-81a9-fefde2398454&quot;}" data-component-name="MentionToDOM"></span>, CTO of Towards AI, and I built the alternative, and we&#8217;ll show you how: your own <strong>AI Research OS</strong>. It&#8217;s a memory layer that sits <em>between</em> your second brain and any harness (Codex, Claude Code, or your own). It runs deep research across your notes and the open web, and stores what it finds as an LLM wiki you can query, maintain, and grow.</p><p>We first touched on this subject in a talk at the AI Engineer World&#8217;s Fair. After we saw that people loved it (it was published as a keynote in the online tracks - out of 82 videos - and is the 2nd most popular one), I decided to write an article about it as well.</p><p>By the end you&#8217;ll learn how to turn your 10,994 notes into a queryable LLM wiki that your AI agents can use as their agent memory, useful for research, coding and content creation.</p><p>You will build an LLM wiki as in the image below, where the payoff already compounds with just 12 sources:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LflI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LflI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 424w, https://substackcdn.com/image/fetch/$s_!LflI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 848w, https://substackcdn.com/image/fetch/$s_!LflI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 1272w, https://substackcdn.com/image/fetch/$s_!LflI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LflI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png" width="1456" height="772" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:772,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The payoff up front: a queryable wiki combining repos, personal notes, and web sources into one graph. Just 12 sources, and the memory already earns its keep.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The payoff up front: a queryable wiki combining repos, personal notes, and web sources into one graph. Just 12 sources, and the memory already earns its keep." title="The payoff up front: a queryable wiki combining repos, personal notes, and web sources into one graph. Just 12 sources, and the memory already earns its keep." srcset="https://substackcdn.com/image/fetch/$s_!LflI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 424w, https://substackcdn.com/image/fetch/$s_!LflI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 848w, https://substackcdn.com/image/fetch/$s_!LflI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 1272w, https://substackcdn.com/image/fetch/$s_!LflI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde064b5c-a1fd-4f12-a210-84b70ef625c1_1614x856.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Or go crazier with a larger wiki:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!USVl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!USVl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 424w, https://substackcdn.com/image/fetch/$s_!USVl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 848w, https://substackcdn.com/image/fetch/$s_!USVl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 1272w, https://substackcdn.com/image/fetch/$s_!USVl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!USVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png" width="1456" height="823" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:823,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A bigger project wiki of ~100 notes, distilled into 73 concepts and 18 entities, that still draws on a 10,000+ note second brain. Why it stays this small and this cheap comes together by the end.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A bigger project wiki of ~100 notes, distilled into 73 concepts and 18 entities, that still draws on a 10,000+ note second brain. Why it stays this small and this cheap comes together by the end." title="A bigger project wiki of ~100 notes, distilled into 73 concepts and 18 entities, that still draws on a 10,000+ note second brain. Why it stays this small and this cheap comes together by the end." srcset="https://substackcdn.com/image/fetch/$s_!USVl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 424w, https://substackcdn.com/image/fetch/$s_!USVl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 848w, https://substackcdn.com/image/fetch/$s_!USVl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 1272w, https://substackcdn.com/image/fetch/$s_!USVl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f1500bb-8910-4222-a8c1-0d396fa71d3c_1602x906.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By the end, you will also see why the wikis don&#8217;t contain all my 10,994 notes to keep ingestion costs low. Let&#8217;s go.</p><div class="callout-block" data-callout="true"><h2>Want your AI work featured across three platforms?</h2><p>I'm looking for one builder to co-create a customer story on how you used Opik to solve a real-world problem in your AI product.</p><p>Here's what you get: from a 1-hour interview where you show off what you built, I'll produce a <strong>co-authored article, a YouTube video, and a run of social posts</strong>, all spotlighting your work. Distributed across both Decoding AI and Opik (by Comet) channels to 200,000+ AI engineers and decision-makers.</p><p>Here are the last two:</p><ul><li><p><a href="https://www.decodingai.com/p/how-evaluation-driven-development-works">How Evaluation-Driven Development (EDD) Works</a></p></li><li><p><a href="https://www.decodingai.com/p/ship-rag-with-weave-cli">What Held Up at 3 AM: One Engineer&#8217;s RAG Case Study</a></p></li></ul><p>If you want to collaborate, email me at <em>pauliusztin@decodingai.com</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;mailto:pauliusztin@decodingai.com?subject=Opik%20Customer%20Story%20Collaboration&quot;,&quot;text&quot;:&quot;Email me&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="mailto:pauliusztin@decodingai.com?subject=Opik%20Customer%20Story%20Collaboration"><span>Email me</span></a></p><p><em>Fine print:</em> your product or project must use Opik. This is a collaboration between Decoding AI and Opik (by Comet). </p></div><h2>Why a Bigger Context Window Won&#8217;t Save You</h2><p>Most research doesn&#8217;t need this system. If you want a quick answer or a one-off, Google it, or reach for Codex and Claude Code. You need this only when the research has to <em>stick</em> and an agent has to reuse those sources later.</p><p>You don&#8217;t need a giant vault either. This is about topic density, not size. It already pays off on a topic-sized cluster: around 20 notes on one subject, or 2 or 3 repos, like coding agents such as Pi, OpenCode, and Aider. Louis-Fran&#231;ois runs it on a few hundred notes, not my 10,000+, and it still earns its keep.</p><p>Why not NotebookLM? It&#8217;s great at digesting sources, but you don&#8217;t own it, you can&#8217;t personalize it deeply, it isn&#8217;t agent-native, and it&#8217;s weak for coding since it&#8217;s browser-bound.</p><p>Why not a vector-database RAG pipeline? That&#8217;s the right call at production scale, but it&#8217;s infrastructure. It&#8217;s hard to inspect or edit by hand, and overkill for a personal tool you open every day.</p><p>So you build it yourself: a personalized research assistant that uses an LLM wiki knowledge base that&#8217;s light and human-friendly as its agent memory. The perfect context engineering technique as an interface between the human and the AI agent.</p><p>Now, I want to go over, step by step, how we reached our final deep research + LLM wiki design, with the &#8220;why&#8221; and &#8220;how&#8221; in mind.</p><h2>The Deep-Research Loop, Version 1: Mining the Public Web</h2><p>A year ago, building the Agent Engineering course, we scoped the loop tightly: give it a topic plus a few hand-picked <strong>golden links</strong>, and get back a single static <code>research.md</code>.</p><p>The deep research algorithm first scrapes the golden links for seed context. Knowing them up front lets the agent frame better questions. Then it runs query rounds: one <strong>orchestrator</strong> generates the questions, and a <strong>sub-agent per question</strong> searches (Gemini grounded in Google) and returns links plus a summary, which the orchestrator aggregates so the context never explodes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FbGR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FbGR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 424w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 848w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 1272w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FbGR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png" width="1456" height="443" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:443,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Version 1 in one line: topic + golden links &#8594; deep-research algorithm &#8594; one static research.md.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Version 1 in one line: topic + golden links &#8594; deep-research algorithm &#8594; one static research.md." title="Version 1 in one line: topic + golden links &#8594; deep-research algorithm &#8594; one static research.md." srcset="https://substackcdn.com/image/fetch/$s_!FbGR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 424w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 848w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 1272w, https://substackcdn.com/image/fetch/$s_!FbGR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a02e318-e3d9-43f6-a2a5-7429e48b19c0_2400x731.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Version 1 in one line: topic + golden links &#8594; deep-research algorithm &#8594; one static research.md.</em></figcaption></figure></div><p>Three rounds of 6 queries surface 40&#8211;50 links, which is too noisy to keep whole. A <strong>ranking</strong> step scores each source against the topic. Only the top-K get fully scraped, the rest are kept as summaries, and everything is compiled into one flat <code>research.md</code>. That version generated 35 course lessons fast.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y6mp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y6mp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 424w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 848w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 1272w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y6mp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png" width="1456" height="581" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:581,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The deep-research algorithm unpacked: orchestrator, six sub-agents per round, three rounds, ranking, then top-K full scrapes into research.md.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The deep-research algorithm unpacked: orchestrator, six sub-agents per round, three rounds, ranking, then top-K full scrapes into research.md." title="The deep-research algorithm unpacked: orchestrator, six sub-agents per round, three rounds, ranking, then top-K full scrapes into research.md." srcset="https://substackcdn.com/image/fetch/$s_!Y6mp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 424w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 848w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 1272w, https://substackcdn.com/image/fetch/$s_!Y6mp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F792be5b5-ea26-4bfb-829d-d861596cb62f_2400x957.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The deep-research algorithm unpacked: orchestrator, six sub-agents per round, three rounds, ranking, then top-K full scrapes into research.md.</em></figcaption></figure></div><p>It worked for the course, but it was aimed at the generic public web, with every golden link hand-picked from our own second brain.</p><h2>Version 2: Point the Loop at Your Second Brain</h2><p>Same loop, new target: aim it at your own sources instead of the public web, where you&#8217;ve already filtered what matters. Your second brain <em>is</em> a curated set of golden links, so the input shrinks to just a topic and the loop finds the rest.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!txf7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!txf7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 424w, https://substackcdn.com/image/fetch/$s_!txf7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 848w, https://substackcdn.com/image/fetch/$s_!txf7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 1272w, https://substackcdn.com/image/fetch/$s_!txf7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!txf7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png" width="1456" height="530" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:530,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Version 2's core move: take the same loop and aim it at your own sources instead of the open web.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Version 2's core move: take the same loop and aim it at your own sources instead of the open web." title="Version 2's core move: take the same loop and aim it at your own sources instead of the open web." srcset="https://substackcdn.com/image/fetch/$s_!txf7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 424w, https://substackcdn.com/image/fetch/$s_!txf7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 848w, https://substackcdn.com/image/fetch/$s_!txf7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 1272w, https://substackcdn.com/image/fetch/$s_!txf7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dce886a-e409-47a9-aba5-cff5a95bc51c_2400x873.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Version 2&#8217;s core move: take the same loop and aim it at your own sources instead of the open web.</em></figcaption></figure></div><p>You plug in Obsidian, Readwise, NotebookLM, and GitHub Stars, then extend with Gemini Deep Research, YouTube, Google Drive, or Notion. Code is a special case: a GitHub sub-agent clones a repo and builds a high-level architecture note.</p><p>The token-efficiency trick lives in the reranker. It scores each candidate from 0 to 1 against your question using only its metadata and summary, never the full text, then passes only the top-K to the model.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1AwG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1AwG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 424w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 848w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 1272w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1AwG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png" width="1456" height="489" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:489,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The loop over your own sources: topic-only input, personal sources plugged in, same rank-and-scrape tail.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The loop over your own sources: topic-only input, personal sources plugged in, same rank-and-scrape tail." title="The loop over your own sources: topic-only input, personal sources plugged in, same rank-and-scrape tail." srcset="https://substackcdn.com/image/fetch/$s_!1AwG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 424w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 848w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 1272w, https://substackcdn.com/image/fetch/$s_!1AwG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6164947-9d0d-4ed7-82a3-022984668b97_2400x806.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The loop over your own sources: topic-only input, personal sources plugged in, same rank-and-scrape tail.</em></figcaption></figure></div><p>The new problem is that the output is frozen. You still end up with a static <code>research.md</code>, and real research isn&#8217;t static. You want another question answered, or part of it goes stale, and re-running the loop from scratch is expensive in tokens and time. The fix is a new layer that sits on top of the raw data: the LLM wiki.</p><h2>Version 3: From a Static Pile to a Living Wiki</h2><p>The pivot came from Andrej Karpathy&#8217;s idea of <strong>LLM-maintained knowledge-base wikis</strong> <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">[1]</a>. Instead of re-deriving knowledge from raw documents on every query, which is the RAG pattern, the LLM incrementally builds and maintains a persistent, interlinked wiki between you and your sources.</p><p><strong>Since I realized the power of LLM wikis, I started to use them for all my personal setups as my agent memory. It&#8217;s simple, powerful and beautiful.</strong></p><p>Since giving this talk, we found that Google had published its <strong><a href="https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing">Open Knowledge Format (OKF)</a></strong>, an open spec that &#8220;formalizes the LLM-wiki pattern into a portable, interoperable format&#8221; <a href="https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing">[2]</a>. It&#8217;s built on the very blocks you&#8217;ll see below: plain markdown with YAML frontmatter, an index, a log, and links that form a graph. When Google independently ships the same architecture as a standard, you know the direction is right.</p><p>During ingestion it generates, as a byproduct, derivatives over your raw sources: entities and concepts, comparisons between them, notes tied to your questions, open questions, and a synthesis:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qxOx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qxOx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 424w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 848w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 1272w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qxOx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png" width="1456" height="1486" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1486,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!qxOx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 424w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 848w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 1272w, https://substackcdn.com/image/fetch/$s_!qxOx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7b23f3-fd42-4087-87b1-d17f4562fe68_2120x2163.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Storing each finding as an individual raw file, instead of one flat <code>research.md</code>, is the one change that makes everything downstream queryable and growable. Sources can include Obsidian, GitHub, Google Drive, even custom URLs (plain curl for simple sites, Bright Data for bot-walled ones).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K5GT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K5GT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 424w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 848w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 1272w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K5GT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png" width="1456" height="497" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30565fb3-2384-4103-aa3a-172461647681_2400x820.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:497,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Sources &#8594; deep research &#8594; store raw files &#8594; index &#8594; generate wiki &#8594; query. The version-3 pipeline end to end.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Sources &#8594; deep research &#8594; store raw files &#8594; index &#8594; generate wiki &#8594; query. The version-3 pipeline end to end." title="Sources &#8594; deep research &#8594; store raw files &#8594; index &#8594; generate wiki &#8594; query. The version-3 pipeline end to end." srcset="https://substackcdn.com/image/fetch/$s_!K5GT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 424w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 848w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 1272w, https://substackcdn.com/image/fetch/$s_!K5GT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30565fb3-2384-4103-aa3a-172461647681_2400x820.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Sources &#8594; deep research &#8594; store raw files &#8594; index &#8594; generate wiki &#8594; query. The version-3 pipeline end to end.</em></figcaption></figure></div><p>The natural fear is that &#8220;index + wiki + query&#8221; means vector databases and knowledge graphs. It doesn&#8217;t, and that&#8217;s the surprising part.</p><h2>A Memory Layer Built From Plain Files and No Database</h2><p>Vector databases, knowledge graphs, and semantic and text search all add real complexity, too much for a personal research OS. So drop that infrastructure and build the whole thing on files and references: no database, just a simple index rooted in how your filesystem already works.</p><p>The index is the retrieval layer. An agent reads a single <code>index.yaml</code> first, a catalog with a summary and metadata for each source (original file, origin, title, authors, date).</p><p>There are 3 layers. A <code>raw</code> folder holds the immutable source data, a <code>wiki</code> folder holds the LLM-generated derivatives, and the <code>index</code> points to all of it. A real example is an <code>index.yaml</code> cataloging 10 sources and 38 wiki pages.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OJ0b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OJ0b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 424w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 848w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 1272w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OJ0b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png" width="1456" height="387" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:387,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!OJ0b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 424w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 848w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 1272w, https://substackcdn.com/image/fetch/$s_!OJ0b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76c82d98-b000-496f-a6fa-8f1f93bb0da1_2120x563.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xLVZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xLVZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 424w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 848w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 1272w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xLVZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png" width="1456" height="673" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:673,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The index is the retrieval layer: one YAML catalog the agent reads first, pointing to everything else.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The index is the retrieval layer: one YAML catalog the agent reads first, pointing to everything else." title="The index is the retrieval layer: one YAML catalog the agent reads first, pointing to everything else." srcset="https://substackcdn.com/image/fetch/$s_!xLVZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 424w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 848w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 1272w, https://substackcdn.com/image/fetch/$s_!xLVZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1e1cc-58c1-4df9-bc93-93a94480e689_2400x1110.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The index is the retrieval layer: one YAML catalog the agent reads first, pointing to everything else.</em></figcaption></figure></div><p>You even get a knowledge graph for free. Because everything is Obsidian-flavored markdown with references, Obsidian&#8217;s local graph renders the connections out of the box: entities like OpenCode or MCP linked to concepts like tool registry, context compaction, and sandboxing, and the sources they touch.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jvI7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jvI7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 424w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 848w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 1272w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jvI7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png" width="1456" height="1242" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1242,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;claude code entity&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="claude code entity" title="claude code entity" srcset="https://substackcdn.com/image/fetch/$s_!jvI7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 424w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 848w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 1272w, https://substackcdn.com/image/fetch/$s_!jvI7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d11c98e-271b-41b5-a728-adc37e38024e_2112x1802.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Obsidian is only a viewer, though. The whole system runs from any working directory through Codex or Claude Code, so the graph is a bonus on top.</p><h2>Querying the Wiki, and Why It Never Freezes</h2><p>The agent queries through progressive disclosure. It starts at the <code>index.yaml</code> summaries. If it needs more, it opens the <strong>source wiki page</strong> (an expanded summary), and often stops there.</p><p>If not, it follows references into the <strong>derivatives</strong> (entities, concepts, comparisons, notes). Only as a last resort does it read the <strong>raw source</strong>. Summaries are computed once, at ingestion, so the context window stays small.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y3Kw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 424w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 848w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png" width="1456" height="703" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:703,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The query drill-down: each level answers most questions, so the agent rarely touches raw sources and context stays small.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The query drill-down: each level answers most questions, so the agent rarely touches raw sources and context stays small." title="The query drill-down: each level answers most questions, so the agent rarely touches raw sources and context stays small." srcset="https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 424w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 848w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 1272w, https://substackcdn.com/image/fetch/$s_!Y3Kw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd45a4434-b833-4be1-be5c-cd3fd702c2ac_2400x1158.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The query drill-down: each level answers most questions, so the agent rarely touches raw sources and context stays small.</em></figcaption></figure></div><p>The wiki is also alive. Ask a question and the LLM can spawn a new concept, note, or comparison, and each question is written to a log. So the wiki evolves as you <em>talk</em> to it, not only when you ingest data.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DbRB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DbRB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 424w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 848w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 1272w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DbRB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png" width="1456" height="484" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:484,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Every question leaves a trace: new notes and comparisons accrete, and the log tracks the whole history.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Every question leaves a trace: new notes and comparisons accrete, and the log tracks the whole history." title="Every question leaves a trace: new notes and comparisons accrete, and the log tracks the whole history." srcset="https://substackcdn.com/image/fetch/$s_!DbRB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 424w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 848w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 1272w, https://substackcdn.com/image/fetch/$s_!DbRB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd62a4de4-10b1-452f-b73c-0fbd9ee2ddef_2400x798.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Every question leaves a trace: new notes and comparisons accrete, and the log tracks the whole history.</em></figcaption></figure></div><p>It&#8217;s never frozen, and it grows 3 ways: ingest a new custom link, run another deep-research round, or let it create derivatives purely from your questions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QyOU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QyOU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 424w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 848w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 1272w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QyOU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png" width="1456" height="859" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:859,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The wiki grows three ways: new links, new research rounds, and new derivatives born from your questions.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The wiki grows three ways: new links, new research rounds, and new derivatives born from your questions." title="The wiki grows three ways: new links, new research rounds, and new derivatives born from your questions." srcset="https://substackcdn.com/image/fetch/$s_!QyOU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 424w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 848w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 1272w, https://substackcdn.com/image/fetch/$s_!QyOU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dc23955-1cf8-4cc0-ad10-47d0539c3249_2400x1416.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The wiki grows three ways: new links, new research rounds, and new derivatives born from your questions.</em></figcaption></figure></div><p>One design choice makes this safe to run against a decade of notes: the wiki never sits directly on your whole second brain.</p><h2>Scope It to a Project With PARA</h2><p>Your second brain stays an immutable snapshot. I organize everything with the <strong>PARA method</strong>: Projects, Areas, Resources, Archive <a href="https://fortelabs.com/blog/para/">[3]</a>. Sources are piped into Resources as a flat list, then referenced into Projects and Areas. So Obsidian stays read-only; I don&#8217;t want the LLM editing notes I write by hand.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Hom-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Hom-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 424w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 848w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 1272w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Hom-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png" width="1456" height="757" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/df9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:757,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;PARA keeps your global second brain an immutable, read-only snapshot the LLM never writes to.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="PARA keeps your global second brain an immutable, read-only snapshot the LLM never writes to." title="PARA keeps your global second brain an immutable, read-only snapshot the LLM never writes to." srcset="https://substackcdn.com/image/fetch/$s_!Hom-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 424w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 848w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 1272w, https://substackcdn.com/image/fetch/$s_!Hom-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf9e096d-bde9-4394-8e57-af70ea9b5215_2400x1248.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>PARA keeps your global second brain an immutable, read-only snapshot the LLM never writes to.</em></figcaption></figure></div><p>The wiki is scoped per project, not global. When you start something new, you reference that snapshot <em>through</em> the deep-research loop and scope it down to the project, running the loop or ingesting specific repos, articles, and notes via skills plugged into a harness.</p><p>Scoping is a scale choice as much as a safety one: plain files stay fast and inspectable at project size, but a whole-vault wiki of thousands of documents is exactly where a vector or graph database finally earns its place.</p><p>That&#8217;s the ~100-note wiki from the top, kept small by scoping to one project, yet reaching my entire 10,000+ note second brain through the loop.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j4il!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j4il!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 424w, https://substackcdn.com/image/fetch/$s_!j4il!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 848w, https://substackcdn.com/image/fetch/$s_!j4il!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 1272w, https://substackcdn.com/image/fetch/$s_!j4il!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j4il!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png" width="1456" height="521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:521,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Scope the snapshot down into a project wiki, then let an agent turn that research into the actual work.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Scope the snapshot down into a project wiki, then let an agent turn that research into the actual work." title="Scope the snapshot down into a project wiki, then let an agent turn that research into the actual work." srcset="https://substackcdn.com/image/fetch/$s_!j4il!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 424w, https://substackcdn.com/image/fetch/$s_!j4il!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 848w, https://substackcdn.com/image/fetch/$s_!j4il!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 1272w, https://substackcdn.com/image/fetch/$s_!j4il!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb1f960-b375-4943-8d4d-07f9e637778a_2400x859.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Scope the snapshot down into a project wiki, then let an agent turn that research into the actual work.</em></figcaption></figure></div><p>The mental model is that the project is the work and the second brain is the research. A project is anything where you turn research into work: an article, a video, a set of slides (this talk was built this way), or a whole codebase. That&#8217;s the whole architecture, and the fastest way to see why it matters is to watch it run.</p><h2>See It Run: Three Demos</h2><p>Everything ships as one open-source Claude Code plugin you can clone and run on your own notes (<a href="https://github.com/iusztinpaul/ai-research-os-workshop">https://github.com/iusztinpaul/ai-research-os-workshop</a>), tweakable for any harness.</p><p>It&#8217;s four skills: <code>/research</code> (build or query the wiki), <code>/research-distill</code> (a per-piece <code>research.md</code>), <code>/research-lint</code> (health-checks), and <code>/research-render</code> (slides or a brief).</p><p><strong>Demo 1</strong> is research from a brain dump around &#8220;agentic harnesses&#8221;. You point the research skill at a file of notes plus a few must-include references. It scrapes those for seed context and picks a depth: <strong>fast</strong> (1 round of 3 queries), <strong>light</strong> (2 rounds, 3 then 2), or <strong>deep</strong> (3 rounds of 3). Out come the raw files + the LLM wiki:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m3dw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m3dw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 424w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 848w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 1272w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m3dw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png" width="1456" height="1062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1062,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Demo 1 output: a topic's worth of research rendered as a live Obsidian graph, the index at its center.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Demo 1 output: a topic's worth of research rendered as a live Obsidian graph, the index at its center." title="Demo 1 output: a topic's worth of research rendered as a live Obsidian graph, the index at its center." srcset="https://substackcdn.com/image/fetch/$s_!m3dw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 424w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 848w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 1272w, https://substackcdn.com/image/fetch/$s_!m3dw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd63cc833-a7f5-45e8-9da0-b04a9609955d_1482x1081.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Demo 2</strong> is ingesting and comparing GitHub repos. You give it 3 harness repos (OpenCode, Pi, Hermes), no deep research, scoped to architecture, sub-agents, memory, and the permission flow. It clones each, writes per-repo notes, then builds cross-repo comparisons.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0gs0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0gs0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 424w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 848w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 1272w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0gs0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png" width="1145" height="822" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:822,&quot;width&quot;:1145,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Demo 2 output: three harnesses ingested straight from code, with the cross-repo comparison notes generated automatically.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Demo 2 output: three harnesses ingested straight from code, with the cross-repo comparison notes generated automatically." title="Demo 2 output: three harnesses ingested straight from code, with the cross-repo comparison notes generated automatically." srcset="https://substackcdn.com/image/fetch/$s_!0gs0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 424w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 848w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 1272w, https://substackcdn.com/image/fetch/$s_!0gs0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F347becea-b19b-45a9-8512-a7d3c7417e3a_1145x822.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Demo 3</strong> is ad-hoc links on GraphRAG, then questions to create notes. You hand it 3 arbitrary links to build a wiki, then ask how agentic GraphRAG differs from a plain knowledge graph. It answers off the wiki <em>and</em> updates it in place.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jzx2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jzx2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 424w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 848w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 1272w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jzx2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png" width="976" height="740" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:740,&quot;width&quot;:976,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Demo 3 output: a wiki built from three raw links that keeps growing as you query it.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Demo 3 output: a wiki built from three raw links that keeps growing as you query it." title="Demo 3 output: a wiki built from three raw links that keeps growing as you query it." srcset="https://substackcdn.com/image/fetch/$s_!Jzx2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 424w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 848w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 1272w, https://substackcdn.com/image/fetch/$s_!Jzx2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20818c5f-397a-477f-9606-c6c66e2ca1f6_976x740.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>It was super hard to show the full demos here. You can find the full examples within the <a href="https://github.com/iusztinpaul/ai-research-os-workshop">Examples</a> section of the repo or watch me go over them in Obsidian and Zed in the <a href="https://www.youtube.com/watch?v=ZRM_TfEZcIo">full video</a>.</p><h2>Where This Is Going</h2><p>Some connectors are missing on purpose (Google Drive, Notion, Slack) &#8212; the point is for <em>you</em> to add what you need. Louis-Fran&#231;ois added YouTube transcript ingestion in seconds with one prompt to Codex.</p><p>Two weaknesses stand out. The byproducts are often poorly written, fixable with the article writing profiles I already use. And as data grows, the LLM makes subtle errors: <strong>concept confusion</strong> (comparing Claude Code and OpenCode, it merged how each handles tool calls into one explanation) and <strong>superficiality</strong> (the Claude Code queuing system took many follow-ups to get right).</p><p>The fix is constant linting, which is what <code>/research-lint</code> does: it sweeps the wiki for orphan sources, broken links, stale claims, and contradictions.</p><h2>What&#8217;s Next</h2><p>Everything you saw here is open source. <strong>Clone the repo</strong> (or install it as a Claude Code plugin) and run it on your own notes today: <a href="https://github.com/iusztinpaul/ai-research-os-workshop">https://github.com/iusztinpaul/ai-research-os-workshop</a></p><p>If you&#8217;d rather see the whole system in action first, watch the full talk <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Louis-Fran&#231;ois Bouchard&quot;,&quot;id&quot;:130571458,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!f-b9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe0c5d976-f699-4595-8b6d-6ffa3e42a5e5_400x400.jpeg&quot;,&quot;uuid&quot;:&quot;9c3ede7f-d61e-4f65-a625-08e3bc850048&quot;}" data-component-name="MentionToDOM"></span> and I gave at the <strong>AI Engineer World&#8217;s Fair</strong>:</p><div id="youtube2-ZRM_TfEZcIo" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;ZRM_TfEZcIo&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/ZRM_TfEZcIo?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>And if you want to go beyond a workshop repo, such as <strong>building a deep-research-plus-writing multi-agent system</strong> from <strong>scratch</strong> and <strong>shipping</strong> it to <strong>production</strong> with AI evals and an observability layer on top, that&#8217;s exactly what we teach in our <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems course</a></strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uql0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uql0!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uql0!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;placeholder&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="placeholder" title="placeholder" srcset="https://substackcdn.com/image/fetch/$s_!Uql0!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!Uql0!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe507da12-ec85-47cf-bd9e-afadffc7e99d_1200x1200.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The multi-agent system built during the <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems course</a></strong></figcaption></figure></div><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/llm-wiki-agent-memory?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/llm-wiki-agent-memory?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Explore Next</h2><ol><li><p>Karpathy, A. (n.d.). LLM Wiki: A pattern for building personal knowledge bases using LLMs. GitHub. <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f</a></p></li></ol><ol><li><p>Google Cloud. (n.d.). How the Open Knowledge Format can improve data sharing. Google Cloud Blog. <a href="https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing">https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing</a></p></li><li><p>Forte, T. (n.d.). The PARA Method: The Simple System for Organizing Your Digital Life. Forte Labs. <a href="https://fortelabs.com/blog/para/">https://fortelabs.com/blog/para/</a></p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[From Harness Lock-In to Portable Context Layer]]></title><description><![CDATA[Build a unified memory (knowledge graph or an LLM wiki) and serve it over MCP servers or skills, so any agent, open or closed, plugs in within minutes.]]></description><link>https://www.decodingai.com/p/the-context-layer</link><guid isPermaLink="false">https://www.decodingai.com/p/the-context-layer</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 30 Jun 2026 08:20:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!k7bK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k7bK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k7bK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k7bK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Your memory is the one thing you carry from one machine to the next.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Your memory is the one thing you carry from one machine to the next." title="Your memory is the one thing you carry from one machine to the next." srcset="https://substackcdn.com/image/fetch/$s_!k7bK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!k7bK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34e5ac29-e4cc-447f-b4c5-b25cefcce8b2_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Models are commoditizing fast. Harnesses already have. What you care about is your research, your notes, your conversations, your tasks, your preferences, and your domain knowledge.</p><blockquote><p>&#8220;Free&#8221; open-source harnesses don&#8217;t make you free. What you want to own is the <em>context layer</em>. Every agent is the same model + runtime + harness underneath, rebuildable on an open stack <a href="https://youtube.com/watch?v=BEYEWw1Mkmw">[1]</a>.</p></blockquote><p>I hit this myself. The deeper I built into a single harness, the clearer it got how much I&#8217;d lose the day I had to leave. The loss comes in 3 forms.</p><p><strong>Failure 1 &#8212; You start from scratch.</strong> You&#8217;ve run Claude Code for 6 months. You switch to an open model and every past conversation, every preference the agent learned about you, is gone. You begin again from zero.</p><p><strong>Failure 2 &#8212; Your skills are hostage.</strong> The harder lock-in is your business logic. If your skills and workflows are coupled to one harness&#8217;s features and keywords, switching doesn&#8217;t just lose chat history &#8212; your custom logic breaks or quietly performs worse on the next tool.</p><p><strong>Failure 3 &#8212; You&#8217;re billed at their mercy.</strong> The plan you depend on can be pulled, suddenly gated behind expensive pay-as-you-go, restricted from the latest models (e.g., the Fable story), or repriced from 200 <em>to </em>1,000 overnight. With high switching friction, you can&#8217;t leave. You never know how the AI world can change. But for sure it won&#8217;t stay as is now.</p><blockquote><p><em>So what do you do?</em></p></blockquote><p>Keep your context layer detached from the harness. Any harness, any model (open or closed), plugs in and within ~5 minutes knows who you are, what you&#8217;re working on, what matters to you and how you like things to get done.</p><p>Everything that follows is based on the two projects I am working on: Scrabble, my own context layer anchored into my Obsidian notes, Readwise library, Notion, and Google ecosystem; and Tree, the project I am working on with <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Maxime Labonne&quot;,&quot;id&quot;:31453795,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17e73529-4d58-4477-b896-6d1e1f5c9796_896x896.png&quot;,&quot;uuid&quot;:&quot;6a62bff0-f52e-4d91-9880-7e3c5fe1eddb&quot;}" data-component-name="MentionToDOM"></span> for our next book, where we teach how to build a personal AI assistant from scratch.</p><h2>The Architecture of Your Context Layer</h2><p>A context layer is made out of 3 core components. First, a <strong>unified memory</strong> that holds everything you know. Second, a <strong>serving layer</strong> (MCP server or skills) that is the interface to that memory and the <strong>business logic</strong> that defines how the memory is used. The harness sits on top and is deliberately disposable.</p><p>The unified memory fuses what used to be separate systems: a filesystem, keyword search (BM25), semantic vector search, and a knowledge graph of typed POLE+O nouns (Person, Organization, Location, Event, Object), all in one place. The goal is a memory that belongs to you.</p><p>What I always preach is to try your best to build your unified memory on top of a single database that supports text, semantic, and graph search (such as <a href="https://www.mongodb.com/">MongoDB</a>). Start simple and add complexity only when your use case demands it.</p><p>The serving layer has 2 angles. The first is an MCP server, surfacing Tools, Resources, Prompts, Skills, and even MCP Apps (e.g. a graph visualizer) <a href="https://www.youtube.com/watch?v=v3Fr2JR47KA">[2]</a>. It wraps the business logic for how memory is queried and updated. That&#8217;s what makes it portable.</p><p>The second form skips the server entirely, which is based on skills shipped straight on the filesystem (an <code>AGENTS.md</code> plus a folder of skills). Skills are an interface too. They&#8217;re leaner, with nothing to run, but more tied to a given harness&#8217;s conventions. It&#8217;s how Scrabble&#8217;s wiki layer gets consumed.</p><p>In practice the strongest setups do both: a portable MCP server for memory access, skills layered on top for higher-level workflows <a href="https://www.youtube.com/watch?v=v3Fr2JR47KA">[2]</a>. To avoid fragmenting your business logic, host the skills directly on your MCP servers, coupling them with the rest of the server&#8217;s business logic.</p><p>In Tree, where I am building a unified memory powered by knowledge graphs, everything is discovered as ordinary MCP tools. That is exactly why &#8220;swap the harness, keep the memory&#8221; is a one-line config change, not a migration.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!l99G!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!l99G!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!l99G!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!l99G!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!l99G!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!l99G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The context layer &#8212; interchangeable harnesses over an MCP-server interface over one unified memory you own.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The context layer &#8212; interchangeable harnesses over an MCP-server interface over one unified memory you own." title="The context layer &#8212; interchangeable harnesses over an MCP-server interface over one unified memory you own." srcset="https://substackcdn.com/image/fetch/$s_!l99G!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!l99G!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!l99G!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!l99G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf894e06-e355-4ae6-95b5-45f3b84ec6dd_1200x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The context layer: Interchangeable harnesses over an MCP-server interface over one unified memory you own.</em></figcaption></figure></div><p><em>Here is what happens when you interact with the context layer:</em></p><p>You enter a prompt into the harness, which becomes an MCP tool call to the server. The server queries the unified memory, and results flow back into the agent&#8217;s context. Nothing crazy so far.</p><p>The interesting part happens when you start adding stuff to your memory. It&#8217;s where continual learning happens.</p><h2>Building a Unified Memory for Continual Learning</h2><p>At a high level, the pipeline is simple. Ingest data into the unified memory &#8594; extract entities and relationships into a graph &#8594; index for hybrid and graph retrieval &#8594; expose everything through an MCP server &#8594; connect it to a harness like Claude Code or OpenCode. Building the knowledge graph was the easy part. Designing how the agent interacts with it was the hard part.</p><p>Don&#8217;t expose raw database operations. Agents struggle with them. Instead, design the server around how agents actually search and write, giving them high-leverage primitives they can compose like LEGOs inside skills. In Tree that&#8217;s 6 tools: 3 to search, 3 to write.</p><p>There are 3 search tools. <code>nl_query_memory</code> is the default &#8212; an LLM maps a natural-language (NL) question into a MongoDB hybrid-search + graph query. <code>query_memory</code> is the deterministic fallback for structured filters when NL fails. <code>deep_search_memory</code> handles large result sets (50+ docs) via progressive disclosure: it writes intermediate results to a YAML index creating a localized LLM wiki on the fly.</p><p>The distinction between <code>nl_query_memory</code> / <code>query_memory</code> and <code>deep_search_memory</code> is important because when retrieving chunks from the unified memory, you need to further compress them before adding them into the context window to avoid exploding your costs. But that means you lose a lot of information. Thus, creating a wiki on the fly trades latency for performance and lower costs.</p><p>There are also 3 write tools: <code>ingest_url</code>, <code>ingest_file</code>, and <code>ingest_conversation</code>.</p><p>The last is auto-triggered by a hook that ingests incrementally every ~10 conversation turns and finalizes when the conversation ends. That hook is what makes the learning loop continual: the system writes back what it just learned without you asking, so it gets smarter the more you use it.</p><p>And &#8220;smarter&#8221; is concrete. Across tens of thousands of notes, it finds links between things you&#8217;d long forgotten you had, connections you&#8217;d never have made by hand. It&#8217;s how you finally harvest your own past work and your graveyard of bookmarks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6ZNy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6ZNy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 424w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 848w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 1272w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6ZNy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png" width="1232" height="1065" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1065,&quot;width&quot;:1232,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:159550,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/203854945?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6ZNy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 424w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 848w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 1272w, https://substackcdn.com/image/fetch/$s_!6ZNy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d4eef9e-3825-4125-95e4-a6827be4dfe8_1232x1065.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The continual-learning loop: The agent queries the graph through the MCP tools, and every conversation is ingested back into the unified memory.</figcaption></figure></div><p>Now, let&#8217;s see how to actually build the unified memory layer.</p><h2>Build It Three Ways</h2><p>You&#8217;re implementing 3 pieces: the unified memory, your custom business logic, and the serving layer. How much you build yourself is also split into 3 levels of effort, which translates to a build vs. buy discussion.</p><p><strong>Level 1: Build all three from scratch</strong> on a database that supports everything at once (such as <a href="https://www.mongodb.com/">MongoDB</a>), implementing the memory and the MCP serving layer yourself. Maximum control, maximum effort.</p><p><strong>Level 2: Build only the business logic and serving layer</strong>, on top of an SDK that already implements the memory layer: <a href="https://github.com/getzep/graphiti">Graphiti</a>, a bi-temporal entity/fact/episode graph; Neo4j-Labs&#8217; <a href="https://github.com/neo4j-labs/agent-memory">agent-memory</a>, a graph-native POLE+O store; or <a href="https://github.com/mem0ai/mem0">mem0</a>, a vector-first layer that stores facts as rows.</p><p><strong>Level 3: Off-the-shelf</strong> memory engines you mostly just run: <a href="https://github.com/topoteretes/cognee">cognee</a>, an Extract-Cognify-Load pipeline of typed nodes that are graph + vector at once; or managed services like <a href="https://www.getzep.com/">Zep</a> (temporal context graphs on the open-source Graphiti engine) and <a href="https://hydradb.com/">HydraDB</a> (a graph DB on tiered object storage, pitched as &#8220;own your memory, no data leaving your stack&#8221;). Lowest effort, least control over the data model, and a vendor dependency. Cognee can import and export memory across Mem0, Zep, and Graphiti if you need to switch.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dGWD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dGWD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dGWD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Agentic GraphRAG Architecture&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Agentic GraphRAG Architecture" title="Agentic GraphRAG Architecture" srcset="https://substackcdn.com/image/fetch/$s_!dGWD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 424w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 848w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!dGWD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68892c6f-9124-46c5-805a-e3b9adfe0282_1200x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Version 1 (from scratch): The full agentic GraphRAG pipeline from raw sources to MCP tools.</em></figcaption></figure></div><p>Now zoom into Level 1, the from-scratch path. Building the memory yourself splits into 2 versions. <strong>Version 1 (more complex)</strong>, such as Tree, the agent memory I am building, which is a GraphRAG system whose retrieval fuses vector and keyword search with knowledge-graph traversal. It contains a POLE+O ontology, the index (graph + vector + text), the data and memory pipelines that ingest into it, and the query algorithms that read it.</p><p>POLE+O is a popular data model for building ontologies, borrowed from law-enforcement and intelligence analysis. Its beauty is that it&#8217;s perfectly balanced. It&#8217;s not too shallow, nor too deep. Perfect for an LLM to extract KG triplets from your data. Here it is as a thin <code>StrEnum</code> of the 5 node types:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZojL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZojL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 424w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 848w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 1272w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZojL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png" width="1456" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!ZojL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 424w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 848w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 1272w, https://substackcdn.com/image/fetch/$s_!ZojL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9eee1cf0-da6a-46be-a4a4-0bb896b6a262_2911x819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In case you want more granularity over your POLE+O model, you can introduce subclasses, such as:</p><ul><li><p><strong>Person</strong>: individual, alias, persona</p></li><li><p><strong>Organization</strong>: company, nonprofit, government, ...</p></li><li><p><strong>Location</strong>: address, city, region, country, ...</p></li><li><p><strong>Event</strong>: meeting, transaction, communication, ...</p></li><li><p><strong>Object</strong>: device, software, document, task, topic, project</p></li></ul><p>To learn more, I have a full article on <a href="https://www.decodingai.com/p/agentic-graphrag">agentic GraphRAG</a> and another one on <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">designing an ontology for your context layer</a>.</p><p><strong>Version 2</strong>, the lighter one, is based on LLM wikis, such as Scrabble, my current agent memory. Markdown files with YAML frontmatter and cross-references, sitting directly on top of your existing infrastructure (Obsidian, Notion, Google Drive) &#8212; exactly how Scrabble runs over my own second brain. Google recently formalized this pattern as the Open Knowledge Format (OKF), a vendor-neutral directory of markdown + YAML whose only required field is <code>type</code> <a href="https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing">[3]</a>. The filesystem is the state; no database required.</p><p><strong>Which do you pick?</strong> It depends on how much control over the data model you want and your technical depth. Personally, I use both: Scrabble for everyday research across my second brain, and I plan to use Tree when I need precision at scale. Such as mining high-signal knowledge from 10,000+ documents.</p><p>Still, when it comes to implementing a unified memory layer on top of a knowledge graph, I keep getting asked one question: is a single database (MongoDB) enough? Why not throw in a specialized graph database like Neo4j or a vector database like Pinecone?</p><h2>Is MongoDB Enough?</h2><p>The simplest system that works wins. Instead of 3 databases (a SQL/NoSQL store, a vector DB, and a graph DB), you want one store that does all three. The payoff is concrete: far less operational overhead (one production DB, not three), less deep expertise required (being a power user of one engine beats being mediocre at three), and the ability to join documents, vectors, and graph in a single query. That last point matters most for memory: a single-store join is faster, cheaper, and lower-latency.</p><p><a href="https://www.mongodb.com/">MongoDB</a> is a good example, because it&#8217;s schema-less, supports all indexing operations, and has a huge ecosystem around it, with both an open-source version and their self-managed Atlas version. Another option I&#8217;ve tried that works well, but with more developer friction, is Postgres.</p><p>Also, as the cherry on top, you get lineage for free. Which is essential for adding references, understanding where each node came from, or simply preparing for an audit. You keep references on each knowledge-graph node instead of copying all data onto it: the document(s) a node was extracted from, the user who owns it, other metadata. That gives you easy lineage and versioning, and lets your memory connect to the rest of your system with no cross-database sync tax.</p><p><strong>Now what about scale?</strong> For personal assistants, where you have only 100-10,000 documents, a single MongoDB cluster is more than enough. But even for medium to big enterprises, you can easily scale to millions of documents by adding more clusters (aka horizontal scaling).</p><p>After a conversation with a principal MongoDB engineer I understood that the real bottleneck is RAM. RAM is the most expensive component from your database cluster and you want to keep it as low as possible.</p><p>So index only what you query. Your memory holds 2 snapshots of the same knowledge: an append-only log (the immutable record of everything ingested) and a materialized view (the queryable graph rebuilt from that log). Vector indexes are inverted indexes &#8805; the data they cover, so indexing both blows ~10 GB of data up toward ~40 GB of RAM.</p><p>Keep the log on disk (no vector index) and index only the materialized view, and it collapses back toward ~10 GB with the same data, at a quarter of the RAM.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NMXo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NMXo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 424w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 848w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 1272w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NMXo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png" width="1400" height="618" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:618,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Vector-indexing both snapshots inflates ~10 GB of data toward ~40 GB of RAM; index only the materialized view and it collapses back toward ~10 GB.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Vector-indexing both snapshots inflates ~10 GB of data toward ~40 GB of RAM; index only the materialized view and it collapses back toward ~10 GB." title="Vector-indexing both snapshots inflates ~10 GB of data toward ~40 GB of RAM; index only the materialized view and it collapses back toward ~10 GB." srcset="https://substackcdn.com/image/fetch/$s_!NMXo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 424w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 848w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 1272w, https://substackcdn.com/image/fetch/$s_!NMXo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff370b6c4-e1ce-4802-98b9-f5da8230fbf9_1400x618.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Vector-indexing both snapshots inflates ~10 GB of data toward ~40 GB of RAM; index only the materialized view and it collapses back toward ~10 GB.</em></figcaption></figure></div><p><strong>When does it make sense to use a specialized graph DB like Neo4j?</strong> The reality is that for most use cases, you will do only 2-3 hops traversals. Such as getting all the preferences of a user, and the documents/conversations they were extracted from. In these cases, a single database that does it all is amazing. But there are cases when you should reach for a specialized graph DB like Neo4j. For example, when you need to do 3+ hop traversals, your whole business logic relies on graphs or simply as an internal visualization tool. You could sync your MongoDB production database to Neo4j, just for exploration reasons, as their Cypher engine + visualization ecosystem is stronger.</p><h2>Using Your Context Layer With Any Agent</h2><p>The wiki version is the simplest to switch between agents. If your context layer is shipped as an LLM wiki, switching harnesses is just handing the new harness a path. For this article, I literally pointed the harness at the research wiki folder from my Second Brain. Without any fancy skills or plugins in place.</p><p>Or a step further, is to point it at my entire second brain &#8212; that&#8217;s Scrabble &#8212; whose <code>AGENTS.md</code> explains how to navigate it and which CLI tools and skills to use. It works out of the box because it&#8217;s just files.</p><p>The MCP version is a bit more work, but not much. Serving memory over an MCP server means re-pointing one config entry from one harness to the next &#8212; switch from Claude Code to Codex by configuring the path to your MCP server, and your whole memory moves with almost zero friction, regardless of harness or model.</p><p>Each MCP server ships its own tools (read tools and write tools), and the tool descriptions are the contract the agent reads. It gets especially interesting on the write side, where the tools decide when to persist (e.g. parsing a whole conversation into memory when it ends).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Qrw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Qrw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 424w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 848w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 1272w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Qrw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png" width="1200" height="1034" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1034,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The MCP server serves the same memory, skills, and UI to any harness and any interface.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The MCP server serves the same memory, skills, and UI to any harness and any interface." title="The MCP server serves the same memory, skills, and UI to any harness and any interface." srcset="https://substackcdn.com/image/fetch/$s_!8Qrw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 424w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 848w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 1272w, https://substackcdn.com/image/fetch/$s_!8Qrw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74b95bcc-d207-4f47-95ba-03311f4500ae_1200x1034.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em> The MCP server serves the same memory, skills, and UI to any harness and any interface.</em></figcaption></figure></div><p>Skills are where the leverage compounds. On top of this memory, you can write deep-research, writing, or coding-agent skills that remember your preferences. A few of mine, all part of Scrabble:</p><ul><li><p><code>/research</code>, which runs deep research on a topic and produces a localized wiki (I have an open-source version in my latest <a href="https://github.com/iusztinpaul/ai-research-os-workshop">ai-research-os-workshop</a> talk made for the AI Engineer World&#8217;s Fair SF - <a href="https://www.youtube.com/watch?v=ZRM_TfEZcIo">full video</a>);</p></li><li><p><code>/article-guideline</code>, which expands a brain dump into an article plan anchored in a wiki;</p></li><li><p><code>/squid:plan</code>, part of my <a href="https://github.com/iusztinpaul/squid">Squid</a> software factory, which plans a feature from my spec, codebase, and memory &#8212; injecting my personal takes on how I write software.</p></li></ul><h2>What&#8217;s Next</h2><p>Agent memory is an unsolved, fast-moving topic. These designs work, but they&#8217;re far from perfect, and your data is still segregated across Obsidian, Notion, local files, and messages in ways that are hard to unify. In practice, I lean on the lighter wiki-based approach. One per project does the job. I reserve Tree&#8217;s heavy knowledge-graph memory for the few high-precision cases that earn its cost.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>Your data can move between harnesses, but can your skills? I have this issue with Claude Code&#8217;s workflows and agents embedded into my skills.</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/the-context-layer/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/the-context-layer/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/the-context-layer?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.decodingai.com/p/the-context-layer?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p><em>Special thanks to <a href="https://www.mongodb.com/">MongoDB</a> for sponsoring this article and keeping it free!</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.mongodb.com/" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg" width="1200" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48258,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://www.mongodb.com/&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/203854945?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!c1Gm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!c1Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F143757ba-2cb8-4d2f-be0e-dbd29fcbb7d0_1200x400.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Explore Next</h2><ol><li><p>LangChain. (n.d.). Open Models, Open Runtime, Open Harness &#8212; Building Your Own AI Agent With LangChain and Nvidia. YouTube. <a href="https://youtube.com/watch?v=BEYEWw1Mkmw">https://youtube.com/watch?v=BEYEWw1Mkmw</a></p></li><li><p>Soria Parra, D. (n.d.). The Future of MCP. YouTube. <a href="https://www.youtube.com/watch?v=v3Fr2JR47KA">https://www.youtube.com/watch?v=v3Fr2JR47KA</a></p></li><li><p>McVeety, S., &amp; Hormati, A. (n.d.). Introducing the Open Knowledge Format. Google Cloud.<a href="http://The MCP server serves the same memory, skills, and UI to any harness and any interface."> https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing</a></p></li><li><p>getzep. (n.d.). Graphiti. GitHub. <a href="http://The MCP server serves the same memory, skills, and UI to any harness and any interface.">https://github.com/getzep/graphiti</a></p></li><li><p>Neo4j Labs. (n.d.). agent-memory. GitHub. <a href="https://github.com/neo4j-labs/agent-memory">https://github.com/neo4j-labs/agent-memory</a></p></li><li><p>mem0ai. (n.d.). mem0. GitHub. <a href="https://github.com/neo4j-labs/agent-memory">https://github.com/mem0ai/mem0</a></p></li><li><p>topoteretes. (n.d.). cognee. GitHub. <a href="https://github.com/topoteretes/cognee">https://github.com/topoteretes/cognee</a></p></li><li><p>getzep. (n.d.). Zep. <a href="https://www.getzep.com/">https://www.getzep.com/</a></p></li><li><p>HydraDB. (n.d.). HydraDB. <a href="https://www.getzep.com/">https://hydradb.com/</a></p></li><li><p>Iusztin, P. (n.d.). ai-research-os-workshop. GitHub. <a href="https://github.com/iusztinpaul/ai-research-os-workshop">https://github.com/iusztinpaul/ai-research-os-workshop</a></p></li><li><p>Iusztin, P. (n.d.). squid. GitHub. <a href="https://github.com/iusztinpaul/squid">https://github.com/iusztinpaul/squid</a></p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[How Evaluation-Driven Development (EDD) Works]]></title><description><![CDATA[Turn every AI agent change into a measured experiment you compare before and after to detect regressions and measure performance.]]></description><link>https://www.decodingai.com/p/how-evaluation-driven-development-works</link><guid isPermaLink="false">https://www.decodingai.com/p/how-evaluation-driven-development-works</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 23 Jun 2026 08:57:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!opgq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!opgq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!opgq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!opgq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!opgq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!opgq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!opgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Hold the before and the after up to the light &#8212; and don't open the gate until you know which ray went dark.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Hold the before and the after up to the light &#8212; and don't open the gate until you know which ray went dark." title="Hold the before and the after up to the light &#8212; and don't open the gate until you know which ray went dark." srcset="https://substackcdn.com/image/fetch/$s_!opgq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!opgq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!opgq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!opgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca8875b3-6a98-444f-9b68-0085006c19f1_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The scariest AI failures are the silent ones.</p><p>You ship a change to your agent on a branch &#8212; a new feature, a prompt fix, a quick refactor. No errors. No complaints. Everything <em>looks</em> fine. But does it still work, or did you quietly break something that worked yesterday?</p><p>As Alejandro Aboy puts it: <em>&#8220;the fact that they&#8217;re not complaining doesn&#8217;t mean there&#8217;s no issue going on.&#8221;</em> A quiet user is not a happy user. Usually, it&#8217;s the opposite.</p><blockquote><p>The more Alejandro and I talked about AI evals and EDD, the more his struggles sounded like mine. A story from builders to builder.</p></blockquote><p><strong>1. You can break what already worked.</strong> Change a prompt, refactor a tool, and an old feature quietly regresses. Alejandro lived it: cleaning noisy instructions out of his agent&#8217;s system prompt made it start fabricating IDs it used to get right. You only catch that by running the same tests before and after the change, and comparing.</p><p><strong>2. The feature is brand new, so you have nothing to test it on.</strong> No dataset, no historical traces, no ground truth. Yet you still need to know whether it works, and how well. So how do you generate realistic test data fast, then feed it to evaluators that turn it into hard performance numbers?</p><p>This is the case study that gives you a plan of attack for both: <strong>Evaluation-Driven Development (EDD)</strong></p><p>How to prove a new feature works, and didn&#8217;t regress, <em>before</em> you merge. It comes from a recent conversation with <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Alejandro Aboy&quot;,&quot;id&quot;:22949723,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82b06564-e92e-44ba-80d7-0a45455d7ab7_1003x1003.png&quot;,&quot;uuid&quot;:&quot;8ebabe2d-0981-4315-8d99-d44100e5187a&quot;}" data-component-name="MentionToDOM"></span>, a senior data and AI engineer at Workpath who owns the entire data stack, built the Workpath AI Companion, and writes <em>The Pipe and The Line</em> Substack.</p><p>And we won&#8217;t keep it abstract. Every example comes from one real product: <strong>Workpath</strong>, a strategy-execution SaaS that keeps large companies&#8217; OKRs and initiatives aligned. (OKRs &#8212; Objectives and Key Results &#8212; are the goal-setting framework teams use to name what they want to achieve and the measurable results that prove they&#8217;re getting there.) Its AI-native feature is the <strong>Workpath AI Companion</strong>: an agent that scans a company&#8217;s strategy and OKR data end-to-end to keep enterprise teams aligned. It&#8217;s the exact system Alejandro runs EDD on every day.</p><p>So when we say <em>developing a new feature</em>, picture shipping a change to that Companion and proving, before you merge, that it works and didn&#8217;t regress.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AcZy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AcZy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 424w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 848w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 1272w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AcZy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png" width="1200" height="832" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:832,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The moving parts &#8212; Claude Code drives a headless agent, Agno enriches its trace, and Opik stores and scores everything.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The moving parts &#8212; Claude Code drives a headless agent, Agno enriches its trace, and Opik stores and scores everything." title="The moving parts &#8212; Claude Code drives a headless agent, Agno enriches its trace, and Opik stores and scores everything." srcset="https://substackcdn.com/image/fetch/$s_!AcZy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 424w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 848w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 1272w, https://substackcdn.com/image/fetch/$s_!AcZy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1ec3350d-e9cb-45f1-a7b7-d95a966fc5e5_1200x832.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The moving parts</em></figcaption></figure></div><h2>The Develop-a-Feature Workflow</h2><p>Imagine. You start working on a new feature, branch, and develop the change. But before you merge, you have to answer 2 questions:</p><ol><li><p>What&#8217;s the performance of my new feature?</p></li><li><p>Did my change introduce any regressions into the existing codebase?</p></li></ol><p>Only when both look good you accept the pull request. EDD helps you answer those 2 questions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jIGa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jIGa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 424w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 848w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 1272w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jIGa!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png" width="984" height="331.74857142857144" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:472,&quot;width&quot;:1400,&quot;resizeWidth&quot;:984,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;EDD is the offline gate between developing a change and merging it &#8212; it answers \&quot;does it work?\&quot; and \&quot;did it regress?\&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="EDD is the offline gate between developing a change and merging it &#8212; it answers &quot;does it work?&quot; and &quot;did it regress?&quot;" title="EDD is the offline gate between developing a change and merging it &#8212; it answers &quot;does it work?&quot; and &quot;did it regress?&quot;" srcset="https://substackcdn.com/image/fetch/$s_!jIGa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 424w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 848w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 1272w, https://substackcdn.com/image/fetch/$s_!jIGa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1813e19e-2dd7-42ca-a4f1-24ae965d54b6_1400x472.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>EDD is the offline validation gate between developing a change and merging it</em></figcaption></figure></div><p>Every feature is hypothesis-first. As Alejandro frames it, <em>&#8220;I have a hypothesis... and everything should lie around that.&#8221;</em> Every change starts as a stated hypothesis on a branch.</p><p>Based on that hypothesis, EDD runs a simulation and scores the results to answer the 2 questions.</p><p>Every feature ends in a PR, backed by an experiment, with clear traces and metrics. Framing the eval results as an experiment allows you to compare current results to previous ones, detecting regressions or tracking improvements.</p><p>This is how you can compare two experiments in Opik:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MJ44!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MJ44!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 424w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 848w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png" width="1456" height="594" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:594,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Comparing two experiments in Opik&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Comparing two experiments in Opik" title="Comparing two experiments in Opik" srcset="https://substackcdn.com/image/fetch/$s_!MJ44!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 424w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 848w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Comparing two experiments in Opik</em></figcaption></figure></div><p>What about the process that happens between starting a new feature and its experiment?</p><h4>From an architectural perspective, we have:</h4><ul><li><p>The <strong>AI application</strong>, which can be an AI agent, workflow or a simple chatbot. In Alejandro&#8217;s case, it&#8217;s an AI agent built with Agno. More precisely, it&#8217;s the Workpath AI Companion he is building. But due to data privacy reasons, during the demo, he could share only a mock of the data.</p></li><li><p>A <strong>headless evaluation harness</strong>, powered by Claude Code.</p></li><li><p>An <strong>AI observability and evaluation platform</strong> responsible for capturing traces, managing eval datasets and evaluators, running experiments and comparing results. Alejandro is using <a href="https://github.com/comet-ml/opik">Opik</a>. The tool is open-source, but for ease of use, you can also try out their managed platform for free <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">here</a> for 25k spans/month.</p></li></ul><p>Now... how do we generate data for these experiments? How do we get the traces? How do we populate the evaluation harness with the right context? We will see how all of that falls into place, where everything starts with two modes.</p><h2>Two Modes: Manual Quick Check vs. Automated Experiments</h2><p>The two modes are modeled by the <code>/edd</code> skill, which has two inputs: Mode and Aggression.</p><p><strong>Mode 1</strong> is a quick, manual check. You fire around 30 fresh traces, let Claude Code read them back from Opik one by one, and trigger a judge by hand only if you want a score. As Alejandro describes it, <em>&#8220;it won&#8217;t trigger automatic evaluations; you trigger them manually.&#8221;</em> No dataset, no experiment, ephemeral, minutes. His favorite for a small change: his Substack Author Agent kept over-asking for the publication URL on every new trace. A tiny, targeted fix, exactly what Mode 1 is for.</p><p><strong>Mode 2</strong> automates the judgment. When you touch a lot or ship new functionality, you turn the traces into a dataset and run an experiment, both Opik objects, where the judges score every item automatically and produce an experiment you can compare across runs. This is the only way to catch a subtle regression, because you compare 2 experiments.</p><p>Both modes start from a hypothesis on a branch, emit fresh simulated traces, and can use the same evaluators. The mode only changes whether the evaluation is done by hand or automatically.</p><p>The <strong>Aggression setting</strong> controls how adversarial the simulated traces get, from happy-path up to fully adversarial. As you turn up the knob, simulated traces get more aggressive, finding harder and harder corner cases to break the agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JD2l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JD2l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 424w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 848w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 1272w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JD2l!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png" width="1008" height="647.28" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:899,&quot;width&quot;:1400,&quot;resizeWidth&quot;:1008,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The skill's decision flow &#8212; a small change takes the quick Mode 1 path; new functionality takes the Mode 2 dataset-and-experiment path.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="The skill's decision flow &#8212; a small change takes the quick Mode 1 path; new functionality takes the Mode 2 dataset-and-experiment path." title="The skill's decision flow &#8212; a small change takes the quick Mode 1 path; new functionality takes the Mode 2 dataset-and-experiment path." srcset="https://substackcdn.com/image/fetch/$s_!JD2l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 424w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 848w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 1272w, https://substackcdn.com/image/fetch/$s_!JD2l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9266d723-6f23-405c-8dcb-bf71c5493ace_1400x899.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The skill&#8217;s decision flow: A small change takes the quick Mode 1 path, while new functionality takes the Mode 2 dataset-and-experiment path.</em></figcaption></figure></div><p>The secret sauce of Alejandro&#8217;s EDD approach is in how he uses Claude Code to simulate fresh traces.</p><h2>Scope the Change and Simulate Its Traces</h2><p>Remember. Our goal is to simulate relevant traces to test the performance of our feature. To do that, we use Claude Code to read the agent&#8217;s source code, especially the code around the new feature. After, we retrieve old traces (stored in Opik) that are relevant to our current code. </p><p>Based on these two signals, we generate ~30 traces targeting the new feature&#8217;s functionality.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uUqd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uUqd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 424w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 848w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 1272w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uUqd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png" width="1400" height="508" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:508,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The evals can only see what the trace carries &#8212; so the trace has to carry the whole harness, not just the answer.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The evals can only see what the trace carries &#8212; so the trace has to carry the whole harness, not just the answer." title="The evals can only see what the trace carries &#8212; so the trace has to carry the whole harness, not just the answer." srcset="https://substackcdn.com/image/fetch/$s_!uUqd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 424w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 848w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 1272w, https://substackcdn.com/image/fetch/$s_!uUqd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F276950ac-3f87-4242-ae76-7d5ebef0c393_1400x508.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The evals can only see what the trace carries. So the trace has to carry the whole harness, not just the answer.</em></figcaption></figure></div><p>The traces need to be high signal and as diverse as possible. The goal is to find holes within our system and fix them, not to validate what currently works. </p><p>To achieve that, the traces are generated based on 2 dimensions:</p><ul><li><p><em>Regression evals</em> (what worked still works) vs. <em>capability evals</em> (can do it on new things</p></li><li><p><em>Happy path</em> (easy: testing the core logic) vs. <em>adversarial</em> (hard: finding edge cases, such as missing data, faulty tool descriptions or guardrails)</p></li></ul><p>During generation, we can configure these parameters. For example, if we go full adversarial, the probability of finding errors increases. Which isn't necessarily a good thing, as you don&#8217;t want to overoptimize in advance either. You want to make the system as good as possible on the hot path. You don&#8217;t want to waste time on scenarios that might never happen. That&#8217;s why anchoring your trace generation to existing traces is an essential step for properly understanding the user&#8217;s behavior and which components to target when generating the traces.</p><blockquote><p>&#9888;&#65039; <strong>Important!</strong> Even if we simulate the data, we still want REAL traces and outputs to evaluate on.</p></blockquote><p><strong>This is what we have to do.</strong> The pipeline starts from the data, not from invented inputs. Claude Code analyzes the current traces to learn what inputs are worth generating, so we <strong>simulate only the inputs, NOT the outputs or internal state.</strong></p><p>That&#8217;s the whole point. Synthesize the outputs too and you hit Alejandro&#8217;s problem: <em>&#8220;every time I try synthetic datasets, I was losing everything the agent was doing beyond the response.&#8221;</em> Grade the final answer alone and a wrong tool call stays invisible.</p><p>To get there, we send each simulated input to a headless copy of the agent, which runs for real: selecting tools, calling the staging backend, handling whatever comes back. As it runs, Agno records the full tool-call history and outputs into its OpenTelemetry trace, and the agent emits it to Opik.</p><p>Using this strategy, we simulate the inputs, run the agent, and record the trace with real values produced by the agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GXvk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GXvk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 424w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 848w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 1272w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GXvk!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png" width="1010" height="706.1675824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1018,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1010,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!GXvk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 424w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 848w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 1272w, https://substackcdn.com/image/fetch/$s_!GXvk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7ca37f6-6b19-4678-a857-081ca79038ed_2428x1698.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>A single simulated trace in Opik</em></figcaption></figure></div><p>A simulated trace is only as trustworthy as the state the agent was in when it ran, and recreating that state is the hardest part.</p><h2>Context Population: Mocking Production State</h2><p>The hardest part of agentic evals is getting the agent into the right state, so it passes or fails for reasons that actually relate to your hypothesis. A trace generated from the wrong state is a useless trace.</p><p>In Alejandro&#8217;s use case, roughly 90% of the agent&#8217;s tools are API calls, so Claude Code gets a token and hits the real internal backend through a staging mocked account that already holds data. For the happy path, it pulls real goals, OKRs, and teams. To go adversarial, it forces errors and asks for data that doesn&#8217;t exist.</p><p>The reusable trick is where the context gets injected. Before the agent boots, Claude Code calls the API and injects the user&#8217;s context into dedicated system-prompt sections. So the agent greets you with <em>&#8220;Hi Paul, want to check goals from the coding AI team?&#8221;</em> It runs <em>&#8220;as if for real.&#8221;</em></p><p>Alejandro is explicit that this is not pytest-style fixtures, but <em>&#8220;the prompt is the only thing the LLM sees.&#8221;</em> A faithful prompt-level state is a faithful enough production proxy. You mock at the system-prompt layer and stop worrying about reproducing the whole backend.</p><p>So instead of using the standard way of using fixtures to populate the backend, you can bypass everything and directly inject the context into the system prompt. From the LLM&#8217;s perspective, it&#8217;s the same thing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QxfE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QxfE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 424w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 848w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 1272w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QxfE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png" width="1073" height="559" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:559,&quot;width&quot;:1073,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Mock the state at the system-prompt level, hit a real staging backend, and the agent runs as if in production.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Mock the state at the system-prompt level, hit a real staging backend, and the agent runs as if in production." title="Mock the state at the system-prompt level, hit a real staging backend, and the agent runs as if in production." srcset="https://substackcdn.com/image/fetch/$s_!QxfE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 424w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 848w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 1272w, https://substackcdn.com/image/fetch/$s_!QxfE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a74f723-8dbb-43f3-9594-6555739931e4_1073x559.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Mock the state at the system-prompt level, hit a real staging backend, and the agent runs as if in production.</em></figcaption></figure></div><p>The last step is to transform the traces into an evals dataset.</p><h2>On-Demand Datasets</h2><p>You want two types of eval datasets:</p><ol><li><p>A persistent, hand-built evaluation set that tests the core business logic. Useful for catching regressions.</p></li><li><p>An on-demand, synthetic dataset used to evaluate the feature you are working on.</p></li></ol><p>We are interested here in the second option.</p><p>Via the <code>/edd</code> skill Claude Code assembles an Opik dataset, on the fly, from the branch-tagged simulated traces. The dataset is tagged so a later run can filter straight to it, then kept or thrown away.</p><p>Before committing to a big sample, Alejandro fires a couple of runs as smoke checks, <em>&#8220;to catch anything awful&#8221;</em> before spending tokens. Then he checks that the dataset&#8217;s coverage is good enough to be worth running an experiment against. Small, cheap, and it saves the expensive mistake.</p><p>Because the dataset is cheap to regenerate and scoped to one change, it&#8217;s disposable. Optionally, you might promote a couple of high signal traces into the persistent regression set.</p><p>A dataset is only useful once you&#8217;ve decided what metrics to use &#8212; aka the judges.</p><h2>Define the Judge</h2><p>You want to support 2 evaluator types.</p><p><strong>Code metrics</strong> score the structural things deterministically, server-side, free, no LLM, like whether it called the tool or whether the format is right. Always try to evaluate a given metric via code metrics if possible.</p><p><strong>LLM judges</strong> score the subjective things, like completeness, accuracy, and ranking quality.</p><p>Both evaluators are designed as binary classifiers: verified, or not. The urge to introduce 1-5 likert scales is huge. But the thing is that it&#8217;s incredibly difficult to get it right. What&#8217;s the difference between 2 and 3 or 4 and 5? Even when using multiple human annotators, the labels are inconsistent. With binary labels, the decision is clear: it&#8217;s correct or not. Which makes it incredibly easy for the LLM to get it right.</p><p>To get some nuance, on top of the binary labels, you want to add a critique that explains in 2-3 sentences why the output is correct or not.</p><p>The judge model is deliberately a different model than the agent, so the two don&#8217;t share blind spots and the judge can&#8217;t rubber-stamp its own family&#8217;s mistakes.</p><p>But here is the trick! The evaluators are static, carefully defined and calibrated up front from the codebase. The loop regenerates traces and datasets, not the metrics. When implementing LLM judges, it&#8217;s extremely important to align them with the domain expert. Once they are working well, you can use them for inference, which we are doing here on the dynamic datasets.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zrh6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zrh6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 424w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 848w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zrh6!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png" width="1044" height="455.3159340659341" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:635,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1044,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!zrh6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 424w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 848w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!zrh6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F620b20f7-a725-445e-bc36-18d4b9be1753_2936x1280.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Opik&#8217;s Insights view turns each judge into a per-dimension score profile for the run.</em></figcaption></figure></div><p>The judges are configured within Opik, using their API to call the model to score each sample from the dataset.</p><p>In the image below, you can see the evaluators Alejandro configured for each experiment:</p><ul><li><p>Content Completeness</p></li><li><p>Metric Accuracy</p></li><li><p>Ranking Quality</p></li><li><p>Relative Grounding</p></li><li><p>Response Directness</p></li><li><p>Semantic Search Accuracy</p></li><li><p>Skill Selection</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CNQw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CNQw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 424w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 848w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CNQw!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png" width="1096" height="388.4175824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:516,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1096,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CNQw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 424w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 848w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 1272w, https://substackcdn.com/image/fetch/$s_!CNQw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17033b01-aa15-49d7-a6e6-d504048eced4_2926x1036.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The evaluator suite Alejandro runs on every experiment. One judge per dimension, scoring the whole dataset.</em></figcaption></figure></div><p>With the dataset built and the judges defined, you run the experiment. And you run it twice.</p><h2>Run and Compare Experiments</h2><p>The experiment runs in Opik, scoring the dataset against all the judges to produce a score distribution.</p><p>In a feature Alejandro was working on, he cleaned all the noisy instructions out of his agent&#8217;s system prompt, <em>&#8220;hygiene before&#8221;</em> vs. <em>&#8220;hygiene after,&#8221;</em> and ran 2 experiments over the same scope in Opik&#8217;s comparison view.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mWkj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mWkj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 424w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 848w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 1272w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mWkj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png" width="1456" height="589" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:589,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Run the same scope twice and the regression you introduced shows up as one short bar.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Run the same scope twice and the regression you introduced shows up as one short bar." title="Run the same scope twice and the regression you introduced shows up as one short bar." srcset="https://substackcdn.com/image/fetch/$s_!mWkj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 424w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 848w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 1272w, https://substackcdn.com/image/fetch/$s_!mWkj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F445836b8-2b99-4d09-a10a-c5393dfd0cf2_1760x712.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Run the same scope twice and the regression you introduced shows up as one short bar.</em></figcaption></figure></div><p>The <em>after</em> had regressed on one judge: tool-call parameter inference. The agent should remember which ID to pass to a tool, but the cleanup made it <em>&#8220;get lost and fabricate IDs.&#8221;</em> EDD caught his own change before it shipped.</p><p>Comparison matters because failure hides where a single trace can&#8217;t show it. Trace-level evals are usually fine, but problems surface across 5, 10, or 20-message conversations. Around the 10th message, the model slides into a <em>&#8220;context rot zone&#8221;</em>: a request that earlier earned a cooperative <em>&#8220;let&#8217;s work with this&#8221;</em> now gets <em>&#8220;what do you mean by that?&#8221;</em></p><p>A user asks the agent to <em>&#8220;scan 50 teams, get me all the OKRs.&#8221;</em> It pushes back and offers to go progressively, returning 17 copy-pasteable tables. But by trace 21 of a 20-message conversation, you&#8217;re at 200k total tokens, paying heavily without caching.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MJ44!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MJ44!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 424w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 848w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png" width="1456" height="594" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:594,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!MJ44!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 424w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 848w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1272w, https://substackcdn.com/image/fetch/$s_!MJ44!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c347d8-ed96-4989-8bd8-8f61587a0b2c_2974x1214.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The same scope, before vs after, overlaid in Opik. One regressed dimension can&#8217;t hide across the judges.</em></figcaption></figure></div><p>These are the kinds of errors proper evals protect you from! Not only performance, but also latency and cost issues that can blow up your infrastructure overnight.</p><h2>Don&#8217;t Run Online Evals</h2><p>Everything so far ran offline, on a branch, before the merge. The expensive default everyone reaches for instead is always-on online evals. That&#8217;s the trap.</p><p>Alejandro made the same mistake.</p><p>He thought running online evaluations on all the traces was essential for production. Until the bill! It was on credits, not cash, but it would have been around $2k a month just from triggering a few evaluations: <em>&#8220;the bill just pops in &#8212; in one second you have thousands of dollars in debt.&#8221;</em></p><p>So you recalibrate. What&#8217;s the actual risk of evaluating whether the agent leaked an ID to the user? Low. So you sample or look for a pattern, run the heavy judges offline, and cap spend first: <em>&#8220;consume an amount you know you can afford.&#8221;</em></p><blockquote><p><strong>The good news?</strong> The whole <code>/edd</code> skill and headless harness implemented by Alejandro via Opik is now an <a href="https://github.com/aboyalejandro/eval-driven-development">installable open-source Claude Code plugin</a>. You can also create a free account on <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik</a> with <em>25k spans/month</em> to try out this EDD strategy on your own project.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nQe4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nQe4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 424w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 848w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nQe4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png" width="1456" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Opik Dataset&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Opik Dataset" title="Opik Dataset" srcset="https://substackcdn.com/image/fetch/$s_!nQe4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 424w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 848w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!nQe4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24590605-5526-432d-a9d3-fd49543a10c3_3358x1260.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The offline eval dataset</em></figcaption></figure></div><div><hr></div><div class="callout-block" data-callout="true"><h4>&#127909; Watch the full conversation between Alejandro Aboy and me</h4><div id="youtube2-1zuGTgHQGcM" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;1zuGTgHQGcM&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/1zuGTgHQGcM?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></div><div><hr></div><h2>Final Thoughts</h2><blockquote><p>You&#8217;re already driving one AI process with another. Would you hand the whole thing over to an agent that reads the traces, understands the agent&#8217;s mistakes, gets the signal from the evaluators and writes the code changes itself?<br>&#8212; Paul</p></blockquote><p>Alejandro would want exactly that, on one condition. He&#8217;s tried prompt-only optimizers and doesn&#8217;t trust them, because they change the prompt but never test the agent&#8217;s full harness. Until then, the human stays in the loop, and every change earns its pull request.</p><blockquote><p>Opik has been shipping exactly that: Test Suites, Agent Configuration and Playground. Where does your hand-rolled loop go from here?<br>&#8212; Paul</p></blockquote><p>Because they tackle the prompt-only-optimization gap, Alejandro is bullish on adopting them &#8212; he expects they&#8217;ll close the whole agentic loop: analyze the code &amp; failures &#8594; generate inputs &#8594; call the agent &#8594; build a dataset &#8594; evaluate each sample &#8594; fix the code &#8594; repeat, all in one place.</p><p>Try out Alejandro&#8217;s EDD code on <a href="https://github.com/aboyalejandro/eval-driven-development">GitHub</a>, while leveraging <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik&#8217;s free tier</a> as the observability platform.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>Where do you draw the line between online and offline evals? What do you actually run always-on in production, and how do you cap the spending?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/how-evaluation-driven-development-works/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/how-evaluation-driven-development-works/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/how-evaluation-driven-development-works?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/how-evaluation-driven-development-works?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><p><em>Thanks again to <a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Opik</a> for sponsoring this case study and keeping it free!</em></p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oSDm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 424w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 848w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1272w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png" width="1456" height="364" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:364,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Opik Banner&quot;,&quot;title&quot;:&quot;Opik Banner&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Opik Banner" title="Opik Banner" srcset="https://substackcdn.com/image/fetch/$s_!oSDm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 424w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 848w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1272w, https://substackcdn.com/image/fetch/$s_!oSDm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c21863-4ee6-4026-91c7-74650eb16dac_3168x792.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption"><a href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul">Try Opik for free here</a> (25k spans/month free)</figcaption></figure></div><p><strong>If you want to monitor, evaluate and optimize your AI workflows and agents:</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul&quot;,&quot;text&quot;:&quot;Try Opik for free&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://www.comet.com/site/?utm_source=newsletter&amp;utm_medium=partner&amp;utm_campaign=paul"><span>Try Opik for free</span></a></p><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Build, Configure, or Use As-Is: The Agentic Harness]]></title><description><![CDATA[A component-by-component teardown of an agentic harness, from tools and skills to memory, sandbox, and permissions.]]></description><link>https://www.decodingai.com/p/agentic-harness-system-design</link><guid isPermaLink="false">https://www.decodingai.com/p/agentic-harness-system-design</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 09 Jun 2026 05:00:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qdmn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qdmn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qdmn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qdmn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1466419,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/200891005?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qdmn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!qdmn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc4bb167-4683-4bec-b335-e44e6efafa57_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Maxime Labonne&quot;,&quot;id&quot;:31453795,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17e73529-4d58-4477-b896-6d1e1f5c9796_896x896.png&quot;,&quot;uuid&quot;:&quot;191ae76b-9f08-4ecb-978b-b953476cb01b&quot;}" data-component-name="MentionToDOM"></span> and I were planning our upcoming book when we kept hitting the same realization. Just as LLMs got commoditized, the harness around them is commoditizing too, hardening into a handful of standardized, batteries-included frameworks. Once it&#8217;s a commodity, the hard question flips. It stops being &#8220;how do I get an agent running&#8221; and becomes &#8220;for each piece, do I build, configure, or just use it?&#8221; And that line is blurry.</p><p>Overbuild, and you burn weeks reimplementing a tool loop, a permission system, and a sandbox that is already available for free. Under-build, and you lean on the defaults forever, never building the one layer that&#8217;s actually yours, your context layer, your moat, so you stay a renter of someone else&#8217;s system.</p><p>The harnesses fall along a spectrum, from tool-like ones you customize as a user (Claude Code, Codex, OpenCode) through framework-type ones you build with, like Pydantic AI in Python or pi in TypeScript.</p><p>This article hands you that system design: the ~80% blueprint that&#8217;s conceptually the same across Claude Code, OpenCode, Codex, and pi, walked component by component, with one conclusion per piece.</p><p>We start with the big-picture architecture, the shape almost every harness shares, then walk it component by component: the tools the model calls, the catalog of agents, how subagents spawn and stay contained, how skills load cheaply, where memory really lives, how sandboxes both protect and scale you, and the permission layer with almost no AI in it. Each one closes on a verdict that fills in the map.</p><div class="callout-block" data-callout="true"><h2><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Build the Layer That&#8217;s Actually Yours (Product)</a></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YHdS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YHdS!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YHdS!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif" width="1200" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;placeholder&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="placeholder" title="placeholder" srcset="https://substackcdn.com/image/fetch/$s_!YHdS!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 424w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 848w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 1272w, https://substackcdn.com/image/fetch/$s_!YHdS!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F221368fb-6f12-4684-9807-e738c255c22e_1200x1200.gif 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This article shows the system design of a harness, the commoditized part. The real value is the business layer you build on top of it. That&#8217;s what my <a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent AI Engineering course</a> teaches, built with Towards AI: only what you need to deliver value, not how to rebuild the harness.</p><p>35 lessons. 3 end-to-end portfolio projects. A certificate. And a Discord community with direct access to industry experts and me.</p><p>Built for software, data engineers or scientists transitioning into AI engineering.</p><p><em>Rated 5/5 by 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p></div><h2>The 80% Every Harness Shares</h2><p>Roughly 80% of a harness&#8217;s blueprint is identical regardless of the tool or framework, because every harness solves the same problems with different techniques. That shared 80% is exactly the part you mostly <em>use as-is</em>. The decisions about what to <em>configure</em> or <em>build</em> live in the remaining slice. At the highest level: a user message goes in, an answer comes out, and everything between is the harness.</p><p>In between, here are the 5 core layers:</p><p>The <strong>Agent</strong> is the innermost piece: the agentic loop (the ReAct loop, where the model reasons then acts) wrapping an LLM plus its tools. The LLM can be closed (Gemini, Anthropic, OpenAI) or open-source served over the OpenAI protocol on Modal, RunPod, GCP, or TogetherAI, or run locally with Ollama or llama.cpp. This loop is the core: strip away compaction, task budgets, and thinking and it&#8217;s roughly 150 lines.</p><p>The <strong>Harness</strong> is everything wrapped around the agent: a message queue with a priority gate, the sandbox, hooks, services (LLM gateway, memory, LSP servers, MCP client), skills, the permission system, an agents catalog, and subagents, with context engineering sprinkled everywhere.</p><p>The <strong>Runtime</strong> is the durable execution layer the whole harness runs inside: Prefect, Temporal, Kitaru. It gives you non-blocking human-in-the-loop, scheduling, durability and caching, and a credentials proxy.</p><p>The <strong>Presentation layer</strong> is how you talk to the harness, whether TUI, web, mobile, WhatsApp, or Telegram. The interesting question is how the <em>same</em> agent serves many front-ends, and there are 2 real patterns. One is a pub/sub bus, OpenCode style, where a headless server streams events to TUI, web, and desktop clients over HTTP+SSE so many clients observe 1 live session. The other is custom services bridging into 1 in-process loop, the Claude Code style.</p><p>The <strong>Observability layer</strong> is tracing, logging, metrics and evals sitting across everything, with tools like Opik, Langfuse, or Braintrust.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2QwS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2QwS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 424w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 848w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2QwS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png" width="1456" height="614" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:614,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The layered anatomy of an agentic harness &#8212; the agentic loop at the core, wrapped by harness services, all running inside a durable runtime, with presentation and observability spanning the stack.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The layered anatomy of an agentic harness &#8212; the agentic loop at the core, wrapped by harness services, all running inside a durable runtime, with presentation and observability spanning the stack." title="The layered anatomy of an agentic harness &#8212; the agentic loop at the core, wrapped by harness services, all running inside a durable runtime, with presentation and observability spanning the stack." srcset="https://substackcdn.com/image/fetch/$s_!2QwS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 424w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 848w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!2QwS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae792e86-7aa3-4a27-b515-9ce157ac0c19_2676x1129.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The layered anatomy of an agentic harness: The agentic loop at the core, wrapped by harness services, all running inside a durable runtime, with presentation and observability spanning the stack.</em></figcaption></figure></div><p>To see how the components connect, let&#8217;s follow a single message down the happy path: user &#8594; TUI &#8594; message queue &#8594; wait for the agent to be free &#8594; agent &#8594; LLM &#8594; tool &#8594; LLM &#8594; tool &#8594; &#8230; &#8594; LLM &#8594; answer &#8594; TUI &#8594; user.</p><p>Meanwhile, The TUI sends and receives over SSE. The priority gate decides when to inject a new message <em>between</em> loops rather than interrupting mid-loop. When the context window nears its limit (tokens &#8805; contextWindow &#8722; reserve), compaction runs, keeping the window as [system prompt] + [summary] + [recent tail]. And a single tool call can fan out into hooks, sandboxes, services, and permission gates.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Q7I0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Q7I0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 424w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 848w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 1272w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Q7I0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png" width="1400" height="656" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:656,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A user message buffered by the priority gate, run through the agentic loop's stream&#8594;check&#8594;tool&#8594;append&#8594;recurse cycle, then streamed back to the TUI as the answer &#8212; with compaction ([system prompt]+[summary]+[recent tail]) kicking in as the context window fills.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A user message buffered by the priority gate, run through the agentic loop's stream&#8594;check&#8594;tool&#8594;append&#8594;recurse cycle, then streamed back to the TUI as the answer &#8212; with compaction ([system prompt]+[summary]+[recent tail]) kicking in as the context window fills." title="A user message buffered by the priority gate, run through the agentic loop's stream&#8594;check&#8594;tool&#8594;append&#8594;recurse cycle, then streamed back to the TUI as the answer &#8212; with compaction ([system prompt]+[summary]+[recent tail]) kicking in as the context window fills." srcset="https://substackcdn.com/image/fetch/$s_!Q7I0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 424w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 848w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 1272w, https://substackcdn.com/image/fetch/$s_!Q7I0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2553bc0-4c0e-4564-bf21-43e7f4773b22_1400x656.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>A user message buffered by the priority gate, run through the agentic loop&#8217;s stream&#8594;check&#8594;tool&#8594;append&#8594;recurse cycle, then streamed back to the TUI as the answer.</em></figcaption></figure></div><p>This skeleton, the loop, the queue, the runtime wiring, the message journey, is the commoditized 80%. As there is a ton going on on top of the basic agentic loop, let&#8217;s explore all the core components of the harness to get an intuition on what can be customized or built on top of it.</p><h2>The Tools</h2><p>The set of tools the LLM can call inside the agentic loop is the most visible part of a harness. Everything the model can invoke conforms to a single shape, a name, an input schema, and an <code>execute</code> method behind a flat registry.</p><p>Ground that in what a real harness ships. Claude Code organizes ~40 built-ins into 10 families, and these are what you get for free:</p><ul><li><p><strong>File I/O:</strong> <code>FileRead</code>, <code>FileWrite</code>, <code>FileEdit</code>, <code>Glob</code>, <code>Grep</code>. The model&#8217;s hands on your files. Read one, write a new one, edit in place, find files by name pattern with <code>Glob</code>, and search their contents with <code>Grep</code>.</p></li><li><p><strong>Execution:</strong> <code>Bash</code>. A single tool to run shell commands. The most powerful tool available that allows an agent to run shell, Python, TypeScript or in general interact with your machine.</p></li><li><p><strong>Orchestration:</strong> <code>EnterPlanMode</code> / <code>ExitPlanMode</code>, <code>Sleep</code>, <code>Agent</code> (spawn a subagent), <code>EnterWorktree</code> / <code>ExitWorktree</code>. These shape the work itself. Plan mode gates edits behind a read-only planning pass, <code>Sleep</code> pauses the loop, <code>Agent</code> spawns a subagent, and the worktree pair carves out an isolated branch to edit without touching the main tree.</p></li><li><p><strong>Tasks:</strong> <code>TaskCreate</code> / <code>Update</code> / <code>Get</code> / <code>List</code> / <code>Output</code> / <code>Stop</code>. A task state machine that lets the agent track a to-do list and run long jobs that outlive a single turn.</p></li><li><p><strong>Web:</strong> <code>WebSearch</code>, <code>WebFetch</code>. The window outward. Search the web, then pull a specific URL&#8217;s contents into context.</p></li><li><p><strong>MCP:</strong> an MCP tool factory + <code>ToolSearch</code>, <code>ListMcpResources</code>, <code>ReadMcpResource</code>, <code>MCPAuth</code>. This is how external tool servers plug in. The factory mints 1 tool per each tool from the MCP server to flatten out the tool discovery logic into a single tool set (e.g., <code>/mcp__brown__edit_content_prompt</code>). <code>ToolSearch</code> surfaces the right one when hundreds are attached, and the rest list resources, read them, and handle auth.</p></li><li><p><strong>Scheduling and misc:</strong> <code>ScheduleCron</code>, <code>RemoteTrigger</code>, <code>Skill</code> (a dispatcher, 1 tool with N skills by argument), <code>LSP</code>, <code>AskUser</code>. The odds and ends. Schedule a run on a cron, trigger one remotely, dispatch a skill by argument, query a language server with <code>LSP</code>, and hand a question back to the human with <code>AskUser</code>.</p></li></ul><p>The built-in tool families are the commoditized surface. The customizer&#8217;s job is to <strong>configure</strong> which tools each agent may call. The architect&#8217;s is to <strong>build</strong> new domain tools as MCP servers plugged into the same registry. That&#8217;s where your product&#8217;s actual capabilities live.</p><p>Tools are <em>what</em> the model can do. The agents&#8217; catalog is <em>who</em> does it.</p><h2>The Agent Catalog Is Just a Config File</h2><p>Each harness ships a set of predefined agents, and the version worth copying defines them as config, not code, because that makes them discoverable and pluggable without touching the loop. The format varies: a markdown file with YAML frontmatter, where the body is the prompt, in pi and Claude Code, or plain YAML or JSON in OpenCode. I reach for YAML, but the point is the same. The core fields are small: <code>name</code>, <code>mode</code>, <code>model</code>, <code>tools</code>, <code>disallowedTools</code>, and <code>permission</code>.</p><p>When you open Claude Code, you chat directly with the primary agent, the primary process. The trickiest part to understand is that both the primary and subagents can wear multiple hats. The agent catalog distcribes these hats, these modes the agent can take on.</p><p>A catalog worth copying looks like this, synthesized across the references (the <code>mode: primary | subagent | all</code> axis is OpenCode&#8217;s, while <code>Plan</code>, <code>Explore</code>, and <code>General Purpose</code> ship in Claude Code):</p><ul><li><p><strong>Build</strong> (mode: primary), the default agent.</p></li><li><p><strong>Plan</strong> (mode: primary), read-only.</p></li><li><p><strong>General Purpose</strong> (mode: subagent), the fallback when no specific agent fits.</p></li><li><p><strong>Explore</strong> (mode: subagent), read-only search and locate, running on a cheap model.</p></li><li><p><strong>Code Reviewer</strong> (mode: subagent), read-only and git/diff-aware.</p></li></ul><p>The <code>code-reviewer</code> subagent (in Claude Code) <code>tools</code> allowlist grants <code>FileRead</code>, <code>Grep</code>, <code>Glob</code>, and <code>Bash(git *)</code>, while its <code>disallowedTools</code> denylist blocks <code>FileEdit</code>, <code>FileWrite</code>, and <code>Bash(rm *)</code>. So it can read the tree and run git, but it can never edit a file or shell out to delete one. That dual allowlist/denylist, with rule syntax like <code>Bash(git *)</code>. The safety trick is that the scope is <em>narrowing only</em>. OpenCode enforces it by deriving a child&#8217;s permissions from its parent&#8217;s, so a delegated agent can never out-permission the one that spawned it.</p><p>Use the bundled agents as-is for everyday work, then author your own as YAML or markdown files. You rarely need to build a custom agent. That usually happens when you build your custom application. For example, I did it only for my deep research and writing skills, which required a ton of customization. Ultimately, ending up as completely apps covered as a skill.</p><p>To get the full picture, let&#8217;s understand how subagents work.</p><h2>A Subagent Is a New Loop</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!weZT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!weZT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 424w, https://substackcdn.com/image/fetch/$s_!weZT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 848w, https://substackcdn.com/image/fetch/$s_!weZT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 1272w, https://substackcdn.com/image/fetch/$s_!weZT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!weZT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png" width="1087" height="351" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:351,&quot;width&quot;:1087,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A main orchestrator spawns a subagent through the Agent tool; the subagent runs its own loop, and only a compressed summary of its output is re-injected into the parent.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A main orchestrator spawns a subagent through the Agent tool; the subagent runs its own loop, and only a compressed summary of its output is re-injected into the parent." title="A main orchestrator spawns a subagent through the Agent tool; the subagent runs its own loop, and only a compressed summary of its output is re-injected into the parent." srcset="https://substackcdn.com/image/fetch/$s_!weZT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 424w, https://substackcdn.com/image/fetch/$s_!weZT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 848w, https://substackcdn.com/image/fetch/$s_!weZT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 1272w, https://substackcdn.com/image/fetch/$s_!weZT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3acbea4f-ba49-4915-8860-1b83ae76c6e8_1087x351.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>A main orchestrator spawns a subagent through the Agent tool; the subagent runs its own loop, and only a compressed summary of its output is re-injected into the parent.</em></figcaption></figure></div><p>Most harnesses support subagents, though some, like pi, do it via plugins instead of natively. The hard part is keeping orchestrator and child communicating without the child&#8217;s full context polluting the parent loop and ensuring the orchestrator, &#8220;orchestrates&#8221; the subagents as expected. Remember that the orchestrator is an agent, not a workflow encoded in code, which means it can easily go off track and forget a step.</p><p>In Claude Code a subagent is <em>not new code</em>. It&#8217;s the same loop re-entered with a cloned context and a restricted tool list, and only a condensed summary flows back. A periodic ~30-second summarizer fork produces a live progress label plus a bounded final summary. The lesson to steal: a subagent is your existing loop, narrowed, with a summary on the return path. Only recently they started introducing subagents as new processes.</p><p>Harnesses almost never support swarm architectures where every agent talks to every other. They support a master&#8211;slave orchestrator topology where one main agent tracks the children.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TacJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TacJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 424w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 848w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 1272w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TacJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png" width="791" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:791,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Parent and subagent talk over a channel that sits outside the isolation boundary &#8212; here a queue the parent awaits, with the child's output compressed before it folds back into the loop.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Parent and subagent talk over a channel that sits outside the isolation boundary &#8212; here a queue the parent awaits, with the child's output compressed before it folds back into the loop." title="Parent and subagent talk over a channel that sits outside the isolation boundary &#8212; here a queue the parent awaits, with the child's output compressed before it folds back into the loop." srcset="https://substackcdn.com/image/fetch/$s_!TacJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 424w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 848w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 1272w, https://substackcdn.com/image/fetch/$s_!TacJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3cb62ab-55e5-42e2-aa0f-f2a8dfed9b29_791x386.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Parent and subagent talk over a channel that sits outside the isolation boundary.</em></figcaption></figure></div><p>Spawning is half the problem. The parent and child still have to talk, and there are three channels, ordered by how far apart the two run.</p><p>Cheapest is <strong>in-process</strong>: the child is a nested call, so its output is just a return value handed back to the caller. A <strong>queue</strong> sits one step out. The parent drops work on a message queue, the child consumes it, and the parent <em>awaits</em> a result event. Because the queue is a shared bus, other clients can watch the same exchange live, the way OpenCode streams a subagent&#8217;s events to many observers. Most decoupled are <strong>shared JSON files</strong>: a lock-serialized mailbox, one file per recipient, that agents in separate processes or worktrees write and poll. pi&#8217;s one-way subprocess, streaming JSON lines back to the parent, is the same idea narrowed to a pipe.</p><p>For most builders this is <strong>use-as-is, lightly configured</strong>. The spawn mechanism and orchestrator topology come standard, and all you configure is each subagent&#8217;s tool and permission scope and which agent it spawns. You only <strong>build</strong> when you need exotic isolation, like pi&#8217;s out-of-process model for untrusted children. That&#8217;s a rare need.</p><p>Now let&#8217;s see how skills fit into the picture.</p><h2>Skills</h2><p>A skill is one of the simplest implementations to understand yet one of the highest-impact things in the whole harness. It&#8217;s essentially a markdown recipe, instructions plus an allowed-tool set, that the model pulls in on demand.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ujpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ujpr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 424w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 848w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 1272w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ujpr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png" width="1456" height="424" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:424,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Skills from three sources (bundled, user-defined, MCP prompts) are merged, capped at ~1% of the context window, assembled into a skills context, and injected as a system reminder.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Skills from three sources (bundled, user-defined, MCP prompts) are merged, capped at ~1% of the context window, assembled into a skills context, and injected as a system reminder." title="Skills from three sources (bundled, user-defined, MCP prompts) are merged, capped at ~1% of the context window, assembled into a skills context, and injected as a system reminder." srcset="https://substackcdn.com/image/fetch/$s_!ujpr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 424w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 848w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 1272w, https://substackcdn.com/image/fetch/$s_!ujpr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F915659a5-a406-4169-b9f4-d10cd3ac7214_1610x469.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Skills from three sources (bundled, user-defined, MCP prompts) are merged, capped at ~1% of the context window, assembled into a skills context, and injected as a system reminder.</em></figcaption></figure></div><p>Concretely, skills come from 3 sources merged together: bundled skills shipped with the harness (e.g. <code>src/skills/bundled</code>), defined skills dropped into <code>.agents/skills</code>, and MCP server prompts. The pipeline is short. A <code>GetSkills</code> step collects all 3 sources, caps the total at ~1% of the context window, assembles a single skills context, and wraps it as a <code>&lt;system_reminder&gt;</code>.</p><p>That 1% cap is the whole trick, and it works because of progressive disclosure. Skills are surfaced by name and description only, so the agent sees a cheap menu of capabilities and reads a skill&#8217;s body on demand, which is why the always-loaded skills context can be hard-capped at ~1% and still scale to dozens of skills. pi takes the same spirit further, surfacing its skills via prompt injection rather than as tools.</p><p>This is pure <strong>configure</strong>, or really authoring, and it&#8217;s the single best return on effort for the user and customizer tiers. Writing a markdown skill is the cheapest way to teach the harness a new workflow, and the 1% cap means you can pile on dozens.</p><p>Skills, tools, and subagents all hang off the loop, and they&#8217;re mostly things you configure. Memory is different. It&#8217;s the one component where you actually build your own layer.</p><h2>Memory Is the Layer You Actually Build</h2><p>In most harnesses, out-of-the-box memory is loaded directly into context, not via a tool. The model never calls a tool to &#8220;remember.&#8221; Relevant memories are read off disk and prepended to the system prompt <em>before</em> the turn runs, and new memories are extracted <em>after</em> the turn by a separate process.</p><p>A file-backed design, Claude Code-style, is worth grounding concretely. The store splits into 2 kinds of files. User-defined <code>.md</code> files come first: <code>AGENTS.md</code> is always loaded, and <code>**/AGENTS.md</code> is loaded dynamically per directory, on demand. LLM-extracted <code>.md</code> files come second: <code>MEMORY.md</code> is an always-loaded index, hard-capped at ~200 lines / 25 KB, while <code>logs/YYYY-MM-DD.md</code> is an append-only daily log where only the <em>relevant</em> logs are loaded. A small-model side-query ranks topic files from the log by their frontmatter description, not embeddings, and picks the top few to inject, which is debuggable and needs no vector store.</p><p>By default a forked extractor updates <code>MEMORY.md</code> live after each turn. A daily-log variant runs a nightly <code>/dream</code> distillation instead: a small LLM extracts the conversation into <code>logs/YYYY-MM-DD.md</code>, then a second distills those logs into <code>MEMORY.md</code>. In other words the pipeline looks like this: raw conversation &#8594; daily logs &#8594; durable memory.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!81Pd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!81Pd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 424w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 848w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!81Pd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png" width="1400" height="1380" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1380,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Three out-of-the-box memory designs &#8212; file-backed, SQLite-backed, and an append-only session tree &#8212; plus the custom MCP-server memory layer that sits above all of them.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Three out-of-the-box memory designs &#8212; file-backed, SQLite-backed, and an append-only session tree &#8212; plus the custom MCP-server memory layer that sits above all of them." title="Three out-of-the-box memory designs &#8212; file-backed, SQLite-backed, and an append-only session tree &#8212; plus the custom MCP-server memory layer that sits above all of them." srcset="https://substackcdn.com/image/fetch/$s_!81Pd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 424w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 848w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!81Pd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f2b5f4c-a07d-4241-ae41-aae257087452_1400x1380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Three out-of-the-box memory designs: file-backed, SQLite-backed, and an append-only session tree. Plus the custom MCP-server memory layer that sits above all of them.</em></figcaption></figure></div><p>Most harnesses use a file-based system for memory. Which is good enough for uses cases such as coding. Other tools, like Cursor or OpenClaw, build a vector index over your memory instead. That&#8217;s why many people report better memory from OpenClaw. As instead of parsing your whole memory as append only logs or forgetting context when building the <code>MEMORY.md</code> index, OpenClaw builds a vector index over your memory.</p><p>Here&#8217;s the heart of the build/configure/use thread, though. The defaults get you started and <code>AGENTS.md</code> is worth configuring, but the highest-leverage move is a <strong>custom memory layer behind an MCP server</strong>, a database exposed through an MCP server with your own read/write logic. Because it&#8217;s harness-independent, you jump from Claude Code to Cursor to anything and the agent instantly picks up who you are.</p><p>Real independence means owning your own context layer.</p><p>This is the one place to <strong>build</strong>, and it pays off for every tier that&#8217;s serious. The context layer behind an MCP server is the moat. It&#8217;s harness-portable, fully yours, and the thing that makes the assistant <em>your</em> assistant.</p><p>Owning your context is about <em>what</em> the agent knows. The next layer is about <em>where</em> its code runs, sandboxing, which protects you and, surprisingly, lets 1 harness scale to many jobs.</p><h2>The Sandbox: One Jail, Many Remote Workers</h2><p>The obvious reason for a sandbox comes first: it keeps the agent in a controlled environment with no direct access to your machine. Establish the key separation early.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J4Lc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J4Lc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 424w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 848w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 1272w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J4Lc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png" width="1456" height="411" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:411,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;When the model issues a Bash command, the harness decides where it runs &#8212; remotely on Modal, locally in a sandbox (Docker/Firecracker), or directly &#8212; with the OS jail co-located with execution.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="When the model issues a Bash command, the harness decides where it runs &#8212; remotely on Modal, locally in a sandbox (Docker/Firecracker), or directly &#8212; with the OS jail co-located with execution." title="When the model issues a Bash command, the harness decides where it runs &#8212; remotely on Modal, locally in a sandbox (Docker/Firecracker), or directly &#8212; with the OS jail co-located with execution." srcset="https://substackcdn.com/image/fetch/$s_!J4Lc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 424w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 848w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 1272w, https://substackcdn.com/image/fetch/$s_!J4Lc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87958c6d-55fa-4b3f-926c-4be4be8edb19_2162x611.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>When the model issues a Bash command, the harness decides where it runs:  remotely on Modal, locally in a sandbox (Docker/Firecracker), or directly on the host</em></figcaption></figure></div><p>Sandboxing lives at the Bash and PowerShell tool layer, not the UI. When the model issues a <code>Bash</code> tool call, a decision runs about where it executes. If remote, the command runs in a sandbox such as Modal. If local, the harness asks whether to use a sandbox at all: yes means it runs inside a local sandbox (Docker, Firecracker, &#8230;). No means it runs directly on your machine.</p><p>The enforcement detail worth stealing, the way Claude Code does it, is that the jail is derived from the same permission rules the agent already uses, and it always denies writes to its own settings file.</p><p>On top of security sandboxes can change how we define software architecture. Reframe sandboxes as workers from classic distributed systems: each sandbox is a worker that runs jobs in parallel, and 1 harness can manage and scale many of them. So the same harness that protects you locally can fan out dozens of remote jobs. Depending on your sandbox type, you can run data ingestion jobs or even training jobs if the VM has a GPU. Everything from your harness. Codex is a harness that is all in on remote sandboxing.</p><p>Now, let&#8217;s wrap up the article with the most important component: the permission layer.</p><h2>The Permission Layer Has Almost No AI in It</h2><p>The permission system is the hardest part to reason about, and the strange thing is it has essentially no AI in it, yet it&#8217;s what makes the whole system safe to run. Its job is narrow: for every tool call, decide to (a) run it, (b) ask the user, or (c) deny it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3SHl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3SHl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 424w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 848w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 1272w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3SHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;For every tool call the harness resolves a decision &#8212; allow it, ask the user, or deny it &#8212; combining agent modes with user-defined permission rules.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="For every tool call the harness resolves a decision &#8212; allow it, ask the user, or deny it &#8212; combining agent modes with user-defined permission rules." title="For every tool call the harness resolves a decision &#8212; allow it, ask the user, or deny it &#8212; combining agent modes with user-defined permission rules." srcset="https://substackcdn.com/image/fetch/$s_!3SHl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 424w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 848w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 1272w, https://substackcdn.com/image/fetch/$s_!3SHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc43c0d55-93a7-489c-8d9d-493acace2235_1945x972.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>For every tool call, the harness resolves a decision: allow it, ask the user, or deny it</em></figcaption></figure></div><p>The structure has 2 flavors. Agent modes change default behavior: <code>default</code>, <code>acceptEdits</code>, <code>bypassPermissions</code>, and <code>plan</code>. User-defined rules live in config, in <code>.agents/settings.json</code> and <code>.agents/settings.local.json</code>, where you declare what the agent can and cannot run, including wildcard rules like <code>Bash(git *)</code>. The harness combines mode metadata and user rules at runtime to resolve each call.</p><p>The <em>&#8220;Can use tool?&#8221;</em> question has 3 outcomes.</p><p><strong>Allow</strong> calls the tool. <strong>Ask</strong> surfaces it to the user, and on allow it calls the tool, while on deny it synthesizes a denial tool-result and continues. <strong>Deny</strong> synthesizes the denial directly.</p><p>When deciding what to do, the harness runs tool filter &#8594; user settings &#8594; mode.</p><p>Here&#8217;s the counterintuitive payoff. &#8220;Bypass everything&#8221; is not total. Plan mode is enforced <em>prompt-side</em>, via a system reminder telling the model to only edit the plan file.</p><p>Which shows how fragile these mechanisms still are, as we just hope for the best that the model will pick up the instruction.</p><p>You almost never build this. But it&#8217;s incredebly important to properly configure it. It&#8217;s probably the most important part to configure right to ensure it has just enough access to your data and machine.</p><h2>What&#8217;s Next</h2><p>These are just the core components that almost any agentic harness needs and has.</p><p>But there is more to it.</p><p>Worktrees for parallel isolated edits, multiprocessing subagents for true parallelism, and a plugin system for extending the harness without forking it. Which I will address in future articles.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>Which component did you decide to build rather than configure? Was owning it worth it, or did you reinvent something the harness already had?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/agentic-harness-system-design/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/agentic-harness-system-design/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/agentic-harness-system-design?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/agentic-harness-system-design?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[How to Keep Your AI Agent's Knowledge Graph Clean]]></title><description><![CDATA[The resolution, deduplication, and review pipeline that keeps agent memory usable as it grows.]]></description><link>https://www.decodingai.com/p/keep-knowledge-graph-clean</link><guid isPermaLink="false">https://www.decodingai.com/p/keep-knowledge-graph-clean</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 02 Jun 2026 05:00:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!p5lm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p5lm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p5lm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p5lm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1382657,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/199956327?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!p5lm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!p5lm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F71377412-24c1-4531-883e-22f3a5057aa5_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Two months ago, I started building unified memory layers on top of knowledge graphs. One question kept coming back from readers. How do you handle entity resolution and deduplication without corrupting the graph?</p><p>Rather than guessing, I spent serious time studying how mem0, cognee, and Neo4j actually solve it. The recurring question exposes a confusion almost everyone shares. People treat entity resolution and deduplication as the same step.</p><p>That confusion is exactly what corrupts graphs. People collapse naming and identity into 1 fuzzy check.</p><p>Also, if the merging step is not properly designed, 2 different real-world entities can silently merge, corrupting your graph.</p><p>Resulting in losing the trust in your graph that made it worth building. The graph quietly rots. Nobody trusts it, and the entire memory layer you invested in goes unused.</p><p>The failure is invisible until it becomes expensive to undo. The fix is to separate naming from identity.</p><p>We will walk through the end-to-end pipeline. This includes LLM extraction, entity resolution for naming, embedding the full node and deduplication for identity. Plus, the 2 safety nets most tutorials skip.</p><p>We covered the full <a href="https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system">memory-system design</a> and the <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">ontology design</a> in prior articles. This piece focuses only on keeping the graph clean. By the end, you will be able to design a graph that stays clean and usable as it grows.</p><div class="callout-block" data-callout="true"><h2><a href="https://www.youtube.com/watch?v=BtY6hqNpMNk">Why We Killed RAG in Production (Product)</a></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.youtube.com/watch?v=BtY6hqNpMNk" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ciWB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ciWB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg" width="1280" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;placeholder&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://www.youtube.com/watch?v=BtY6hqNpMNk&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="placeholder" title="placeholder" srcset="https://substackcdn.com/image/fetch/$s_!ciWB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ciWB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F026e9a22-c706-4acb-a74d-7aa50c5173db_1280x720.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This article shows how to keep a graph memory layer clean. In a recent podcast, I covered the decision that comes before it: whether you need retrieval at all.</p><p>I explain why we killed RAG for a financial advisor product. All of an advisor&#8217;s data summed to 64,000 tokens, so loading the full context beat RAG&#8217;s zigzag retrieval loop. The formula I use: your data-to-context-window ratio.</p><p>We also get into regretting MCP everywhere, treating vibe-coded output as a compilation step, and why AI evals become the real job once the model writes the code.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.youtube.com/watch?v=BtY6hqNpMNk&quot;,&quot;text&quot;:&quot;Watch the episode&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.youtube.com/watch?v=BtY6hqNpMNk"><span>Watch the episode</span></a></p></div><h2>One Pipeline, Five Steps</h2><p>In goes a document or a conversation turn. Out comes a set of canonical, deduplicated nodes correctly wired into the existing graph. Everything between is about making sure each new node is named and identified right.</p><p>First, an LLM extractor reads the text and emits entities and relationships connected by <code>(entity, relationship, entity)</code> triplets. It anchors within the POLE+O, Facts, and Preferences ontology. This ensures it only extracts the entity types you actually care about, as we explained in depth <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">in this article</a>.</p><p>For example, a sentence about a person working at a company becomes a <code>(Person)-[:WORKS_AT]-&gt;(Organization)</code> triplet. The ontology told the extractor those are the types that matter.</p><p>If using only LLMs for extraction becomes too costly, you can use a cost-tiered cascade here, starting with fast statistical models like spaCy for common entities, moving to zero-shot models like GLiNER for domain-specific types, and falling back to an LLM for complex cases.</p><p>Before touching the graph, we must decide what this new entity should be called. The system normalizes its name against existing nodes of the same type. This is the finding-the-canonical-name step, and no merges happen yet.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qe_I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qe_I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 424w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 848w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 1272w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qe_I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png" width="1200" height="1009" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1009,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;From raw documents to a clean graph node: extraction, resolution, embedding, deduplication, then the merge/flag/add decision.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="From raw documents to a clean graph node: extraction, resolution, embedding, deduplication, then the merge/flag/add decision." title="From raw documents to a clean graph node: extraction, resolution, embedding, deduplication, then the merge/flag/add decision." srcset="https://substackcdn.com/image/fetch/$s_!qe_I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 424w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 848w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 1272w, https://substackcdn.com/image/fetch/$s_!qe_I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae16fdb-fca4-480b-b88a-c43f8b35a461_1200x1009.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>From raw documents to a clean graph node: extraction, resolution, embedding, deduplication, then the merge/flag/add decision.</em></figcaption></figure></div><p>Next, we compute an embedding over the entity&#8217;s full context. This includes its name, type, and attributes. We embed more than just its bare name. This is what later lets deduplication compare identity rather than spelling.</p><p>We compare the embedded node against existing nodes. This decides whether it is the same real-world entity as one already in the graph.</p><p>Based on the deduplication outcome, the system makes a final routing decision. It either merges into an existing node, flags the pair for human review, or adds a brand-new node.</p><p>A new mention of a company gets extracted as a typed entity. The resolution step normalizes it to a canonical name. Then, it gets embedded with its full context so we capture its semantic meaning. It is compared against existing same-type nodes to verify its identity. Finally, it gets added, merged, or flagged for review.</p><p>Resolution and deduplication are 2 distinct decisions doing 2 distinct jobs. Let&#8217;s zoom in on each one.</p><h2>Entity Resolution: &#8220;What Should We Call This?&#8221;</h2><p>During resolution we find the canonical name for each entity. It answers <em>&#8220;what should we call this?&#8221;</em>.</p><p>It handles typos, acronyms, and surface-form similarity. These are the noisy ways humans and documents write the same thing. It uses exact, fuzzy, and semantic matching in a short-circuit chain.</p><p>The short-circuit chain passes the entity to the next matcher only if no confident match is found. If exact match fails, it tries fuzzy match. If fuzzy match fails, it tries semantic match (using light embeddings only on the name).</p><p>But it matches only against the names of existing nodes of the same type. You never compare a <code>PERSON</code> name against an <code>ORGANIZATION</code> name.</p><p>&#8220;NYC&#8221; resolves to &#8220;New York City&#8221;. &#8220;JP Morgan&#8221; resolves to &#8220;JPMorgan Chase&#8221;. The 3 forms <code>"John Smith "</code>, <code>"john smith"</code>, and <code>"Jon Smith"</code> all collapse to 1 canonical &#8220;John Smith&#8221;.</p><p>This happens because resolution absorbs whitespace, casing, and typo variations. Fuzzy string matching uses token-based comparison to handle word order and partial matching for abbreviations. At this stage the system only updates the node&#8217;s <code>canonical_name</code> property. No graph merges happen yet.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p1qh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p1qh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 424w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 848w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 1272w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p1qh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png" width="1400" height="536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:536,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:558276,&quot;alt&quot;:&quot;Resolution chains exact &#8594; fuzzy &#8594; semantic matching against same-type names to assign a canonical name &#8212; without ever merging nodes.&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Resolution chains exact &#8594; fuzzy &#8594; semantic matching against same-type names to assign a canonical name &#8212; without ever merging nodes." title="Resolution chains exact &#8594; fuzzy &#8594; semantic matching against same-type names to assign a canonical name &#8212; without ever merging nodes." srcset="https://substackcdn.com/image/fetch/$s_!p1qh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 424w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 848w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 1272w, https://substackcdn.com/image/fetch/$s_!p1qh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37cc7c05-b7d4-4317-a222-5b4fa3ac46ea_1400x536.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Resolution chains exact &#8594; fuzzy &#8594; semantic matching against same-type names to assign a canonical name (without ever merging nodes).</em></figcaption></figure></div><p>Often, you also keep track of a list of aliases for each node. Whenever you find a new hit via fuzzy or semantic match that doesn&#8217;t match the current <code>canonical_name</code>, you add it to the list of aliases. Like this, in future checks you can speed up matching by checking the alias list first.</p><p>Similar names are not strong enough evidence that 2 entities are identical. This is the line most people blur. Blurring it is what causes silent corruption.</p><p>Apple the company is not Apple the fruit. They have different types, so type-gating already separates them. A harder example is Jensen Huang the CEO of NVIDIA versus a doctor in Taipei with the same name.</p><p>They have the same name and the same type. Yet they are 2 different real-world people. Naming similarity alone would happily fuse them.</p><p>Still, canonical names are extremely useful for GROUP BY operations where, during querying and visualizations, we can quickly understand the data. During human review, we can even spot duplicates and resolve them manually.</p><p>That is why identity is a separate decision. Resolution has told us what to call the node. It has deliberately not told us whether the node is a duplicate.</p><p>That second, riskier question belongs to deduplication.</p><h2>Deduplication: &#8220;Is This the Same Entity?&#8221;</h2><p>Deduplication is the identity layer. It answers the harder question: <em>&#8220;is this the same real-world entity?&#8221;</em>. It is the step where merges actually happen <a href="https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/">[5]</a>.</p><p>In goes 1 embedded node. Out comes a single routing decision: merge into an existing node, flag it for review, or create a new node.</p><p>The system embeds the full entity context. It compares it against existing nodes using semantic and fuzzy similarity across that full context. The richer signal is what lets it distinguish 2 same-named, same-type entities that resolution could not.</p><p>By the context of a node, we refer to the entity&#8217;s attributes such as its text, image, video content or even its metadata properties such as a person&#8217;s email or date of birth. Or an object&#8217;s model or manufacturer. Still, you don&#8217;t want to embed everything, such as identifier, but per each ontology type pick the fields that contain the highest signal.</p><p>The combined deduplication score is an explicit weighted blend. It uses the embedding score multiplied by 0.7 and the fuzzy score multiplied by 0.3. Based on a similarity score from 0 to 1, we have 3 bands.</p><p>High confidence (&#8805;0.95) triggers an auto-merge. Medium confidence (0.85&#8211;0.95) flags the pair for human review. Low confidence (&lt;0.85) creates a new node.</p><p>Near-certain identity is allowed to merge automatically. The uncertain middle is escalated. Weak evidence just becomes a fresh node.</p><p>False merges silently corrupt the graph. The corruption is invisible until it is expensive. Take the Paris example: 2 <code>LOCATION</code> nodes both named &#8220;Paris&#8221;.</p><p>One is the capital of France, and the other is Paris, Texas. They have the same name, the same type, and very similar bare-name embeddings. But they are 2 different places.</p><p>The dangerous part is the middle band, the gray area. This is where the system is not sure and a human has to step in.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HtX8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HtX8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 424w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 848w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 1272w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HtX8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png" width="1400" height="785" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:785,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Deduplication scores full-context similarity, then routes to auto-merge, human review, or a new node &#8212; stronger evidence earns more irreversible action.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Deduplication scores full-context similarity, then routes to auto-merge, human review, or a new node &#8212; stronger evidence earns more irreversible action." title="Deduplication scores full-context similarity, then routes to auto-merge, human review, or a new node &#8212; stronger evidence earns more irreversible action." srcset="https://substackcdn.com/image/fetch/$s_!HtX8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 424w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 848w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 1272w, https://substackcdn.com/image/fetch/$s_!HtX8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cbddf49-7c66-407a-946e-57baa4d3c128_1400x785.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Deduplication scores full-context similarity, then routes to auto-merge, human review, or a new node.</em></figcaption></figure></div><h2>When Confidence Lands in the Gray Zone</h2><p>When a deduplication score lands in the medium band (0.85&#8211;0.95), the system deliberately does not merge. It flags the pair for a human to decide, as merging is a dangerous operation we should be really deliberate about.</p><p>The source node gets tombstoned, meaning it is kept queryable for forensics but skipped from future matching. Actually undoing a merge means re-ingesting the source data. That reversibility cost is the whole reason for the gray zone.</p><p>Whenever a new entity is flagged for human review, a new node is created and a <code>(:Entity)-[:SAME_AS {status:'pending', confidence}]-&gt;(:Entity)</code> edge is added inside the graph itself. The human review step transitions that <code>status</code> to <code>confirmed</code> or <code>rejected</code>. The review queue is just a Cypher query over pending <code>SAME_AS</code> edges, ordered by confidence.</p><p>For each flagged pair, the reviewer answers 1 question. Is this actually a duplicate, a new node, or neither?</p><p>This usually happens to entities that are related but not identical. The Codex model and the Codex CLI are related, but not the same object. The same applies to Jensen Huang the CEO versus a same-named doctor in Taipei.</p><p>This is hardest at the start of an entity&#8217;s lifecycle. When metadata is scarce, similarity spikes, and you risk polluting 1 node with another&#8217;s attributes.</p><p>Human review catches the uncertain pairs the live pipeline surfaces. But some duplicates never get surfaced at all. That is the gap the dream pipeline closes.</p><h2>Cleaning the Graph While It Sleeps</h2><p>While the system ingests documents, data often flows through in parallel. If 2 entities are processed at the same time, the resolution and deduplication steps never get to compare them against each other.</p><p>The system would never check whether Claude Code from Conversation X and Claude Code from Document Y are the same entity, because neither existed in the graph when the other was written.</p><p>You run a dream pass every night. It re-runs the deduplication pass on recently ingested nodes only. Otherwise, you will have to loop through all nodes in the graph. Which as the graph grows, becomes increasingly expensive.</p><p>It does not run the full resolution chain. Because the embeddings were already computed at ingest time, this is a light operation. It is primarily database reads and writes, not fresh model calls. Since it mostly adds I/O pressure, run it when organic traffic is low, which is usually during the night, hence the name <code>the dream pipeline</code>.</p><h2>What&#8217;s Next</h2><p>I&#8217;ve spent the past 4 months building unified memory layers on top of knowledge graphs, and I learned that keeping them clean is the hardest part. Keeping your knowledge graph clean is the maintenance step that decides whether the graph ever gets used. A graph full of noise, fragments, and false merges will not be trusted or queried.</p><p>In case you want to learn more, remember that we also covered the full <a href="https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system">memory-system architecture via knowledge graphs</a> and the <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">ontology design</a> in prior articles.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What are the core strategies you&#8217;ve used to keep your knowledge graph clean and usable? Something close to our approach here, or something completely different?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/keep-knowledge-graph-clean/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/keep-knowledge-graph-clean/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/keep-knowledge-graph-clean?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/keep-knowledge-graph-clean?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>References</h2><ol><li><p>Iusztin, P. (n.d.). Understanding the Neo4j Graph Agent Memory System. Decoding AI Magazine. <a href="https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system">https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system</a></p></li><li><p>Iusztin, P. (n.d.). Ship a Knowledge Graph Ontology in 5 Minutes. Decoding AI Magazine. <a href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes">https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes</a></p></li><li><p>POLE+O Data Model. (n.d.). Neo4j Labs. <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">https://neo4j.com/labs/agent-memory/explanation/poleo-model/</a></p></li><li><p>How Entity Extraction Works. (n.d.). Neo4j Labs. <a href="https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/">https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/</a></p></li><li><p>Entity Resolution and Deduplication. (n.d.). Neo4j Labs. <a href="https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/">https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/</a></p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Stop Chasing the Perfect Ontology]]></title><description><![CDATA[Start with a fixed, generic base and extend only when your data demands it.]]></description><link>https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes</link><guid isPermaLink="false">https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 26 May 2026 05:00:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!HeOr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HeOr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HeOr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HeOr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1173447,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/198955243?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HeOr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!HeOr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc87b2d2f-a13e-458f-8014-2d574171418c_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For a while now I&#8217;ve been trying to build a proper memory layer on top of my research, writing, and content creation. Today it all lives in my Second Brain in Obsidian, where the primitives are files like notes, videos, and articles.</p><p>What I actually want is to shift those primitives from files to entities and relationships, such as people, locations, objects, topics, preferences, and facts. I want the memory to get closer to reality so I can watch how things evolve over time. I want a knowledge graph.</p><p>Everyone agrees knowledge graphs and GraphRAG provide a more performant substrate for a unified agent memory layer than plain RAG. But kicking one off is far harder. The resistance always collapses to the same wall: how you model your data. Your ontology is the hardest part of the system.</p><p>If you can&#8217;t define your ontology properly for your domain, the graph won&#8217;t represent the reality you want. The right entities and relationships simply aren&#8217;t there. As a result, GraphRAG ends up performing worse than the simple RAG you were trying to beat.</p><p>This translates straight to a memory layer. There&#8217;s no dodging it. Even if you stay file-only (a &#8220;virtual knowledge graph,&#8221; like an LLM knowledge base over your notes), you still hit the same data-modelling question: which primitives, and which entities, do you even extract?</p><p>The instinctive reaction is to design the perfect, complete ontology upfront. That&#8217;s exactly the trap that freezes the project.</p><p>The strategy is a not-overkill ontology. You need something flexible enough to kick off with almost no friction before you really know your domain, extending it with domain-specific detail as you explore your data.</p><p>Concretely, you use a small, fixed, generic, but extendable noun data model, known as POLE+O. Plus two core primitives, Preferences and Facts, for everything that doesn&#8217;t fit into the nouns.</p><p>You ship something that works, then add subtypes as a lightweight data-exploration step shows you where the generic types clash with your real data.</p><p>This approach lets you stand up a knowledge-graph memory layer for your own assistant without burning weeks on schema design. To build this, we first need to understand what an ontology actually is and why targeted models beat exhaustive ones.</p><div class="callout-block" data-callout="true"><h2><a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Start Your Transition Into AI Engineering (Product)</a></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XTiA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XTiA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 424w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 848w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 1272w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XTiA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png" width="463" height="488.3527827648115" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1175,&quot;width&quot;:1114,&quot;resizeWidth&quot;:463,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XTiA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 424w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 848w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 1272w, https://substackcdn.com/image/fetch/$s_!XTiA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F977ee5b6-01a9-4bf9-a923-d092a8f5ac28_1114x1175.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This article showed how to design the ontology your knowledge-graph memory needs. My <a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agentic AI Engineering course</a> shows the harness around it. I just released a free preview to build and run a working agent in 5 minutes.</p><p>You build a multi-agent system with two MCP servers (Research Agent + Writing Workflow), a deep research algorithm, an evaluator-optimizer loop, observability, and LLM-as-judge evals. Patterns required to ship AI.</p><p>Built for software, data engineers or scientists transitioning into AI engineering.</p><p>7 free lessons, 2 MCP agents ready for your GitHub portfolio. Part of our 35-lesson course. Rated 5/5 by 300+ students.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start the free preview &#8594;&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start the free preview &#8594;</span></a></p></div><h2>What Is an Ontology?</h2><p>An ontology is the formal answer to 1 question. When you read the world, what do you write down as nodes, and what do you draw as edges? It specifies the kinds of things that exist in your domain, their properties, and how they relate to each other.</p><p>The ontology&#8217;s job is to map a targeted slice of the real world into the digital world. A good ontology is highly targeted to the problem you actually want to solve. If you over-model, you drown in noise and never ship. Plus, it get&#8217;s extremely expensive to extract and maintain the knoweldge graph. If you under-target, the graph doesn&#8217;t reflect the reality you care about.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!shkp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!shkp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 424w, https://substackcdn.com/image/fetch/$s_!shkp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 848w, https://substackcdn.com/image/fetch/$s_!shkp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 1272w, https://substackcdn.com/image/fetch/$s_!shkp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!shkp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png" width="1400" height="1202" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1202,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;An ontology is a deliberately narrow funnel from the real world into a queryable graph.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="An ontology is a deliberately narrow funnel from the real world into a queryable graph." title="An ontology is a deliberately narrow funnel from the real world into a queryable graph." srcset="https://substackcdn.com/image/fetch/$s_!shkp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 424w, https://substackcdn.com/image/fetch/$s_!shkp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 848w, https://substackcdn.com/image/fetch/$s_!shkp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 1272w, https://substackcdn.com/image/fetch/$s_!shkp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6da9e68c-1cec-4f99-afe9-ada0003fd270_1400x1202.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>An ontology is a deliberately narrow funnel from the real world into a queryable graph.</em></figcaption></figure></div><p>Look at concrete, shipped ontologies for real-world proof. The <a href="https://create-context-graph.dev/docs/reference/domain-catalog">create-context-graph</a> domain catalog made by Neo4j publishes 22 ready-made domain ontologies. Every single one lands at exactly 10 to 12 entity types. They use a shared 5-noun base plus only 5 to 7 domain-specific nouns.</p><p>For example, the Personal Knowledge domain models the world as Note, Contact, Project, Topic, Bookmark, and JournalEntry. The Agent Memory uses Agent, Conversation, Memory, ToolCall, and Session. The lesson here is that real ontologies are small on purpose. They capture only the entities required to answer the questions the system is designed for.</p><p>So if targeted and small is the goal, why does everyone &#8212; me included &#8212; reach for big and perfect first? That&#8217;s the trap.</p><h2>The Overkill Trap: Why My Knowledge Graphs Never Shipped</h2><p>When I first encountered the ontology concept, I assumed I had to study my domain in depth. I thought I needed to model all of finance, for example, and design the ideal ontology before working with any real data. You can&#8217;t actually do that before you have a system running and data to look at. You just pile up assumptions that mostly turn out wrong.</p><p>I got frozen. Every knowledge-graph solution I started stayed on my laptop and never got used, because I was waiting on an ideal ontology I could never reach. Without understanding the ontology, I couldn&#8217;t even write a decent extraction step to populate it. I was deadlocked, bringing 0 value.</p><p>The breakthrough was realizing I need a couple of models that let me start generic and extend over time. As I get more data, analyze it, and actually understand my problem, the schema evolves. Let&#8217;s meet the base model that lets you start in 5 minutes instead of 5 weeks.</p><h2>The POLE+O Data Model</h2><p>POLE+O is a tiny, fixed, top-level vocabulary that can classify almost anything you pull out of text. It stands for Person, Object, Location, Event, and Organization <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">[2]</a>. It originated in law-enforcement and intelligence analysis. The Organization type was added for general-purpose entity extraction. The point of a fixed base is queryability. There are always exactly 5 base nouns to filter on, so the graph stays answerable no matter how it grows underneath.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wK0q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wK0q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 424w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 848w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 1272w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wK0q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png" width="1400" height="1159" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1159,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;5 fixed base nouns, each extensible with optional subtypes &#8212; the base never changes, so every refinement is additive.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="5 fixed base nouns, each extensible with optional subtypes &#8212; the base never changes, so every refinement is additive." title="5 fixed base nouns, each extensible with optional subtypes &#8212; the base never changes, so every refinement is additive." srcset="https://substackcdn.com/image/fetch/$s_!wK0q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 424w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 848w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 1272w, https://substackcdn.com/image/fetch/$s_!wK0q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34af01f1-f989-43ca-a1ca-f0e76cfa57fd_1400x1159.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>5 fixed base nouns, each extensible with optional subtypes</em></figcaption></figure></div><p>Person covers people, aliases, and personas. Object covers physical or digital things. Location covers places, addresses, and regions. Event covers meetings, transactions, and incidents. Organization covers companies, teams, and institutions. Two or three of these catch the overwhelming majority of what a personal assistant needs.</p><p>Here are POLE+O&#8217;s five base types and the default subtypes each one ships with:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yyhn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yyhn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 424w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 848w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 1272w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yyhn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png" width="1456" height="670" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:670,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;table&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="table" title="table" srcset="https://substackcdn.com/image/fetch/$s_!yyhn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 424w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 848w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 1272w, https://substackcdn.com/image/fetch/$s_!yyhn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cc57663-f5d0-4f97-b81a-60c1bf2c34b9_1920x883.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here&#8217;s the beauty of this approach. You extend the base nouns with your own subtypes, and that&#8217;s how you tailor a generic ontology to your specific domain. It works exactly like object-oriented programming. You start from base classes you adopt without thinking. Then you subclass into specifics as your use case clarifies.</p><p>You can kick off with nothing extended and add concrete types only as you understand your data better. Neo4j&#8217;s <a href="https://github.com/neo4j-labs/agent-memory">agent-memory</a> library uses precisely this approach. POLE+O is its default, swappable ontology.</p><p>The data-exploration workflow runs in a simple loop. First, kick off with generic POLE+O. Second, run an exploration extraction over your real data. Forget production reliability. You only care about understanding what&#8217;s there. Third, inspect the graph for clashes where the generic model lies about your data. Fourth, add or rename subtypes to fix each clash. Finally, repeat the process. You won&#8217;t get it perfect, and that&#8217;s the point. You iterate like any other AI app instead of freezing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pksj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pksj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 424w, https://substackcdn.com/image/fetch/$s_!pksj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 848w, https://substackcdn.com/image/fetch/$s_!pksj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 1272w, https://substackcdn.com/image/fetch/$s_!pksj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pksj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png" width="1400" height="1351" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1351,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;You don't theorize subtypes &#8212; you discover them by watching where generic POLE+O mislabels your real data, then patch the clash and loop.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="You don't theorize subtypes &#8212; you discover them by watching where generic POLE+O mislabels your real data, then patch the clash and loop." title="You don't theorize subtypes &#8212; you discover them by watching where generic POLE+O mislabels your real data, then patch the clash and loop." srcset="https://substackcdn.com/image/fetch/$s_!pksj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 424w, https://substackcdn.com/image/fetch/$s_!pksj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 848w, https://substackcdn.com/image/fetch/$s_!pksj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 1272w, https://substackcdn.com/image/fetch/$s_!pksj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbabfc9-cba1-433b-8ed2-b5d593ef3c81_1400x1351.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>You discover subtypes by watching where generic POLE+O mislabels your real data, then patch the clash and loop.</em></figcaption></figure></div><p>Look at named examples from real extraction runs. Claude Code comes back tagged as a Person when it&#8217;s clearly an Object. The &#8220;AI Engineer&#8221; conference lands as an Event when you wanted an Organization. DeepSeek is tagged a Person, not an Object.</p><p>Portugal and New York both get a flat Location label even though one&#8217;s a country and one&#8217;s a city. An agentic harness shows up as a generic Object when, for knowledge work, you&#8217;d rather have a Topic type. Each clash is a signal to add 1 subtype, not to redesign the whole schema.</p><p>POLE+O nouns and their subtypes cover the things in your world. But to fill in the gaps there are two specials tricks we have to go over.</p><h2>Preferences: The Things a Noun Likes</h2><p>Preferences are the second family of entities you attach to the graph. They are things a noun likes or dislikes. A Preference is a characteristic of an entity. It represents a stance. The canonical case is a person who likes, prefers, or dislikes something.</p><p>Concretely, a Preference entity looks like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3KUZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3KUZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 424w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 848w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 1272w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3KUZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png" width="1456" height="562" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:562,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!3KUZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 424w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 848w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 1272w, https://substackcdn.com/image/fetch/$s_!3KUZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a9cbc22-bb97-4bd4-99fa-a86ad59e6c60_2120x819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><code>category</code> groups the preference, <code>preference</code> is the statement itself, and <code>context</code> optionally records when or where it applies. <code>confidence</code> runs from 0 to 1. The <code>embedding</code> makes it semantically searchable.</p><p>Make it concrete. &#8220;Loves Italian food&#8221;, &#8220;prefers dark mode&#8221;, and &#8220;dislikes long meetings&#8221; are clear examples. Each is a stable stance the assistant should remember and adapt to.</p><p>By default, a Preference hangs off the Person. That&#8217;s the most common and useful case. You can extend preferences to other objects, like an Organization&#8217;s policies, a car&#8217;s settings, or an Event&#8217;s dress code.</p><p>Because I&#8217;m building a personal assistant, I start by attaching Preferences only to the Person. This keeps the graph clean, low-noise, and small. I&#8217;ll extend it later only when a concrete use case demands it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hSPb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hSPb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 424w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 848w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 1272w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hSPb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png" width="1400" height="879" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:879,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Start simple &#8212; preferences attached only to the user; the dotted edges are extensions you add only when you need them.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Start simple &#8212; preferences attached only to the user; the dotted edges are extensions you add only when you need them." title="Start simple &#8212; preferences attached only to the user; the dotted edges are extensions you add only when you need them." srcset="https://substackcdn.com/image/fetch/$s_!hSPb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 424w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 848w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 1272w, https://substackcdn.com/image/fetch/$s_!hSPb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76d5574d-28fd-47a0-94e4-4a735f05dbd4_1400x879.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Preferences attached only to the user. The dotted edges are extensions you add only when you need them.</em></figcaption></figure></div><p>Preferences are the personalization layer. They act as the memory of the user&#8217;s stances. They are the &#8220;sweet sauce&#8221; that makes every future response feel tailored.</p><p>There is one issue. Plenty of useful knowledge is just an atomic fact. Forcing all of that into the ontology is how graphs explode in complexity. The fix is a deliberately generic primitive.</p><h2>Facts: The Trick You Haven&#8217;t Thought Of</h2><p>The Facts entity is the fallback for everything that doesn&#8217;t cleanly fit a noun or a Preference. You drop the claim into a generic Fact. This is the move that keeps the ontology small and stops you from over-thinking the schema.</p><p>A Fact is the closest thing to a classic-RAG chunk. An LLM produces each Fact during extraction. Each Fact holds a single, atomic concept which works like a charm via semantic search.</p><p>The beauty is that with facts you avoid the usual chunking errors, such as splits mid-thought, mixed concepts, and arbitrary boundaries. In reality, a Fact is a triplet. A subject, predicate, and object like &#8220;Eiffel Tower / is / 330m tall&#8221; gets embedded and stored as 1 granular unit.</p><p>Here is the shape of a Fact entity:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g51f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g51f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 424w, https://substackcdn.com/image/fetch/$s_!g51f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 848w, https://substackcdn.com/image/fetch/$s_!g51f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 1272w, https://substackcdn.com/image/fetch/$s_!g51f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g51f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png" width="1456" height="562" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:562,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!g51f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 424w, https://substackcdn.com/image/fetch/$s_!g51f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 848w, https://substackcdn.com/image/fetch/$s_!g51f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 1272w, https://substackcdn.com/image/fetch/$s_!g51f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa162972e-7ad0-4275-94ec-4a9e654d287a_2120x819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The triplet &#8212; <code>subject</code>, <code>predicate</code>, <code>object</code> &#8212; is the whole fact. <code>valid_from</code> and <code>valid_until</code> give it optional bi-temporal validity. The <code>embedding</code>, computed over the concatenated triplet, is what makes the fact retrievable by semantic search.</p><p>It&#8217;s confusing that we have a triplet stored as a node. But this is what it makes it flexible. We don&#8217;t worry about modeling these one-off triplets directly into the ontology, but the LLM extracts them as-is from the text.</p><p>Facts are usually wired to nothing. They have no relationships to other entities. They are retrieved only via semantic search and text search. A Fact stays in the graph but is independent of it. This works because a graph store runs vector search and graph traversal in the same query engine <a href="https://neo4j.com/labs/agent-memory/explanation/graph-architecture/">[4]</a>. Which means facts are retrieved only via semantic/text search.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Wtw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Wtw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 424w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 848w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 1272w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Wtw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png" width="1400" height="1138" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1138,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Facts are atomic triplets retrieved by similarity and wired to nothing; POLE+O entities are reached by walking the graph. Same store, two retrieval modes.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Facts are atomic triplets retrieved by similarity and wired to nothing; POLE+O entities are reached by walking the graph. Same store, two retrieval modes." title="Facts are atomic triplets retrieved by similarity and wired to nothing; POLE+O entities are reached by walking the graph. Same store, two retrieval modes." srcset="https://substackcdn.com/image/fetch/$s_!-Wtw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 424w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 848w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 1272w, https://substackcdn.com/image/fetch/$s_!-Wtw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc37ed613-1a16-40f7-9607-2ed492a787cb_1400x1138.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Facts are atomic triplets retrieved by similarity and wired to nothing; POLE+O entities are reached by walking the graph. Same store, two retrieval modes.</em></figcaption></figure></div><p>Facts let you ship a memory layer before you have the perfect ontology. Anything you can&#8217;t yet model degrades gracefully into a searchable atomic node instead of blocking the build. Early on, you lean on Facts. As the graph matures, claims migrate toward typed entities and edges. It costs nothing to schema and nothing to maintain when entities merge or get deleted.</p><h2>What&#8217;s Next</h2><p>The takeaway is the posture. An ontology is a living artifact you bootstrap from a fixed generic base and grow through a data-exploration loop, exactly like any other AI application.</p><p>If you want to see the whole strategy implemented, the fastest path is to play with Neo4j&#8217;s <a href="https://github.com/neo4j-labs/agent-memory">agent-memory</a> SDK or its MCP server. It uses POLE+O as a swappable default, subtypes as cheap extensions, and Preferences and Facts as first-class primitives. Studying it is what made all of this finally click for me.</p><p>I&#8217;m actively migrating my own Obsidian Second Brain toward the POLE+O, Preferences, and Facts primitives. This turns thousands of files into a graph I can actually traverse, visualize, and watch evolve over time.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>If you worked with Knowledge Graphs, what was your process in discovering your own ontology?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/ship-a-knowledge-graph-ontology-in-5-minutes?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>References</h2><ol><li><p>Create Context Graph. (n.d.). Domain Catalog. create-context-graph. https://create-context-graph.dev/docs/reference/domain-catalog</p></li><li><p>Neo4j Labs. (n.d.). POLE+O Data Model. Neo4j Agent Memory. https://neo4j.com/labs/agent-memory/explanation/poleo-model/</p></li><li><p>Neo4j Labs. (n.d.). Neo4j Agent Memory. GitHub. https://github.com/neo4j-labs/agent-memory</p></li><li><p>Neo4j Labs. (n.d.). Why Neo4j? Graph-Native Memory Architecture. Neo4j Agent Memory. https://neo4j.com/labs/agent-memory/explanation/graph-architecture/</p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[Inside Neo4j's Agent Memory]]></title><description><![CDATA[The knowledge-graph patterns that turn one-shot conversations into compounding intelligence.]]></description><link>https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system</link><guid isPermaLink="false">https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 19 May 2026 08:55:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5ypW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5ypW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5ypW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5ypW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1355267,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/197969180?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5ypW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!5ypW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F282bfce7-31ad-4a52-b320-b917b2696020_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I already have a second brain setup based on Obsidian, Readwise, NotebookLM, and Claude Code. I dump all my notes, research, and highlights there. Whenever I want to create content, I create a scoped wiki targeted toward the topic. I gather information from my second brain using a deep research algorithm on top of my private data and external resources via NotebookLM. The wiki is structured like the LLM Knowledge Base presented by Andrej Karpathy.</p><p>This setup fails to extract and maintain shared entities, preferences, and facts across the wiki as the knowledge base grows. For example, if the topic &#8220;Claude Code&#8221; is mentioned in 10 documents, I want to extract all the metadata about it into its dedicated folder. I want to see what other entities it relates to, such as Anthropic, San Francisco, Codex, or Gemini CLI. I also want to see how many documents mention it to rank frequency. You can do that with a pure file-based system and Obsidian, but performance degrades when your data scales past 50 documents.</p><p>The same concept applies to any unstructured knowledge base. You need a way to extract and connect knowledge from your conversations, documents, and images. This becomes essential between conversations so your agent doesn&#8217;t forget you. Instead, it provides a personalized experience. It&#8217;s also critical for context engineering to inject the right context at the right time and keep the LLM focused on relevant facts.</p><p>Most teams default to one of two memory approaches. Both collapse under real use. A file system gives you append-only logs that the agent re-reads from scratch, which fragments and rots context.</p><p>A vector index gives you fuzzy semantic recall but no merge, no identity, and no way to know if this is the same Karpathy you knew yesterday. Durable AI memory requires a structured graph to track identity and relationships <a href="https://www.linkedin.com/posts/tonyseale_this-week-anthropic-dropped-claude-sonnet-activity-7379787334398926848-iVOE/">[1]</a>. Without this structure, the assistant forgets past interactions and fails to build compounding intelligence.</p><p>Knowledge-graph memory is the next step on the arc from Retrieval-Augmented Generation (RAG) to agentic RAG to agent memory <a href="https://www.leoniemonigatti.com/blog/from-rag-to-agent-memory.html">[2]</a>. Building a unified knowledge-graph memory system is hard, so most teams skip it.</p><p>During my research, I stumbled upon <code>neo4j-labs/agent-memory</code>. It&#8217;s a masterpiece. Who knows more about knowledge graphs (KGs) than Neo4j?</p><p>After I spent 2 days playing with it and understanding the codebase, I realized it was the perfect mental model for any agent memory system powered by KGs.</p><p>In this article, I&#8217;ll walk through the core architectural patterns of <code>neo4j-labs/agent-memory</code>. It features 1 graph, 3 memory tiers, the POLE+O ontology, a 3-stage extraction pipeline, a composite resolver, and the SAME_AS pattern.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cxdW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cxdW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 424w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 848w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 1272w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cxdW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png" width="1456" height="1167" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1167,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:390376,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/197969180?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cxdW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 424w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 848w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 1272w, https://substackcdn.com/image/fetch/$s_!cxdW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44a2dc7c-3947-44f5-88fd-1a5aef196b8d_1744x1398.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By the end, you&#8217;ll have a concrete mental model. You can ship on top of their Software Development Kit (SDK) or hook it into your agent via their Model Context Protocol (MCP) server. Alternatively, you can steal the patterns and ship the same architecture on Postgres or MongoDB if a full graph database in production doesn&#8217;t make sense for your use case.</p><div class="callout-block" data-callout="true"><h2><a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Start Your Transition Into AI Engineering (Product)</a></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BjfO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BjfO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 424w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 848w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 1272w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BjfO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png" width="1285" height="1074" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1074,&quot;width&quot;:1285,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:225430,&quot;alt&quot;:&quot;Build and run a working agent in 5 minutes &#8212; free preview of the Agentic AI Engineering course&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Build and run a working agent in 5 minutes &#8212; free preview of the Agentic AI Engineering course" title="Build and run a working agent in 5 minutes &#8212; free preview of the Agentic AI Engineering course" srcset="https://substackcdn.com/image/fetch/$s_!BjfO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 424w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 848w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 1272w, https://substackcdn.com/image/fetch/$s_!BjfO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5d0b9ec-af0d-4a21-9110-f5a7d1c4a742_1285x1074.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This article shows the memory layer your agent needs. My <a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agentic AI Engineering course</a> shows the harness around it, and I just released a free preview that lets you build and run a working agent in 5 minutes.</p><p>You build a multi-agent system with two MCP servers (Research Agent + Writing Workflow), a deep research algorithm, an evaluator-optimizer loop, observability, and LLM-as-judge evals. The production patterns behind agents that actually ship.</p><p>Built for software, data engineers or scientists transitioning into AI engineering.</p><p>7 free lessons, 2 MCP agents ready for your GitHub portfolio. Part of the 35-lesson course. Rated 5/5 by 300+ students.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start the free preview &#8594;&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start the free preview &#8594;</span></a></p></div><h2>What&#8217;s Inside <code>neo4j-labs/agent-memory</code></h2><p>The SDK takes natural-language interactions on the write side and returns a fused memory context on the read side. Everything anchors to a single Neo4j graph. For our scoped wiki, notes and Readwise highlights about Claude Code flow in. A structured pull of what the agent knows about Claude Code, how it relates to Anthropic, and its frequency across 50 documents comes out.</p><p>At its core, there is 1 graph and 3 memory tiers joined by typed edges: short-term conversations, long-term typed entities, and reasoning traces. They&#8217;re stitched together by <code>:MENTIONS</code>, <code>:TOUCHED</code>, and <code>:INITIATED_BY</code> relationships <a href="https://neo4j.com/labs/agent-memory/explanation/memory-types/">[3]</a>.</p><p>The architecture contains 8 small, single-responsibility modules. The <code>models/</code> module holds Pydantic schemas. The <code>schema/</code> module handles Cypher migrations. The <code>extraction/</code> module runs the Named Entity Recognition (NER) pipeline. The <code>resolution/</code> module holds the composite resolver. The <code>dedup/</code> module manages the SAME_AS pattern. The <code>core/</code> module provides <code>MemoryClient.get_context()</code>. The <code>mcp/</code> module runs the FastMCP server with 15 tools. The <code>integrations/</code> module holds 9 framework adapters for tools like LangChain and LlamaIndex.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z_M-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z_M-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 424w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 848w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 1272w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z_M-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png" width="1400" height="1311" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1311,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The 8 modules sit between an MCP / framework interface and a single Neo4j graph that holds all three memory tiers.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The 8 modules sit between an MCP / framework interface and a single Neo4j graph that holds all three memory tiers." title="The 8 modules sit between an MCP / framework interface and a single Neo4j graph that holds all three memory tiers." srcset="https://substackcdn.com/image/fetch/$s_!Z_M-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 424w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 848w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 1272w, https://substackcdn.com/image/fetch/$s_!Z_M-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb76b9b07-fb46-40c4-81a1-61e5aff42cc0_1400x1311.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>The 8 modules sit between an MCP / framework interface and a single Neo4j graph that holds all three memory tiers.</em></figcaption></figure></div><p>Consider an end-to-end scenario. You drop a Readwise highlight about Claude Code into your scoped wiki. The <code>extraction/</code> module pulls Claude Code as an Object, Anthropic as an Organization, and Codex as an Object. The <code>resolution/</code> module canonicalizes each against existing nodes. The <code>dedup/</code> module checks vector similarity and either auto-merges or flags a pending <code>:SAME_AS</code> edge. The <code>schema/</code> module commits <code>:MENTIONS</code> edges from the note to each entity.</p><p>Later, <code>MemoryClient.get_context()</code> pulls fused context across the same graph in one call. This matters concretely for the scoped-wiki agent. You can ask what you discussed last session, what you know about Claude Code, and why the agent surfaced a Codex comparison last Tuesday. The SDK answers all three against the same graph. It uses the same Cypher dialect with no cross-store join logic.</p><h2>Short-Term, Long-Term, Reasoning Memory</h2><p>The SDK splits memory into three layers that all live on the same Neo4j graph <a href="https://neo4j.com/labs/agent-memory/explanation/memory-types/">[3]</a>. Short-term memory is the linear message sequence. It uses ordered <code>:Message</code> nodes chained by <code>:NEXT</code> edges, scoped to a <code>:Conversation</code>. Long-term memory is the typed entity graph. It uses deduplicated <code>:Entity</code> nodes with vector embeddings and arbitrary domain relationships.</p><p>Reasoning memory is a tree per agent run. It uses a <code>:ReasoningTrace</code> root with child <code>:ReasoningStep</code> nodes capturing thoughts and tool calls. For the scoped-wiki agent, short-term memory holds your current chat. Long-term memory holds the canonical Claude Code entity plus its relations to Anthropic, San Francisco, Codex, and Gemini CLI. Reasoning memory holds the trace of how the agent picked those specific notes to answer you.</p><p>Three relationships do the entire stitching. The <code>:MENTIONS</code> edge joins short-term to long-term memory. The <code>:INITIATED_BY</code> edge joins reasoning to short-term memory. The <code>:TOUCHED</code> edge joins reasoning to long-term memory. These three edges make provenance a one-hop query rather than a log-reconstruction project.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_7Cv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_7Cv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 424w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 848w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 1272w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_7Cv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png" width="1400" height="1370" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1370,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Three tiers, one graph &#8212; the typed edges make every cross-tier question a one-hop query.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Three tiers, one graph &#8212; the typed edges make every cross-tier question a one-hop query." title="Three tiers, one graph &#8212; the typed edges make every cross-tier question a one-hop query." srcset="https://substackcdn.com/image/fetch/$s_!_7Cv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 424w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 848w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 1272w, https://substackcdn.com/image/fetch/$s_!_7Cv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbbcbfc0-e8bd-484a-8ec6-eb4105fcc620_1400x1370.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Three tiers, one graph &#8212; the typed edges (</em><code>:MENTIONS</code><em>, </em><code>:INITIATED_BY</code><em>, </em><code>:TOUCHED</code><em>) make every cross-tier question a one-hop query.</em></figcaption></figure></div><p>Reasoning memory is the novelty from this architecture. By storing past successful or failed thinking patterns into the memory, the agent can one-shot future similar requests or at least know not to repeat similar mistakes. Intuitively, it&#8217;s similar to Reinforcement Learning (RL), but instead of baking the optimizations into the weights, you do it at the database level.</p><p>The most important part of this architecture is the ontology.</p><h2>The Ontology</h2><p>The long-term memory uses a closed five-type vocabulary for its ontology known as POLE+O. It uses Person, Object, Location, Event, and Organization, borrowed from intelligence-analysis taxonomies <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">[5]</a>. Every entity is exactly one of these five types. Subtypes are open, but the top-level vocabulary is fixed.</p><p>In the personal assistant, Karpathy is a Person. Claude Code is an Object. Anthropic is an Organization. Your Tuesday deep-research run is an Event. San Francisco is a Location.</p><p>Type and subtype materialize as multi-tier Neo4j labels. The query builder sanitizes and PascalCases them into labels like <code>:Entity:Person:Individual</code>. You can search by type or subtype, making this solution highly efficient.</p><p>Using this strategy, you can extend each core type from POLE+O with your own custom domain. Other defaults are: <code>:Entity:Location:City</code>, <code>:Entity:Event:Concert</code>, <code>:Entity:Organization:Company</code>, etc. <a href="https://create-context-graph.dev/docs/reference/domain-catalog">Here</a> is a catalog of over 20 domains such as Data Journalism, Gaming, Personal Knowledge, and Product Management.</p><p>Entities modeled via POLE+O are nouns. The SDK adds 2 other node types beyond entities.</p><p><code>:Fact</code> nodes hold every claim mentioned in the text. They&#8217;re intentionally generic so the ontology doesn&#8217;t get over-specified. They serve as a fallback when nothing else fits. You can intuitively see them as chunks of text that contain only 1 concept.</p><p>Then there are <code>:Preference</code> nodes that store user preferences via a <code>SUPERSEDED_BY</code> relationship. As agent memory is user-centric, this provides the WOW effect where the agent remembers past preferences and learns from them over time.</p><p>For the scoped wiki, &#8220;Anthropic developed Claude Code&#8221; is an edge. &#8220;Claude Code 1.0 shipped in 2025&#8221; is a <code>:Fact</code>. &#8220;I prefer agent-harness comparisons over pure benchmarks&#8221; is a <code>:Preference</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m-oO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m-oO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 424w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 848w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 1272w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m-oO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png" width="1400" height="1357" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1357,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A scoped-wiki graph built from the five POLE+O types.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A scoped-wiki graph built from the five POLE+O types." title="A scoped-wiki graph built from the five POLE+O types." srcset="https://substackcdn.com/image/fetch/$s_!m-oO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 424w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 848w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 1272w, https://substackcdn.com/image/fetch/$s_!m-oO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96ae330f-3585-4cc7-9dc5-831f2c778da4_1400x1357.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>A scoped-wiki graph built from the five POLE+O types &#8212; every node is exactly one of Person, Object, Location, Event, Organization, and every typed relationship is a </em><code>:RELATED_TO</code><em> edge with the semantic name carried as a property.</em></figcaption></figure></div><h2>Extraction: From Raw Text to Typed Entities</h2><p>The SDK runs entity extraction as a speed-versus-accuracy ladder. It uses spaCy for fast statistical NER. It uses GLiNER and GLiREL for zero-shot extraction. It uses an LLM stage for cases that need real semantics and to extract the relationships between them <a href="https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/">[6]</a>.</p><p>Each stage maps its outputs back to POLE+O types. It uses explicit merge strategies when 2 extractors disagree. When you drop a Readwise highlight about Claude Code into your scoped wiki, spaCy lifts proper nouns like Anthropic and San Francisco. GLiNER catches domain entities like Claude Code and Gemini CLI. The LLM stage only fires when the previous 2 stages leave ambiguity, or when the model needs to extract relationships.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sw5N!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sw5N!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 424w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 848w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 1272w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sw5N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png" width="1400" height="1369" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1369,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;From raw text to a clean graph &#8212; the three-zone SAME_AS pattern is what stops the same entity from becoming three nodes.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="From raw text to a clean graph &#8212; the three-zone SAME_AS pattern is what stops the same entity from becoming three nodes." title="From raw text to a clean graph &#8212; the three-zone SAME_AS pattern is what stops the same entity from becoming three nodes." srcset="https://substackcdn.com/image/fetch/$s_!sw5N!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 424w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 848w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 1272w, https://substackcdn.com/image/fetch/$s_!sw5N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad32c39-16d8-4231-b576-69087bff7511_1400x1369.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em> From raw text to a clean graph &#8212; the three-zone SAME_AS pattern is what stops the same entity from becoming three nodes.</em></figcaption></figure></div><p>Routing every mention through an LLM would multiply extraction cost massively for marginal recall on rare entities. The ladder pushes high-confidence cases to cheap models. It escalates only ambiguous mentions to the zero-shot models and reserves the LLM stage for when real semantics matter.</p><p>The real problem is at the normalization step.</p><h2>When Two Mentions Are the Same Entity (And When They Aren&#8217;t)</h2><p>Resolution and deduplication are 2 different problems. Resolution sets a canonical string property on an existing reference. Deduplication decides whether a new node gets created at all. Conflating them is how graphs end up with 3 Anthropic nodes that none of your queries find together <a href="https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/">[7]</a>.</p><p>Resolution runs 3 strategies on the name field in cost order. Exact matches existing canonical strings. Fuzzy uses RapidFuzz string similarity for surface variants like &#8220;A. Karpathy&#8221; and &#8220;Karpathy, Andrej&#8221;. Semantic falls back to embedding similarity for cases like &#8220;the founder of Eureka Labs&#8221;. It only matches between nodes of the same type, meaning a Person only resolves against Person candidates.</p><p>After resolution runs, two mentions like &#8220;Apple&#8221; and &#8220;Apple Inc.&#8221; end up with different surface names but the same canonical name. That&#8217;s why a second step is needed. Deduplication looks at the semantics, not just the name.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!joRt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!joRt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 424w, https://substackcdn.com/image/fetch/$s_!joRt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 848w, https://substackcdn.com/image/fetch/$s_!joRt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 1272w, https://substackcdn.com/image/fetch/$s_!joRt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!joRt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png" width="1400" height="1363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1363,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Same name, three outcomes &#8212; high similarity auto-merges, the middle band defers to a human, and low similarity creates two nodes that share a canonical name but live as separate referents.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Same name, three outcomes &#8212; high similarity auto-merges, the middle band defers to a human, and low similarity creates two nodes that share a canonical name but live as separate referents." title="Same name, three outcomes &#8212; high similarity auto-merges, the middle band defers to a human, and low similarity creates two nodes that share a canonical name but live as separate referents." srcset="https://substackcdn.com/image/fetch/$s_!joRt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 424w, https://substackcdn.com/image/fetch/$s_!joRt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 848w, https://substackcdn.com/image/fetch/$s_!joRt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 1272w, https://substackcdn.com/image/fetch/$s_!joRt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f4cbb67-cf5c-481b-b0e9-f7fa3f45eb1a_1400x1363.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Same name, three outcomes: High similarity auto-merges, the middle band defers to a human, and low similarity creates 2 nodes that share a canonical name but live as separate referents.</em></figcaption></figure></div><p>For deduplication, the SDK uses vector and fuzzy similarity across the entire node content. This ensures the node is actually the same, not just a name coincidence. In other words, this avoids false positives. Using vector and fuzzy search, the SDK computes a score.</p><p>Scores at or above 0.95 trigger an auto-merge. Scores below 0.85 create a new node. Scores between 0.85 and 0.95 don&#8217;t silently merge. Instead, they create a <code>:SAME_AS</code> edge with a pending status. This flags the edge for a human or downstream agent to resolve later. This pattern stops &#8220;Jensen Huang the NVIDIA CEO&#8221; from merging with &#8220;Jensen Huang the Taipei dermatologist&#8221; just because their embeddings landed 0.91 apart <a href="https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/">[7]</a>.</p><p>A false merge is silent and unrecoverable. A false split is noisy but recoverable. You can&#8217;t undo a false merge without re-ingesting from the raw source data. That&#8217;s why you should leave uncertainty to a human.</p><h2>Zooming into the Retrieval Algorithm</h2><p>Because all three tiers live on one graph, a single retrieval can compose vector similarity over <code>:Entity</code> embeddings, multi-hop expansion over typed relationships, time-ordered <code>:NEXT</code> conversation walks, and reasoning-trace lookups via <code>:INITIATED_BY</code> and <code>:TOUCHED</code> joins. All of these run as steps in the same Cypher query. Neo4j 5.20 introduces <code>db.index.vector.queryNodes</code>, making vector similarity a first-class graph operation <a href="https://neo4j.com/labs/agent-memory/explanation/graph-architecture/">[4]</a>.</p><p>When you ask what you know about Claude Code, how it relates to Codex and Gemini CLI, and why you looked at it last week, the agent fuses three things in one pull. It uses vector similarity over your Readwise highlights to surface relevant passages. It uses a multi-hop traversal of <code>:DEVELOPED_BY</code> and <code>:COMPETES_WITH</code> edges to bring in Anthropic and Codex neighbors. Finally, it uses an <code>:INITIATED_BY</code> jump back to the prior conversation that discussed agent harnesses. There&#8217;s no cross-store join logic and no orchestrator.</p><p>From our tests, the library leaves the context construction to the user of the SDK. In other words, you get the whole output from the graph, and it&#8217;s your responsibility to further compress it before passing it to the LLM.</p><h2>What&#8217;s Next</h2><p>The <a href="https://github.com/neo4j-labs/agent-memory">neo4j-labs/agent-memory</a> architecture is more complex than what this article covers, but this is the core idea behind it. I&#8217;ll cover other components in more depth in future articles, including designing the ontology and keeping your knowledge graph clean over time.</p><p>I think this open-source repository is a perfect blueprint you can take to build your own agent memory solution, even with Postgres or MongoDB, to avoid keeping multiple databases in production. Still, Neo4j is probably the best choice for data mining and exploration.</p><p>For small to medium-scale projects with thousands of nodes and short hop traversals, I&#8217;d probably build my own agent memory solution from scratch on top of Postgres or MongoDB. I&#8217;d reach for Neo4j as an internal tool within my organization, or when the scale or complexity becomes too large for Postgres or MongoDB.</p><p><em>But here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>How are you handling agent memory today? Flat files, a vector index, a knowledge graph, or something stranger?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/understanding-neo4j-graph-agent-memory-system?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>References</h2><ol><li><p>Seale, T. (n.d.). This week Anthropic dropped Claude Sonnet 4.5. LinkedIn. <a href="https://www.linkedin.com/posts/tonyseale_this-week-anthropic-dropped-claude-sonnet-activity-7379787334398926848-iVOE/">https://www.linkedin.com/posts/tonyseale_this-week-anthropic-dropped-claude-sonnet-activity-7379787334398926848-iVOE/</a></p></li><li><p>Monigatti, L. (n.d.). The Evolution From RAG to Agentic RAG to Agent Memory. Leonie Monigatti. <a href="https://www.leoniemonigatti.com/blog/from-rag-to-agent-memory.html">https://www.leoniemonigatti.com/blog/from-rag-to-agent-memory.html</a></p></li><li><p>Neo4j Labs. (n.d.). Understanding the Three Memory Types. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/memory-types/">https://neo4j.com/labs/agent-memory/explanation/memory-types/</a></p></li><li><p>Neo4j Labs. (n.d.). Why Neo4j? Graph-Native Memory Architecture. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/graph-architecture/">https://neo4j.com/labs/agent-memory/explanation/graph-architecture/</a></p></li><li><p>Neo4j Labs. (n.d.). POLE+O Data Model. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/poleo-model/">https://neo4j.com/labs/agent-memory/explanation/poleo-model/</a></p></li><li><p>Neo4j Labs. (n.d.). How Entity Extraction Works. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/">https://neo4j.com/labs/agent-memory/explanation/extraction-pipeline/</a></p></li><li><p>Neo4j Labs. (n.d.). Entity Resolution and Deduplication. Neo4j Agent Memory. <a href="https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/">https://neo4j.com/labs/agent-memory/explanation/resolution-deduplication/</a></p></li></ol><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item><item><title><![CDATA[From Vibe Coding to a Real Engineering Team]]></title><description><![CDATA[My Claude Code agentic coding setup that ships features end-to-end]]></description><link>https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026</link><guid isPermaLink="false">https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026</guid><dc:creator><![CDATA[Paul Iusztin]]></dc:creator><pubDate>Tue, 12 May 2026 11:04:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5s3I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5s3I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5s3I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5s3I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png" width="1376" height="768" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2577418-f25c-4206-a924-4dc119729cd3_1376x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:768,&quot;width&quot;:1376,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1362362,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://www.decodingai.com/i/196997194?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5s3I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 424w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 848w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 1272w, https://substackcdn.com/image/fetch/$s_!5s3I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2577418-f25c-4206-a924-4dc119729cd3_1376x768.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I needed a TypeScript harness for my latest book code. It required a Terminal User Interface (TUI), an agent loop, tools, Model Context Protocol (MCP) support, skills, and slash commands. I will be honest with you. I first tried to vibe code this project.</p><p>As I knew what I was looking for, it worked. Until it didn&#8217;t. The code was working until you started looking more closely at the details. Only the first 20 characters were rendering inside the TUI, and the skills weren&#8217;t invoked by the agent loop.</p><p>So I deleted the whole code base and started over with a new strategy.</p><p>The cost of vibe coding isn&#8217;t abstract. It&#8217;s the next feature you can&#8217;t ship because you&#8217;re debugging a slash-command renderer that looked finished. This is what most people get wrong. Output that compiles and looks done breaks the moment you reach for the rough edges.</p><p>I divided the harness into tasks. I one-shotted the barebones version, which was just a TUI plus an agent loop with <code>bash</code>, <code>grep</code>, and a todo tool. Then I layered MCP, skills, and slash commands as separate features.</p><p>You can&#8217;t one-shot whole applications. You can one-shot big features if you scope them right and run them through a real engineering process.</p><p>This is known as agentic coding. Not vibe coding. You&#8217;re using agents to write the whole codebase, but you are still the mastermind behind everything.</p><p>But I wanted more. I wanted to automate this process. But with a single constraint in mind: &#8220;the code should HAS to be good&#8221;.</p><p>That&#8217;s why I built Squid. It&#8217;s an opinionated six-agent Claude Code setup available at <a href="https://github.com/iusztinpaul/squid">iusztinpaul/squid</a>. It ships features the way a real software team ships them.</p><p>Squid has already shipped our content-automation tool, expanding it from articles to posts, notes, threads, and messages. It shipped the book&#8217;s code data pipelines and TypeScript harness.</p><p>In this article I will show you how it works.</p><p>The concrete blueprint relies on a specialized team and an e2e lifecycle.</p><div class="callout-block" data-callout="true"><h2><a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Start Your Transition Into AI Engineering (Product)</a></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2YEV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2YEV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 424w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 848w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2YEV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png" width="1400" height="1380" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1380,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Multi-agent free lesson architecture&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Multi-agent free lesson architecture" title="Multi-agent free lesson architecture" srcset="https://substackcdn.com/image/fetch/$s_!2YEV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 424w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 848w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!2YEV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef20e0ae-d28f-4cbf-bb86-675b4a0ab84a_1400x1380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Squid applies the multi-agent pattern to coding. My <a href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agentic AI Engineering course</a> applies it to writing, and I just released a free hands-on lesson that distills the whole system.</p><p>You build a multi-agent system composed of two FastMCP servers (Deep Research + LinkedIn Writer) orchestrated by a harness, plus an observability and evals layer on top. The shift from classic backend/frontend stacks to MCP servers and harnesses is the pattern shaping modern agentic AI.</p><p>Built for software and data engineers moving into agentic AI engineering.</p><p><em>Part of the 35-lesson course. Rated 5/5 by 300+ students. First 7 lessons free.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start the free lesson &#8594;&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://academy.towardsai.net/pages/free-lesson-offer-2?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start the free lesson &#8594;</span></a></p></div><h2>The Six Agents Engineering Team</h2><p>The system contains six agents. No agent both writes code and decides whether the code is correct.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9yS9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9yS9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 424w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 848w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 1272w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9yS9!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png" width="1200" height="1031.1258278145694" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1038,&quot;width&quot;:1208,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The six-agent team&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="The six-agent team" title="The six-agent team" srcset="https://substackcdn.com/image/fetch/$s_!9yS9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 424w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 848w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 1272w, https://substackcdn.com/image/fetch/$s_!9yS9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecde9a6b-b62d-4f38-a010-6c8af2e9728e_1208x1038.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">My Agentic Engineering Team</figcaption></figure></div><p>The <strong>product manager agent</strong> manages the tasks and ensures the feature adheres to the software architect&#8217;s specifications. It takes a raw feature specification, writes or updates an Architecture Decision Record (ADR) for non-obvious choices, and splits the feature into ordered tasks. It also maintains the Domain-Driven Design (DDD) glossary so vocabulary stays consistent between the business and engineering.</p><p>Note how, because Claude can easily handle both PM and software architecture work, we decided to merge these roles together. We did this to avoid fragmenting the context just to follow a standard human process. Ultimately, planning should be closely aligned with the software architect&#8217;s vision. In human processes, dividing these two responsibilities often created more issues than solutions.</p><p>The <strong>software engineer agent</strong> uses red-green Test-Driven Development (TDD). It writes the failing test, writes the minimal code to pass it, and then refactors. The software engineer uses direct command-line interfaces (CLIs) like <code>git</code>, <code>mongosh</code>, and <code>gh</code>. It never uses MCP wrappers. CLIs are more flexible because they tap directly into the power of bash. Plus, LLMs have seen considerably more bash code than MCP wrappers during training.</p><p>The <strong>tester agent</strong> specializes in the adversarial end-to-end edge-case pass. It catches false-confidence claims where the software engineer says the tests pass. It does this by reading every acceptance criterion against concrete evidence, like the test name, file lines, and command output.</p><p>The <strong>pull request reviewer agent</strong> performs a diff-only review. It looks for dead code, duplication, missing test coverage, and documentation adherence. It does a narrow performance review on hot paths only. It&#8217;s explicitly told not to micro-optimize one-off scripts.</p><p>The <strong>on-call agent</strong> loops on the Continuous Integration (CI) pipeline until it passes. In an earlier iteration, the CI check lived inside the software engineer and tester loop, and it got skipped constantly. Promoting it to a dedicated agent invoked by the orchestrator increased the probability the step runs.</p><p>The <strong>self-improve agent</strong> is an optional meta agent. After the feature is done, while looking over the results, the human can run the self-improve agent to scan the run for high-signal lessons and propose updates to the agentic coding layer that consists of <code>CLAUDE.md</code>, skills and subagents. This is a double-edged sword. It can constantly improve your workflow or quickly degrade it if you are not careful. That&#8217;s why it&#8217;s incredibly important that this step is gated by a human.</p><p>The secret sauce is in anchoring the agents into your own documentation.</p><h2>Keeping Up With Documentation: ADRs &amp; DDD Glossary</h2><p>The ADR directory acts as compressed architectural memory across runs. Every non-obvious choice regarding the datastore, synchronization defaults, authentication boundaries, or dependency lock-in ships with an ADR. These records include the status, context, decision, and consequences at <code>docs/adr/&lt;NNNN_title&gt;.md</code>. The product manager reads the directory before grooming a new feature, so decisions stay consistent across feature branches.</p><p>The DDD glossary gives shared vocabulary between the business and engineering at <code>docs/glossary.md</code>. It enforces one canonical name per concept. Code identifiers, OpenAPI schemas, database columns, and customer-facing interfaces all use the term exactly as it appears there. This gives Claude Code business context, not just code context, properly anchoring your code in your domain. The software engineer, tester, and pull request reviewer all reason about the same domain.</p><p>I have an honest caveat. The agents still under-use both the ADRs and the glossary. The spine exists, but I am still working on getting the agents to lean on it consistently.</p><p>Now the agents have the context they need to execute a feature from a raw specification all the way to a merged pull request.</p><h2>The Night Skill. The End-To-End Workflow.</h2><p>The <code>/night</code> skill takes one input, which is a feature specification written by the human, and produces one output, which is a merged pull request with green CI. Everything in this section sits between those two endpoints.</p><p>The <code>/night</code> pipeline is a long-running lifecycle. That&#8217;s why it&#8217;s called the &#8220;night&#8221; skill. It&#8217;s scoped to run for hours at a time, often with multiple pipelines in parallel.</p><p>It has two human checkpoints and five retry caps, while everything else is automated. The orchestrator acts as a manager. It never writes code itself, never runs tests itself, and never reviews the diff itself. It launches agents and enforces human validation.</p><p>After a human carefully writes a detailed feature specification, it calls the <code>/night</code> skill, which creates a new branch and worktree. The product manager reads the glossary and ADR directory, updates or writes a new ADR if needed, and splits the feature into a task plan.</p><p>Then we hit the first human gate. The user approves the plan, optionally sharpened by the <code>/grill-me</code> skill. The <code>/grill-me</code> skill is inspired by Matt Pocock&#8217;s work, which forces the agent to ask sharp questions back about anything fuzzy in the plan, such as interfaces, modularization, or new tools. This conversation is the line between vibe coding and agentic coding.</p><p>Next is the inner loop per task. The software engineer implements the code, the tester verifies it, and failures route back to the software engineer. This loop is capped at 5 attempts. Convergence is mostly mechanical through a run, fail, fix, and run cycle.</p><p>The product manager then performs an acceptance review on the whole feature from the user&#8217;s perspective. Rejections are packed into a single task back into the inner loop. This is capped at 3 attempts, because judgment-call loops are where Claude Code spirals.</p><p>Next, we repeat a similar loop using the PR reviewer agent, which looks at the diff, with a maximum of 3 attempts to avoid perfectionism. Adding a maximum number of attempts here is critical, because during review an LLM almost always has something else to say.</p><p>After the push, the on-call agent watches CI with a maximum of 5 attempts, routing failures back to the software engineer.</p><p>When the CI is green, we notify the user (e.g., via Slack) that the PR is ready for review. Optionally, based on any potential issues found while running the <code>/night</code> skill, we run <code>self-improve</code> to propagate that into your memory.</p><p> The /night lifecycle. Two human gates, five retry caps, everything else automated.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8VWO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8VWO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 424w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 848w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 1272w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8VWO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png" width="1200" height="965" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:965,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The /night lifecycle. Two human gates, five retry caps, everything else automated.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The /night lifecycle. Two human gates, five retry caps, everything else automated." title="The /night lifecycle. Two human gates, five retry caps, everything else automated." srcset="https://substackcdn.com/image/fetch/$s_!8VWO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 424w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 848w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 1272w, https://substackcdn.com/image/fetch/$s_!8VWO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5775bbe9-c91b-46fe-94ef-1a819be0bce8_1200x965.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">My Agentic Coding Setup</figcaption></figure></div><p>Beautiful! With this process I one-shot most of the features I am working on. And when it&#8217;s not a one-shot, I&#8217;m typically 95&#8211;99% there by the time I review the PR.</p><h2>How the Tester Stopped Re-Running What the SWE Already Ran</h2><p>The biggest problem with the e2e workflow above is that it&#8217;s slow and redundant. I preferred that over generating AI slop that I have to manually review and fix.</p><p>Still, there are a few tweaks that we can make to the workflow to improve speed and efficiency.</p><p>For example, when the tester re-ran the linter, type checker, formatter, and the happy-path suite that the software engineer had already run, we paid for everything twice. This was the number-one source of having a system that works but is too slow to use.</p><p>To fix this, the tester now accepts the software engineer&#8217;s reports for formatting and happy-path tests. It only runs the adversarial end-to-end edge-case pass itself. This covers the part the software engineer can&#8217;t credibly self-verify. Trust is bounded. Intuitively, I realized I&#8217;d started shifting the <code>Tester</code> toward QA-style practices, rather than just running simple tests.</p><p>I am still iterating on optimizations. For example, I want to route some subagents to Claude Sonnet models instead of Claude Opus. I also plan to narrow toolsets per role to reduce reasoning failures.</p><p>Also, depending on what you are working on, you might want to use the system more as a fast, snappy assistant than as a long-running workflow that prioritizes correctness above all.</p><h2>Day vs. Night: Two Orchestrators, One Team</h2><p>That&#8217;s why we have two pipelines running the same agents. The <code>/night</code> skill is the full lifecycle. It&#8217;s long-running, set-and-forget, has two human gates, and runs while you are away from the keyboard or working in parallel.</p><p>The <code>/day</code> skill is the lean inner loop. It runs the software engineer, the tester, and human commits for surgical edits. It skips product manager grooming, the pull request reviewer, and the on-call agent.</p><p>There is a concrete use case for the <code>/day</code> skill. When I read a merged pull request and find code I don&#8217;t like, the <code>/day</code> skill runs the stripped software engineer and tester loop to apply targeted edits. Then the on-call agent cleans up any CI fallout. This is the surgery that keeps the system from becoming a black box.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2bZF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2bZF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 424w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 848w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 1272w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2bZF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png" width="1200" height="965" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:965,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Day vs. Night &#8212; same agent team, two orchestrators tuned for different workloads.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Day vs. Night &#8212; same agent team, two orchestrators tuned for different workloads." title="Day vs. Night &#8212; same agent team, two orchestrators tuned for different workloads." srcset="https://substackcdn.com/image/fetch/$s_!2bZF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 424w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 848w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 1272w, https://substackcdn.com/image/fetch/$s_!2bZF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1143ede6-93a8-4c72-ac85-3f12071bd61b_1200x965.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Day vs. Night: Same agent team, two orchestrators tuned for different workloads.</figcaption></figure></div><p>Both pipelines have one thing in common. The human is in the loop on purpose, not as a fallback.</p><h2>Why Code Templates Are a Waste of Time in 2026</h2><p>Most teams are still scaffolding from cookiecutter templates that were outdated the day they were committed. This is a maintenance tax disguised as productivity. Squid stops paying that tax. Technology moves fast enough that any frozen template&#8217;s frameworks, tooling, interfaces, and opinions all need their own maintenance pipeline. That&#8217;s only worth it if one template fans out across dozens of projects.</p><p>A Copier or cookiecutter template isn&#8217;t free. I tried scaling one across Python, TypeScript, and Go. I watched the project balloon into a maintenance burden where most files would never be used. Maintaining a template engine to support multiple stacks is a full-time job.</p><p>Asking Claude Code to copy from the last project fails too. It propagates the technical debt baked into the source codebase. You inherit the mess, not the ideal state.</p><p>The real shift relies on markdown, not Jinja. I call these <strong>agentic templates</strong>.</p><p>You encode good practices as skills and <code>CLAUDE.md</code> files. Fundamentals like clean architecture, CI/CD discipline, testing patterns, and development cycles rarely change. When they do change, you edit prose instead of regenerating from a template engine that quickly slides into dependency hell.</p><p>Tooling stays dynamic. You don&#8217;t pin framework versions inside a template. You keep a decision tree of allowed choices and let the agent pull the latest interfaces on demand via Context7 at scaffold time.</p><p>Project structure can&#8217;t be templatized. The anti-pattern organizes by type, putting files into <code>agents/</code>, <code>nodes/</code>, <code>schemas/</code>, and <code>tools/</code> directories. One business module&#8217;s logic ends up scattered across four folders, forcing both humans and the agent&#8217;s context window to thrash.</p><p>The correct pattern organizes by actionability, keeping one bounded context per directory. Each domain owns its own types, store, Application Programming Interface (API), and prompts. That&#8217;s locally readable, easier to maintain, and easier for the agent to reason about.</p><p>Because we describe the structure in Markdown files instead of cookiecutter templates, we can define it like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bhZj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bhZj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 424w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 848w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 1272w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bhZj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png" width="1456" height="946" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:946,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;code&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="code" title="code" srcset="https://substackcdn.com/image/fetch/$s_!bhZj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 424w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 848w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 1272w, https://substackcdn.com/image/fetch/$s_!bhZj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83fcb967-260a-49e3-af0c-b1a7f0181e01_2737x1779.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image buttonBase-GK1x3M"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" class="icon-noB79L"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image buttonBase-GK1x3M"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2 icon-noB79L"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Avoid global dumping grounds like <code>utils/</code> or <code>helpers/</code>. Avoid a root-level <code>types.py</code> grab bag. Avoid grouping tests by type.</p><p>The <code>/scaffold</code> skill acts as an interactive bootstrap. An <code>AskUserQuestion</code> prompt drives a tight decision tree covering project identity, layout, components, backend, frontend framework, infrastructure, agent team, tracker, ADR and glossary opt-ins, and external services. A deterministic table picks only the matching specifications from the specification library. Unused categories never enter the context. The skill writes a tailored <code>CLAUDE.md</code> brief, lays down an empty folder skeleton, and hands off.</p><p>Then, based on the agentically generated template, you can use <code>/night</code> or <code>/day</code> to start writing real code.</p><h2>Open-Sourcing Squid</h2><p>I don&#8217;t want to keep Squid for myself. I want to share it with the community to learn from and contribute to.</p><p>Thus, <strong>I am open-sourcing <a href="https://github.com/iusztinpaul/squid">Squid</a>.</strong></p><p>You can install it as a Claude Code plugin:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">/plugin marketplace add iusztinpaul/squid
/plugin install squid@squid</code></pre></div><p>I want you to try it, build something awesome with it, and if you like it, contribute back:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://github.com/iusztinpaul/squid&quot;,&quot;text&quot;:&quot;Check the full codebase&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://github.com/iusztinpaul/squid"><span>Check the full codebase</span></a></p><p><em>Still, here is what I&#8217;m wondering:</em></p><blockquote><p><em><strong>What is your agentic coding setup? How is Squid different from your own approach?</strong></em></p></blockquote><p><em>Click the button below and tell me. I read every response.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026/comments"><span>Leave a comment</span></a></p><div><hr></div><p><em>Enjoyed the article? The most sincere compliment is to restack this for your readers.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.decodingai.com/p/squid-my-agentic-coding-setup-may-2026?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><div class="callout-block" data-callout="true"><h4>Whenever you&#8217;re ready, here is how I can help you</h4><p><em>Go from agent user to agent builder.</em> Master the foundations of AI agents and turn fragile demo code into reliable, production-ready systems with my course, <strong><a href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">Agent Engineering: Building Multi-Agent Systems</a></strong> (made with Towards AI).</p><p>35 lessons. Pure foundations from scratch. 4 mini-projects. 2 production systems. A certificate and direct access to me &amp; industry experts in our Discord.</p><p>Built for software and data professionals transitioning into AI engineering. <em>Rated 5/5 with 300+ students. The first 7 lessons are free:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering&quot;,&quot;text&quot;:&quot;Start here&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://academy.towardsai.net/courses/agent-engineering?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering"><span>Start here</span></a></p><p><em>Not ready to commit?</em> Start with our <strong><a href="https://email-course.towardsai.net/?ref=b3ab31&amp;utm_source=decodingai&amp;utm_medium=partner&amp;utm_campaign=agent_engineering">free Agent AI Engineering Guide</a></strong>, a 6-day email course on the mistakes that silently break AI agents in production.</p></div><div><hr></div><h2>Images</h2><p>If not otherwise stated, all images are created by the author.</p>]]></content:encoded></item></channel></rss>