<?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[Ship's Log]]></title><description><![CDATA[Looking into how things work.]]></description><link>https://rocketvish.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!nzzl!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70914df0-f527-4d65-b046-7baa9e4af2fd_512x512.png</url><title>Ship&apos;s Log</title><link>https://rocketvish.substack.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 13 May 2026 06:11:43 GMT</lastBuildDate><atom:link href="https://rocketvish.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Vishnu Kalugotla]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[rocketvish@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[rocketvish@substack.com]]></itunes:email><itunes:name><![CDATA[Vishnu Kalugotla]]></itunes:name></itunes:owner><itunes:author><![CDATA[Vishnu Kalugotla]]></itunes:author><googleplay:owner><![CDATA[rocketvish@substack.com]]></googleplay:owner><googleplay:email><![CDATA[rocketvish@substack.com]]></googleplay:email><googleplay:author><![CDATA[Vishnu Kalugotla]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Compressing Coding Agent Context at Models' Native Representation Layer]]></title><description><![CDATA[Explores whether compressing model context at the representation level, rather than the text level will help preserve important details more efficiently.]]></description><link>https://rocketvish.substack.com/p/compressing-coding-agent-context</link><guid isPermaLink="false">https://rocketvish.substack.com/p/compressing-coding-agent-context</guid><dc:creator><![CDATA[Vishnu Kalugotla]]></dc:creator><pubDate>Mon, 11 May 2026 17:29:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!RntL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2><strong>Introduction &amp; problem</strong></h2><p>Modern agent/model workflows rely on context (essentially conversation history) to be effective. As context grows<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>, models &#8220;forget&#8221; details, slow down, and otherwise display eroded performance, especially as this growing context is compacted<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p><p>Every major coding agent today handles context compression through text summarization (according to public documentation).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>  This post builds on past work and explores compressing at the representation level, rather than the text level to see if it&#8217;s possible to more-efficiently preserve important details.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Below, we get deep into the details&#8212;skip to the <a href="https://rocketvish.substack.com/i/197145273/practical-implications-and-final-thoughts">practical implications section</a> for conclusions and takeaways. </p><h2><strong>What we&#8217;re tackling</strong></h2><p>Every time you send a message to an LLM, the entire conversation history gets re-sent as context in the form of English. Coding agents feel this most acutely because their conversations are long (full of tool calls) and the details matter (a wrong file name or path results in broken code). In <a href="https://substack.com/home/post/p-194259777">Part 3 of this series</a>, I discussed how prompt caching (widely used today) reduces compute costs by ~70% by avoiding redundant computation. However, caching doesn&#8217;t mitigate the fact that infinitely growing context is difficult to manage and impacts output quality.</p><p>Today&#8217;s coding agents handle this by truncating old turns, summarizing them into shorter text, or increasing context window size.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> Claude Code, for example, auto-compacts at 95% capacity, while Cursor truncates old history. Note that these are text-level interventions&#8212;they modify the English conversation before sending it back to the model, while internally representing this information as numerical vectors.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NpKt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NpKt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 424w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 848w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 1272w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NpKt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png" width="1456" height="380" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:380,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60802,&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://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.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_!NpKt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 424w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 848w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.png 1272w, https://substackcdn.com/image/fetch/$s_!NpKt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccfe9f3b-4fc0-4238-8d49-1bcbefda26d0_1799x470.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"><svg role="img" 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"><g><title></title><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"><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"><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">Each call re-sends the full conversation as text. The model processes it, generates a response, and that gets added back for the next trip. </figcaption></figure></div><p>Seeing this made me ask: <em>what if we interacted with internal representations directly?</em></p><p>When a model processes your conversation, it builds representations in the form of numerical vectors<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> that encode its understanding of each token in context. When the model generates a response, that understanding gets turned back to English text, and the internal state is discarded<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a>. In the next turn, the model rebuilds everything all over again.</p><p>Below, we investigate compressing conversation context into the model&#8217;s own representation format. Our experiments compressed a 10-turn coding agent conversation to ~50% of its token count while correctly answering 7 of 8 factual questions about the conversation's content.</p><h2><strong>What we&#8217;re actually doing</strong></h2><p>When a model reads the text &#8220;the project uses <code>bcryptjs </code>for password hashing<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a>,&#8221; it creates internal vectors at each of its layers<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a>. These vectors encode important context<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-9" href="#footnote-9" target="_self">9</a> in the human-literal sense&#8212;that <code>bcryptjs </code>is a specific npm package and that it&#8217;s being used for some security function.</p><p>The way we compress is as follows: we create &#8220;<strong>virtual</strong>&#8221; <strong>tokens</strong>, which are new vectors initialized from mean-pooled embeddings<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-10" href="#footnote-10" target="_self">10</a>, and  we tune them using gradient descent<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-11" href="#footnote-11" target="_self">11</a>  until the model&#8217;s internal response to them matches its response to the original text. After optimization, these virtual tokens become representations that produce approximately the same internal state when the model processes them as if it had read the full text.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nWeS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nWeS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 424w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 848w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 1272w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nWeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png" width="1456" height="1094" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1094,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154478,&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://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.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_!nWeS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 424w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 848w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.png 1272w, https://substackcdn.com/image/fetch/$s_!nWeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F361bfc35-2930-4fbc-8ca9-b8cb17865ce7_1751x1316.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"><svg role="img" 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"><g><title></title><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"><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"><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">How the optimization works: we run the original tokens through the frozen model to get &#8220;target&#8221; V-vectors. Then, we iteratively adjust virtual token embeddings until they match the target. </figcaption></figure></div><p>The model itself is frozen, meaning that we&#8217;re not training or fine-tuning it. In other words, <strong>we&#8217;re finding inputs that, when fed through the frozen model, reproduce the internal states that represent the content we want to maintain that are smaller than the original inputs</strong>.</p><h2><strong>How we tested this</strong></h2><h3><strong>The setup</strong></h3><p>We ran all of the experiments on a local RTX 5090<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-12" href="#footnote-12" target="_self">12</a> with 32 GB of VRAM using Qwen 2.5 Coder 7B-Instruct at 8-bit quantization. This particular Qwen model satisfied a few requirements:</p><ul><li><p>We needed a local open-weight model because our technique required gradient access, which API-based models don&#8217;t expose.</p></li><li><p>We couldn&#8217;t fill the entire 32 GB VRAM capacity with Qwen parameters because we needed room for gradient computation alongside the loaded model.</p></li></ul><h3><strong>The data</strong></h3><p>We used a (very) generic coding agent transcript recorded from our benchmark in <a href="https://substack.com/home/post/p-194259777">Part 3</a>: a 57-turn conversation where an AI agent builds a task management API with Express and SQLite as an example of a coding workflow. The transcript includes (brief) system prompts, tool calls, file reads, code generation, and debugging.</p><p>For single-turn experiments, we worked with a 4,096-token window from this transcript (12 turns). For sequential experiments, we split it into:</p><ol><li><p>Prefix: system prompt</p></li><li><p>Middle: X turns</p></li><li><p>Suffix: most recent exchange</p></li></ol><h3><strong>The evaluation</strong></h3><p>We test whether the model can answer factual questions about the conversation using compressed context, measured against full context.</p><ul><li><p>&#8220;What library does the project use for password hashing?&#8221; (answer: <code>bcryptjs</code>, not just <code>bcrypt</code>)</p></li><li><p>&#8220;What is its <code>Node.js</code> test runner?&#8221; (answer: <code>node:test</code>, not <code>Jest</code>)</p></li><li><p>&#8220;Does the markdown converter use a library or <code>regex</code>?&#8221; (answer: <code>regex-based</code>, no external library)</p></li></ul><p>The scoring is keyword-based to keep complexity low, and scores unambiguous and deterministic. This tests whether specific details survive compression and won&#8217;t get fooled by plausible-sounding text.</p><h3><strong>Why this evaluation is useful</strong></h3><p>Each question has three properties that make it a reasonable test of compression quality:</p><p><strong>The answer exists only in the compressed turns</strong>: We verify that the system prompt and what I call the suffix (latest input) don&#8217;t contain the answer. The model can only get it right by extracting information from the compressed representation.</p><p><strong>The model has a wrong &#8220;default&#8221;:</strong> When given no context, the model guesses <code>bcrypt </code>(not <code>bcryptjs</code>), <code>Jest </code>(not <code>node:test</code>), and <code>marked </code>(not <code>regex</code>). These are what I expect are the most popular options from training data. Correct answers require overriding these &#8220;defaults&#8221; with specific context, which is what our compression methodology needs to preserve.</p><p><strong>There are specific ways to be wrong:</strong> <code>bcryptjs</code> vs <code>bcrypt</code> is a tiny change and <code>node:test</code> vs <code>Jest</code> is a completely different tool. These are the kind of specific details that text-level summarization (or context compression in general) could easily lose.</p><h2><strong>The compression recipe that worked</strong></h2><p>In subsequent sections, I&#8217;ve gone into depth on several paths (and dead ends) that led me to a working &#8220;recipe&#8221; for efficiently compressing context. That recipe is as follows.</p><h4><strong>Use Value-only optimization targets (vs. Query and Key)</strong></h4><p>Optimize virtual tokens so their Value vectors (at all layers) approximately match the Value vectors from the full text. This means excluding Keys entirely from the loss (more on this later).</p><p>V-vectors carry the actual content that gets processed through attention, the data payload. K-vectors serve as an index&#8212;they help the model decide which tokens to attend to. During inference, the model applies RoPE to the virtual tokens&#8217; K vectors at their positions automatically. Since we only optimize V (which is position-independent), we don&#8217;t need to worry about positional encoding during the optimization step.</p><p>This finding was critical because it circumvents the RoPE problem I hit in Failure 2 below&#8212;pooling K vectors from different positions averages together incompatible rotational encodings. There&#8217;s been significant work done on KV optimization, and I&#8217;ll continue to explore this in future studies. Optimizing V-vectors is simple and more architecture-general.</p><h4><strong>Use perplexity-weights when V pooling</strong></h4><p>As in any robust compression, when pooling (i.e., &#8220;averaging&#8221; or compressing) the V-vectors above into blocks, <strong>not all tokens should get equal weight</strong>.</p><p>We computed per-token perplexity (also known as surprisal or &#8220;cross-entropy&#8221; when averaged across tokens), which calculates how &#8220;surprised&#8221; the model was by each token. Boring or &#8220;unsurprising&#8221; tokens (articles, whitespace) get low weight. Surprising tokens (specific library names, unique identifiers) get high weight.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RntL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RntL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 424w, https://substackcdn.com/image/fetch/$s_!RntL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 848w, https://substackcdn.com/image/fetch/$s_!RntL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!RntL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RntL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png" width="1456" height="1030" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/397af75e-bf92-4576-bce3-be703127c920_1781x1260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1030,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:156152,&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://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.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_!RntL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 424w, https://substackcdn.com/image/fetch/$s_!RntL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 848w, https://substackcdn.com/image/fetch/$s_!RntL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!RntL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F397af75e-bf92-4576-bce3-be703127c920_1781x1260.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"><svg role="img" 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"><g><title></title><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"><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"><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">Uniform pooling averages all tokens equally, potentially diluting specific details. Perplexity-weighted pooling down-weights predictable tokens, better preserving the signal carried by more informative ones. </figcaption></figure></div><p>This weighting mechanism doubled the evaluated compression threshold from 1.6x to 3.2x. This mechanism was a bit unintuitive<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-13" href="#footnote-13" target="_self">13</a>&#8212;it works by <em>down-weighting &#8220;boring&#8221; tokens</em> rather than boosting important ones. When predictable tokens carry less weight in the average, the resulting pooled representation is naturally closer to the informative tokens. The optimizing step then has an easier path to matching these improved targets. For example, the loss at 100 virtual tokens dropped from 8.03 to 4.85 compared to uniform pooling in our experiment.</p><h4><strong>Interpolate positions</strong></h4><p>Virtual tokens need positions for RoPE on their K vectors during inference. By default, virtual tokens would get consecutive positions (e.g., 144, 145, ..., 218), while the original tokens might occupy different positions (e.g., 146, ..., 385). We spread the virtual tokens&#8217; positions across the original range: <code>torch.linspace(144, 385, 75)</code>.</p><p>The critical change here is that it preserves the positional distribution that downstream attention expects<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-14" href="#footnote-14" target="_self">14</a> in models. When the suffix (i.e., most important) tokens compute attention, the relative distances to each virtual token approximate the distances to the original tokens. The suffix tokens start at position 386 in our example, regardless of how many virtual tokens there are, acting as if the full middle were present.</p><p>The effect is small at low compression (positions are already dense) and more meaningful at high compression, where position clustering would otherwise distort attention patterns.</p><h4><strong>An important note on practicality</strong></h4><p>This is a proof of concept&#8212;per-instance gradient optimization the way we&#8217;ve done it here is too computationally intensive and slow for production use. The path to get it production-ready likely requires training a neural net to predict the compressed virtual token embeddings.</p><h2><strong>What I tried, what failed, and lessons</strong></h2><p>To get to the working recipe above, I tried numerous approaches and hit several hurdles. Below is a map of that path and how each failed test narrowed the design space that led to the results.</p><p>Note that when I&#8217;m discussing &#8220;loss&#8221; below, I&#8217;m referring to mean-squared error between two sets of vectors that gradient descent is minimizing. The two sets in this case were virtual tokens and the real tokens they were attempting to represent.</p><h4><strong>Failure 1: Optimizing for final layer is the wrong objective</strong></h4><p>My first approach was to create virtual tokens and optimize them so that the model&#8217;s output at the final layer matches what the real tokens produce. Using this method, it looked like the virtual tokens were producing &#8220;correct&#8221; final representations.</p><p>However, in testing, our eval answers looked like there was no context at all, and the model was &#8220;guessing&#8221; its training defaults.</p><p><strong>The lesson:</strong> When the model generates text, it isn&#8217;t solely reliant on its final layer<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-15" href="#footnote-15" target="_self">15</a>. At every layer independently, each generated token attends to the KV cache entries from previous tokens. This means that optimizing only for the final layer results in significant loss in previous layers.</p><h4><strong>Failure 2: Including Keys in optimization difficult due to RoPE</strong></h4><p>In my next attempt, I switched to optimizing the KV entries at all 28 layers. I noticed that loss declined (and later significantly plateaued), but the eval answers were still often wrong.</p><p>The problem: Modern models apply position-dependent rotations to Key vectors, which is called Rotary Position Embeddings, or RoPE. The purpose of RoPE is to encode token positions in a way such that when the model calculates attention, it naturally takes into account relative positions between each token. When we start pooling K vectors from various positions, however, we start averaging vectors with different rotational encodings. The result is a rotational mess that no single-position virtual token can match.</p><p>I also confirmed that RoPE isn&#8217;t unique to Qwen models, and is used by LLaMA, Gemma, and virtually every modern open-weight model. Any compression approach that targets K vectors will hit this wall.</p><p><strong>The lesson:</strong> RoPE makes K vectors position-dependent, but Value vectors are position-independent. We verified in Qwen&#8217;s source: <code>query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)</code>. This means we can modify and optimize V without worrying about positional encoding.</p><p>There&#8217;s room for improvement here since RoPE rotations are deterministic and reversible, a future approach could undo the rotation, optimize K pre-RoPE, then re-apply it for inference</p><h4><strong>Failure 3: Attention-weighted pooling is both question-specific and regresses results</strong></h4><p>Once V-only optimization was working, I tried improving the pooling targets (it&#8217;s something we&#8217;ll have to come back to in future work). Instead of giving all V vectors equal weight when averaging them into blocks, I tried weighting them by how much the evaluation question&#8217;s tokens attended to each position. The thought was: high-attention tokens should be preserved better, right?</p><p>It&#8217;s important to note, though, that this was a rudimentary approach chosen for simplicity given the risk of &#8220;overfitting.&#8221; The results actually got <em>worse</em>. 150 tokens went from 3/3 to 2/ 3 correct answers.</p><p><strong>The lesson:</strong> Attention-weighted pooling is inherently question-specific. Weighting toward one question&#8217;s attention pattern down-weights tokens that other questions need. There may be better weighting mechanisms for query-agnostic compression that we can explore in the future.</p><h3><strong>An aside on the helpfulness of AI</strong></h3><p>It goes without saying that AI coding agents were integral in running these experiments. Of course, AI was vital in writing the necessary Python code to create and run the tests. What I didn&#8217;t expect, though, was how I used it to help me run feasibility tests to avoid hitting unnecessary obstacles. For example: </p><div class="callout-block" data-callout="true"><p>Mr. AI, please help me figure out which Qwen model to use so I don&#8217;t overflow to system DRAM if I have to run gradient descent on my loaded model and therefore have it take days to run.</p></div><h3><strong>Results Summary</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8SyG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8SyG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 424w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 848w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 1272w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8SyG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png" width="1456" height="373" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:373,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78870,&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;:&quot;https://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png&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_!8SyG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 424w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 848w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.png 1272w, https://substackcdn.com/image/fetch/$s_!8SyG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e7eada2-b9d2-4f5e-a815-f176dc72a090_1560x400.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"><svg role="img" 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"><g><title></title><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"><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"><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">Shows single-turn compression across three different content types: 3.2x compression preserves all tested facts regardless of content type.</figcaption></figure></div><p><strong>3.2x is the lossless (in this eval) threshold for all three turns.</strong> Larger turns compress equally well. Turn 24 has the lowest optimization loss at every ratio, suggesting more tokens give the optimizer more material to work with.</p><p><strong>At 4.8x, failures follow a similar pattern of degrading names or strings:</strong></p><ul><li><p>&#8220;<code>bcryptjs</code>&#8221; &#8594; &#8220;<code>bcrypt</code>&#8221; (dropped the JS suffix)</p></li><li><p>&#8220;<code>dev-secret</code>&#8221; &#8594; &#8220;<code>dev-dev-dev-dev-dev...</code>&#8221; (strange repetition of the prefix)</p></li><li><p>&#8220;<code>done</code>&#8221; &#8594; &#8220;<code>completed</code>&#8221; (fell back to a training synonym)</p></li></ul><p>Structural facts seem to survive much longer than exact names. For instance, the model knows which library is used for password hashing well past the point where it &#8220;forgets&#8221; the exact name of that library.</p><h3><strong>Sequential multi-turn: 2x preserves most facts across 10 turns</strong></h3><p>Single-turn compression gives us a great signal on the compression mechanism we tested,  but coding agents rely on long, multi-turn conversations. The next step was testing sequential compression: compressing each turn independently and building up a running KV cache.</p><h5>Sequential Compression in practice</h5><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wt0j!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wt0j!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 424w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 848w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 1272w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wt0j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png" width="1456" height="1136" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1136,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:128255,&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;:&quot;https://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png&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_!Wt0j!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 424w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 848w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.png 1272w, https://substackcdn.com/image/fetch/$s_!Wt0j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02517bc7-58b0-4748-b248-caa58a5a2394_1715x1338.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"><svg role="img" 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"><g><title></title><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"><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"><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">Each turn is compressed independently against the running cache. The compressed representation grows incrementally as the conversation progresses.</figcaption></figure></div><h5><strong>Sequential Compression Results</strong></h5><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qM3b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qM3b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 424w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 848w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qM3b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png" width="1400" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50965,&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://rocketvish.substack.com/i/197145273?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.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_!qM3b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 424w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 848w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.png 1272w, https://substackcdn.com/image/fetch/$s_!qM3b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8831ebb-76b7-477e-815a-89e0824fad0a_1400x400.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"><svg role="img" 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"><g><title></title><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"><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"><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">Multi-turn compression across 10 turns: 2.0x compression preserves 7 of 8 factual answers, which is the same quality as 1.5x at lower token cost.</figcaption></figure></div><p>The main finding was that there is <strong>minimal error accumulation across turns:</strong> meaning the optimization process works equally well at each step. The remaining question, whether the targets themselves drift as compressed context accumulates, is harder to measure directly in this set of experiments. That said, the fact that 2x compression still preserves 7 of 8 answers suggests this drift (if it exists) remains bounded.</p><h2><strong>Practical Implications and final thoughts</strong></h2><p>Getting deep into manipulating internal representations to optimize coding agents, as we&#8217;ve done here, can help us gain an intuitive and applicable understanding of several concepts and model behaviors. Taking that understanding and applying it to real user problems reveals insights that can help us shape how we might build the coding agents of tomorrow.</p><p>In these experiments, we&#8217;ve learned that categorical facts like &#8216;the project uses JWT for authentication&#8217; survive high compression, while exact names like <code>bcryptjs</code> degenerate to the model&#8217;s &#8220;defaults,&#8221; <code>bcrypt</code>, under high compression. Despite the challenge, we&#8217;ve also learned that there&#8217;s <strong>significant headroom</strong> <strong>for more context efficiency in coding agents</strong>. Making such improvements would solve several key issues with coding agents as they exist today, and might make them more useful broadly. Applying the above, I would combine several approaches to create a personalized and efficient context strategy.</p><p><strong>Compression</strong>: Compress context at the representation level with V-vector optimization, using perplexity to weight V-pooling and interpolate virtual tokens. Our proof of concept shows that it may be possible to compress context ~3x using this method. This is also complementary to caching&#8211;combining compression with prompt caching could reduce context costs by 80-90%. Of course, the next step would be building a model to productionize what we&#8217;ve learned. </p><p><strong>Systematic Preservation of Vital Information</strong>: Preserve vital information and keep it verbatim (more to follow on how best to do this in future work). Simple file systems and knowledge graphs using markdown files seem to be the most popular approach. It may also make sense to preserve important information from these file reads in a context window verbatim. This is where personalization comes into play&#8212;what type of &#8220;memory&#8221; system someone uses and what serves as useful information outside of interacting with an agent differs from person to person. This is also complementary to compression.</p><p><strong>Intelligent Compaction</strong>: We&#8217;ve discussed before that Anthropic <a href="https://github.com/anthropics/claude-code/issues/43989">moved away</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-16" href="#footnote-16" target="_self">16</a> from exposing very long (1M token+) context windows by default given the intrinsic issues. With the above techniques at our disposal, we could be more intelligent about <em>when </em>we compress  instead of waiting for a certain context window threshold.</p><p>I would love to explore using signals to automatically trigger compaction and disposal of context, or encourage users to provide those signals directly. Examples include: forking conversations, discarding the last turn if it had a poor result, and having a meta conversation that preserves specific context. This same principle also applies to sub-agents&#8212;deciding explicitly whether sub-agents should have context (and what context), and where they should write outputs.</p><div class="callout-block" data-callout="true"><p><strong>In today&#8217;s landscape, a lot of the burden of context management (and even understanding the problem) is put on the user. We could abstract this into the model harness itself, powered by new techniques.</strong></p></div><h2>Future work</h2><p>There are several directions I want to explore from here.</p><ol><li><p><strong>Optimizing K vectors pre-RoPE:</strong> We circumvented the RoPE problem entirely by only optimizing V, but since RoPE rotations are reversible, we could undo them, optimize K directly, then re-apply them. This could push the compression threshold beyond 3.2x by jointly optimizing both.</p></li><li><p><strong>Re-testing the hybrid approach</strong> by preserving specific pieces of context verbatim and compressing the rest, at the representation level.</p></li><li><p><strong>Combining embedding compression with KV cache eviction: </strong>Our technique preserves historical context in approximate form. Published eviction methods like H2O and SnapKV manage the growing current context by dropping low-attention entries entirely, and these efforts would be complementary. </p></li><li><p><strong>Testing the sub-agent context architecture ideas above</strong>: The compression research tells us what&#8217;s possible with context efficiency, and it would be interesting to apply that systematically to sub agents from a product perspective. For example, what context sub-agents receive, whether it should be compressed or verbatim, and when to discard context entirely.</p></li></ol><h2>Appendix</h2><h3><strong>Limitations</strong></h3><p>There are several limitations to note.</p><p><strong>Model choice and scale:</strong> All of the experiments were conducted using Qwen 2.5 Coder 7B. Larger models with more attention heads and parameters might behave and perform differently. On one hand they might have higher representational capacity in each virtual token. On the other, there are more complex internal representations for a virtual token to approximate. We were hardware bound, but I&#8217;d love to test the same mechanisms in more capable models.</p><p><strong>Eval / benchmark simplicity:</strong> We used a single transcript with a set of binary evaluation questions for simplicity. In previous experiments, broken pipelines (and things as simple computer sleep) resulted in numerous restarts, leading me to focus on the simplest option possible for this phase of research. The compression threshold and degradation patterns need validation across different codebases, programming languages, and types of conversations.</p><p><strong>Sequential test oddities:</strong> Even 1.5x compression scores ~7/8 on the sequential experiment we ran, suggesting that the sequential pipeline has some quality loss likely beyond what compression ratio alone explains. It&#8217;s just something to be explored further.</p><p><strong>Hybrid approach is difficult to validate on short contexts: </strong>On short turns (e.g., 240 tokens), preserving ~15% of them consumes too much of the &#8220;compression budget&#8221; and results in a compression ratio that&#8217;s too aggressive. </p><h2><strong>An initial look at a hybrid compression approach</strong></h2><p>In the above experiments, failures at 4.8x compression are always specific tokens whose signal gets diluted during pooling. Applying a text-level compression technique I&#8217;ve attempted before, <strong>what if we kept those tokens verbatim and only compressed the rest?</strong></p><p>The biggest challenge here was identifying which tokens to exempt. We tested two signals:</p><p><strong>Perplexity:</strong> Represents how &#8220;surprising&#8221; the token was. Unfortunately, this selects formatting markers and sub-word fragments as well as useful ones. Sometimes, tokens that are surprising carry no useful content (hence we down-weighted low perplexity tokens in our pooling methodology). More broadly, perplexity wasn&#8217;t a useful signal (at least when applied this way) at the macro-content level, even though it was useful for pooling.</p><p><strong>&#8220;Uniqueness&#8221; of V:</strong> Represents how different a token&#8217;s internal representation is from its neighbors. This selects content words like <code>Task, converter, reports, SQLite, authenticate, userId</code>. These are exactly the tokens that lose the most from being averaged with their neighbors during pooling.</p><p>Using this technique, we saved the top 15% of tokens by the uniqueness of V, and their KV entries passed through the pipeline unmodified at their original positions (with correct RoPE). Then, we compress the remaining 85%.</p><h3><strong>Bibliography &amp; Related Work</strong></h3><p>Our main technique, embedding optimization (without pre-training), builds directly on Kuratov et al.&#8217;s work demonstrating that hundreds of tokens can be compressed into optimized embedding vectors (<a href="https://arxiv.org/abs/2502.13063">Cramming 1568 Tokens into a Single Vector</a>, ACL 2025). We apply their technique to multi-turn coding agent conversations and add the V-only optimization target, perplexity-weighted pooling, and sequential turn-by-turn compression.</p><p>The KV cache compression research field is quite active. Most approaches compress the cache after computation through quantization or eviction. Our approach is different in that we optimize input embeddings beforehand. Notable work in this space includes<a href="https://arxiv.org/abs/2503.01586"> EliteKV</a> (RoPE frequency selection),<a href="https://arxiv.org/abs/2604.10235"> CodeComp</a> (structural compression for coding agents).</p><p>KV cache eviction methods like<a href="https://arxiv.org/abs/2306.14048"> H2O</a> and<a href="https://arxiv.org/abs/2404.14469"> SnapKV</a> manage growing context by dropping low-attention entries entirely. I would expect these to be complementary to our approach, since compression preserves important historical context, and eviction manages the current context&#8217;s memory footprint.</p><p><a href="https://arxiv.org/abs/2310.05736">LLMLingua</a> (Jiang et al., 2023) uses perplexity to discard tokens at the text level. We use perplexity to weight V-vector pooling at the embedding level, which is the same signal applied at a different level of the model.</p><p>Anthropic&#8217;s guidance on <a href="https://claude.com/blog/using-claude-code-session-management-and-1m-context">session management and context rot</a> informed our experimental motivation and how widespread this problem is.</p><p><strong>Bibliography</strong></p><ul><li><p>Kuratov et al., &#8220;In-Context Learning with Long-Context Models: An In-Depth Exploration.&#8221; ACL 2025.<a href="https://arxiv.org/abs/2502.13063"> arxiv.org/abs/2502.13063</a></p></li><li><p>Jiang et al., &#8220;LLMLingua: Compressing Prompts for Accelerated Inference.&#8221; 2023.<a href="https://arxiv.org/abs/2310.05736"> arxiv.org/abs/2310.05736</a></p></li><li><p>Zhang et al., &#8220;H2O: Heavy-Hitter Oracle for Efficient KV Cache Eviction.&#8221; 2023.<a href="https://arxiv.org/abs/2306.14048"> arxiv.org/abs/2306.14048</a></p></li><li><p>Li et al., &#8220;SnapKV: LLM Knows What You Are Looking For Before Generation.&#8221; 2024.<a href="https://arxiv.org/abs/2404.14469"> arxiv.org/abs/2404.14469</a></p></li><li><p>EliteKV: RoPE-aware KV cache compression. 2025.<a href="https://arxiv.org/abs/2503.01586"> arxiv.org/abs/2503.01586</a></p></li><li><p>CodeComp: Structural KV cache compression for coding agents. 2026.<a href="https://arxiv.org/abs/2604.10235"> arxiv.org/abs/2604.10235</a></p></li><li><p>HybridKV: Hybrid per-head compression for multimodal models. 2026.<a href="https://arxiv.org/abs/2604.05887"> arxiv.org/abs/2604.05887</a></p></li><li><p>Anthropic, &#8220;Using Claude Code: Session Management and the 1M Token Context Window.&#8221; April 2026. <a href="http://claude.com/blog/using-claude-code-session-management-and-1m-context">claude.com/blog/using-claude-code-session-management-and-1m-context</a></p></li></ul><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This means the model uses some summarization technique to &#8220;compact&#8221; context into something more manageable to keep working. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Codex calls an API that is opaque to the public.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>Compounded further by increased use of agents.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>Anthropic published guidance on context rot <a href="https://claude.com/blog/using-claude-code-session-management-and-1m-context">here</a>.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Essentially using coordinates in a high-dimensional space (e.g., [1, 3.2, 4, 7] = cat) to represent pretty much anything. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p>It&#8217;s not <em>quite </em>discarded in the case of caching, but for purposes of this particular point, the message holds. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p>We&#8217;re focused on coding tasks, since that&#8217;s the use case where a lot of this pain is felt, though it&#8217;s likely broadly applicable outside of coding. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p>Qwen 2.5 coder 7B has 28 model layers.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-9" href="#footnote-anchor-9" class="footnote-number" contenteditable="false" target="_self">9</a><div class="footnote-content"><p>A while ago, it took me a long time to figure out how attention works&#8212;it&#8217;s the mechanism that&#8217;s the core of modern LLM architecture. To put it in a few words, attention allows a model to understand whether &#8220;go&#8221; seen in input is a command, a turn (in the British sense), an ancient board game, who is going, and so on. This <a href="https://www.youtube.com/watch?v=eMlx5fFNoYc">video</a> captures it far better than I could explain in text. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-10" href="#footnote-anchor-10" class="footnote-number" contenteditable="false" target="_self">10</a><div class="footnote-content"><p>It&#8217;s pretty much a fancy way of saying averaging together a bunch of vectors. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-11" href="#footnote-anchor-11" class="footnote-number" contenteditable="false" target="_self">11</a><div class="footnote-content"><p>A <a href="https://www.youtube.com/watch?v=IHZwWFHWa-w">video</a> is worth a thousand of my words explaining gradient descent.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-12" href="#footnote-anchor-12" class="footnote-number" contenteditable="false" target="_self">12</a><div class="footnote-content"><p>I&#8217;m very proud to note that I&#8217;m now getting non-gaming use out of this expensive graphics card that I spent multiple months trying to acquire at MSRP. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-13" href="#footnote-anchor-13" class="footnote-number" contenteditable="false" target="_self">13</a><div class="footnote-content"><p>This is because the important tokens (to us) don&#8217;t necessarily have high perplexity. Yet, we&#8217;re able to reduce the dilutive impact of unimportant ones. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-14" href="#footnote-anchor-14" class="footnote-number" contenteditable="false" target="_self">14</a><div class="footnote-content"><p>If all the virtual tokens were packed into consecutive positions, the model would lose valuable information on relative positions of tokens that it expects (that we&#8217;ve now messed with). The interpolation we&#8217;ve done across the original range gets us to &#8220;good enough.&#8221; </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-15" href="#footnote-anchor-15" class="footnote-number" contenteditable="false" target="_self">15</a><div class="footnote-content"><p>To be honest, I excitedly rushed through this step and didn&#8217;t fully think through my optimization. Nevertheless, it was a neat way to empirically show how wrong I was.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-16" href="#footnote-anchor-16" class="footnote-number" contenteditable="false" target="_self">16</a><div class="footnote-content"><p>At least as it was noted several weeks ago.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Where AI coding costs actually come from (and how I cut them by 75%)]]></title><description><![CDATA[Anthropic published guidance last week on managing &#8220;context rot&#8221; in Claude Code. I've been measuring how much that "rot" costs and testing techniques to fix it]]></description><link>https://rocketvish.substack.com/p/where-ai-coding-costs-actually-come</link><guid isPermaLink="false">https://rocketvish.substack.com/p/where-ai-coding-costs-actually-come</guid><dc:creator><![CDATA[Vishnu Kalugotla]]></dc:creator><pubDate>Mon, 20 Apr 2026 20:18:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gSmF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Anthropic <a href="https://claude.com/blog/using-claude-code-session-management-and-1m-context">published guidance</a> last week on managing &#8220;context rot&#8221; in Claude Code, the degradation of model performance as conversations grow longer. In every conversation turn, the model re-reads the entire conversation history, including old files, potentially irrelevant errors, and abandoned directions. This accumulation makes models slower, less focused, and more expensive. </p><p>I&#8217;ve been measuring how much that &#8220;rot&#8221; costs and testing techniques to fix it. This post adds prompt caching to the compression work from <a href="https://rocketvish.substack.com/p/how-i-made-coding-agents-44-cheaper">Part 2</a>, pushing savings to over 70%T against our uncompressed baseline.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The most interesting findings from our series of experiments were where caching works, where it doesn&#8217;t, and why compression matters more than our benchmark suggests.</p><h2><strong>The Experiment: Seven Strategies</strong></h2><p>For this series, I built a minimal three-tool coding agent using the Anthropic API that includes <code>read_file</code>, <code>write_file</code>, and <code>run_command</code> in a loop. This removes the overhead of Claude Code&#8217;s full infrastructure and lets me measure context management techniques in isolation.</p><p>In this follow up, I added prompt caching to our custom agent and ran seven conditions on the same benchmark from <a href="https://substack.com/home/post/p-194145994">Part 2</a> (an 8-task web application benchmark covering database setup, authentication, and testing<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>). We measured cost, tokens, turns, and code quality (1&#8211;5 scale with an LLM judge). I also tested a new technique, embedding-based selective retrieval, as an alternative to lossy summarization.</p><p>Here are the results:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gSmF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gSmF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 424w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 848w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gSmF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png" width="1456" height="783" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:783,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:124511,&quot;alt&quot;:&quot;&quot;,&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://rocketvish.substack.com/i/194259777?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png&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_!gSmF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 424w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 848w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!gSmF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63c0732f-2a28-4866-914d-66b01997f13a_2379x1280.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"><svg role="img" 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"><g><title></title><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"><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"><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">Cost varies ~9x across strategies with consistent quality. </figcaption></figure></div><p>Two things quickly became apparent: </p><ul><li><p>Quality is flat across every condition (4.0 &#8211; 4.2 &#8212;within what I&#8217;d call margin of error for this exercise).</p></li><li><p>Caching alone, with no changes to how the agent thinks or works, cut token costs by 75%. The savings come from paying significantly less for tokens the model has already seen.</p></li></ul><p><em>A note on this comparison: Our agent is intentionally minimal. The Claude Code bar in the graph provides a reference point for what a full-featured tool costs.</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_!xKAx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xKAx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 424w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 848w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 1272w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xKAx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png" width="2457" height="738" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:738,&quot;width&quot;:2457,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:151254,&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;:&quot;https://rocketvish.substack.com/i/194259777?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32da971c-9c24-4021-a02b-c97ed9164ad4_2460x960.png&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_!xKAx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 424w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 848w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.png 1272w, https://substackcdn.com/image/fetch/$s_!xKAx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F952530c8-e503-4644-96d9-4cd9754e0ea2_2457x738.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"><svg role="img" 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"><g><title></title><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"><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"><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">Full results across seven conditions &#8212; ranges shown from multiple runs. </figcaption></figure></div><h2><strong>Caching is a reliable win</strong></h2><p>Adding caching markers (see footnote) to our API calls<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>  dropped costs from $0.62 to $0.18. This means that the agent sends the same tokens, does the same work, and produces very similar code. The only difference here is that on turn 10, the ~8,000 tokens of conversation history from turns 1&#8211;9 cost 1/10th what they cost without caching.</p><p>Prompt caching, of course, has been available for years, and Claude Code already uses it with a 90%+ hit rate. In our own experiment, the stability was remarkable&#8212;the two caching runs cost $0.17 and $0.18. It&#8217;s clearly the optimization to implement first (which is why most people seem to have done it already). It&#8217;s predictable, consistent, and critically, isn&#8217;t lossy.</p><h2><strong>Compression is still helpful</strong></h2><p>Adding compression on top of caching produced our single best experiment result: $0.14 (a 77% reduction from our uncompressed baseline, and our single best result across all conditions). However, it also produced a $0.35 run. The variance comes from the model making different choices after reading a summary instead of reading the full history. While the summary is normally sufficient context, sometimes, the model re-reads files it wouldn&#8217;t have otherwise if it could see the original conversation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!75HQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!75HQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 424w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 848w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 1272w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!75HQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png" width="1456" height="722" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:722,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:211376,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://rocketvish.substack.com/i/194259777?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png&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_!75HQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 424w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 848w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.png 1272w, https://substackcdn.com/image/fetch/$s_!75HQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51341b9d-a990-4a58-b1a7-7de95d348684_2379x1180.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"><svg role="img" 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"><g><title></title><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"><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"><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">Per-turn token accumulation across four strategies. Compression creates the sawtooth pattern (as opposed to linear accumulation). Retrieval cycles repeatedly.</figcaption></figure></div><p>The initial result was surprising, but it made a bit more sense in the context of this experiment. The test benchmark is quite small, comprising eight tasks and files (mainly to save me the enormous headache of debugging a potential multi-hour testing run, not to mention that Anthropic API calls aren&#8217;t free). The model reads the same files repeatedly, and caching handles the repetition. In this testing environment, compression was solving a problem that barely existed.</p><h2><strong>Why these numbers understate the real gains</strong></h2><p>Real codebases are different from my benchmark, and the problem is more acute than the above result might suggest, especially because Claude Code reads entire files by default.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> In a large codebase, each new file the model explores is a cache miss of perhaps tens of thousands of tokens. Context switching has the potential to dramatically compound this as well.</p><p>Cache time-to-live (TTL)<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> makes it worse. The default 5-minute TTL means any break causes a full cache expiry. Claude Code&#8217;s creator, Boris Cherny, acknowledged this directly: </p><blockquote><p>Prompt cache misses when using 1M token context window are expensive... if you leave your computer for over an hour then continue a stale session, it&#8217;s often a full cache miss.</p></blockquote><p>Developers are already building workarounds: MCP servers for code indexing, hooks that pre-process data before Claude sees it, and skills that provide architecture overviews so the model doesn&#8217;t have to search. I&#8217;ve yet to see a standardized solution that&#8217;s broadly applicable, though.</p><p>The 75% token cost savings would likely be even more impactful in a large codebase, where the model accumulates 100K+ tokens of history with lower cache hit rates. Our benchmark is the best case for caching and the worst case for compression. In a real codebase, the balance flips &#8212; cache hit rates drop as the model reads novel files, and the accumulated context that compression eliminates becomes the most significant cost. <strong>The recommendation, then, from this study is to use both: cache everything by default, and compress proactively before the context window fills.</strong></p><p>This also explains why Anthropic <a href="https://github.com/anthropics/claude-code/issues/43989">reduced</a> the auto-compact threshold from ~1M to ~400K tokens in Claude Code v2.1.92. Even with aggressive caching, maintaining the full conversation history at scale was apparently unsustainable. The aim of this project is effective proactive compression, not just to save on token costs, but to keep agents focused and performant in long sessions.</p><h2><strong>Embedding retrieval: completeness beat fidelity</strong></h2><p>Next, I tested an alternative to lossy compression: instead of summarizing all history, I used embedding similarity (to score each conversation turn by relevance) to select the 5 most relevant conversation turns and keep them verbatim. My hypothesis was that verbatim turns preserve more useful detail than a full summary.</p><p>While I&#8217;m sure there&#8217;s room for more optimization (I just picked 5 to start), it was our worst result of the test runs. It took 58 turns, costing $1.66, which was more expensive than Claude Code.</p><p>It was reassuring to see that embeddings actually do differentiate at the per-turn level. Scores ranged from 0.55 to 0.87, noticeably wider than the inter-task embedding scoring that failed in Part 2. This means that the model can tell that &#8220;read package.json&#8221; is less relevant than &#8220;wrote auth routes.&#8221;</p><p>However, keeping only 5 turns for the small tasks in this test seemed to drop too much context. This is likely because it&#8217;s helpful for the model to have a complete map of our codebase. For example, a lossy summary that says &#8220;created db.js with three tables, wrote auth routes with JWT, added validation middleware&#8221; gives the model enough to continue, while five verbatim turns might not include the file the model needs to reference when writing tests. </p><p>In the context of this experiment, completeness beats fidelity. I&#8217;ve seen other work using file structure solutions as maps to help mitigate further&#8212;we may investigate those strategies in future work.</p><h2><strong>What this means for the tools we use</strong></h2><p>Now let&#8217;s look at a broader question that goes beyond this specific research.</p><p>An interesting data point in our comparison is that Claude Code costs $0.72 for our benchmark, while our lean agent costs $0.18 with caching. The gap illustrates where token costs live: roughly 70% of the cost in our measurements comes from infrastructure that gets re-sent every turn, not from the actual code generation.</p><p>I&#8217;m not arguing that everyone should replace Claude Code with minimal agents. Claude Code&#8217;s system prompt, tools, and safety features exist for good reasons and make it flexible and capable. However, as sessions get longer and codebases get larger, that overhead compounds. The question here is how can we intelligently compress the information to make the entire process more efficient. A 4,000-token system prompt that gets re-sent every turn could be a 400-token summary after the first turn&#8212;the model likely doesn&#8217;t need to re-read tool specs it saw ten turns ago.</p><p>The pattern we&#8217;ve established keeps repeating: there is significant headroom for improvement in both context management and AI tool use broadly.</p><h2><strong>Next: beyond the text layer</strong></h2><p>Thus far, I&#8217;ve been investigating techniques that manipulate text, like summarization, caching (little different, but close enough), and embedding retrieval. Summarization works but risks losing some detail; caching is quite helpful, but can&#8217;t help with novel content; retrieval can&#8217;t replace completeness in our study.</p><p>The next step will be looking into the layer below text that these techniques don&#8217;t reach: the model&#8217;s internal representations. When an LLM processes a conversation, it builds vectors to serve as an internal representation of patterns computed from reading that text, which are what it uses in computations to calculate the output. With open-weight models, we can access these vectors directly<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a>.</p><p>Instead of summarizing a turn into text and re-processing the summary, I&#8217;ll try a set of techniques to manipulate these representations more directly. For example, it&#8217;s possible to evict low-value KV cache entries and keep the rest intact.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a> Applying these techniques to multi-turn coding agent sessions, where the &#8220;importance&#8221; signal comes from which past turns the model actually attends to, is less explored. We&#8217;ll dive deeper into that next.</p><div><hr></div><p><em>The code for the evaluation framework, benchmark, agent, and other work described here is open source at <a href="https://github.com/rocketvish/bearing">github.com/rocketvish/bearing</a>.</em></p><h2>Sources</h2><ul><li><p><strong>Session management and context rot</strong> Anthropic blog, April 15, 2026. Official guidance on compaction and context rot in Claude Code. <a href="https://claude.com/blog/using-claude-code-session-management-and-1m-context">https://claude.com/blog/using-claude-code-session-management-and-1m-context</a></p></li><li><p><strong>Context management for coding agents</strong> Lindenbauer et al., TUM / JetBrains. Presented at NeurIPS 2025 (DL4Code workshop). <a href="https://blog.jetbrains.com/research/2025/12/efficient-context-management/">https://blog.jetbrains.com/research/2025/12/efficient-context-management/</a></p></li><li><p><strong>Claude Code autocompact reduction</strong> GitHub Issue #43989. Threshold reduced from ~1M to ~400K tokens in v2.1.92. <a href="https://github.com/anthropics/claude-code/issues/43989">https://github.com/anthropics/claude-code/issues/43989</a></p></li><li><p><strong>Prompt caching mechanics</strong> Anthropic API docs. Cache reads at 0.1x price, writes at 1.25x, 5-minute TTL. <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">https://platform.claude.com/docs/en/build-with-claude/prompt-caching</a></p></li><li><p><strong>Cache read token dominance</strong> GitHub Issue #24147. 99.93% of tokens are cache reads over 30 days of real usage. <a href="https://github.com/anthropics/claude-code/issues/24147">https://github.com/anthropics/claude-code/issues/24147</a></p></li><li><p><strong>Cache TTL regression</strong> GitHub Issue #46829. Documents silent TTL reversion from 1h to 5m, with cost impact analysis. <a href="https://github.com/anthropics/claude-code/issues/46829">https://github.com/anthropics/claude-code/issues/46829</a></p></li><li><p><strong>Claude Code reads entire files by default</strong> BSWEN blog. MCP server for symbol-level indexing reduced tokens from 84K to 2.7K per file read. <a href="https://docs.bswen.com/blog/2026-03-20-reduce-token-usage-claude-code/">https://docs.bswen.com/blog/2026-03-20-reduce-token-usage-claude-code/</a></p></li><li><p><strong>Boris Cherny on cache miss costs</strong> The Register, April 2026. &#8220;Prompt cache misses when using 1M token context window are expensive.&#8221; <a href="https://www.theregister.com/2026/04/13/claude_code_cache_confusion/">https://www.theregister.com/2026/04/13/claude_code_cache_confusion/</a></p><p></p></li></ul><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This is Part 3 of a series on context management for AI coding agents. <a href="https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between">Part 1</a> introduced a lightweight coding agent orchestrator and the case for separating planning and execution context. <a href="https://rocketvish.substack.com/p/how-i-made-coding-agents-44-cheaper">Part 2</a> measured mid-conversation compression (44% savings). </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>This is a controlled 8-task web application benchmark a backend API covering database setup, authentication, data operations, validation, and tests.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>A cache control breakpoint is a marker you place in your API request telling Anthropic &#8220;cache everything up to this point.&#8221; On the next request, if the content before that marker is identical, Anthropic serves it from cache at 1/10th the price instead of reprocessing it.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://docs.bswen.com/blog/2026-03-20-reduce-token-usage-claude-code/">One developer</a> found that reading a single 22,000-line module to understand one function consumed 84,000 tokens. They built an MCP server for symbol-level indexing that reduced it to 2,700 tokens &#8212; a 97% reduction.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Cache TTL (time-to-live) is how long Anthropic keeps your cached tokens available before discarding them. The default is 5 minutes) </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p>Frontier models served don&#8217;t expose their internal representations. Open-weight models like Qwen and Llama do, which is why the next phase of this research uses local models as a test bed. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p>Research frameworks like H2O (NeurIPS 2023) and SnapKV have already demonstrated this for general language tasks.</p><h1></h1></div></div>]]></content:encoded></item><item><title><![CDATA[How I made coding agents 44% cheaper]]></title><description><![CDATA[There&#8217;s the headline &#8211; smart context management cut my AI coding costs by 44%, with room to go further.]]></description><link>https://rocketvish.substack.com/p/how-i-made-coding-agents-44-cheaper</link><guid isPermaLink="false">https://rocketvish.substack.com/p/how-i-made-coding-agents-44-cheaper</guid><dc:creator><![CDATA[Vishnu Kalugotla]]></dc:creator><pubDate>Tue, 14 Apr 2026 03:51:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!sYDG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Smart context management cut my AI coding costs by 44%, with room to go further.</p><p>What started off as a lightweight app to make my work flow more efficient has turned into a veritable rabbithole on effective context management in LLMs.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Model context, especially within the environment of a model harness like Claude Code, tends to be inefficient and can result in higher token burn with potentially worse quality outputs.</p><p>This is because, as conversations get longer, all previous queries and outputs get swept in as context until hitting the context window limit. At this point, conversations are compacted, losing valuable information.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>I built a rough evaluation framework and ran five experiments to find out where those tokens go, which ones matter, and which ones can be cut. There were, of course, a few dead ends, but the results indicate that there&#8217;s significant untapped head room.</p><h4>Findings</h4><ul><li><p>Compressing mid-conversation context to eliminate unnecessary inputs saved 44% on token costs.</p></li><li><p>Claude Code stores full session transcripts, so you can inspect what happened after the fact. However, during execution, you can&#8217;t intervene between turns, making it very difficult to compress the history, drop stale results, etc.</p></li></ul><h2><strong>Experiment Context</strong></h2><p>In my last post, &#8220;<strong><a href="https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between">Why I stopped copy-pasting between Claude windows</a>,</strong>&#8221; I introduced <a href="https://github.com/rocketvish/bearing">Bearing</a> &#8212; an open-source orchestrator that separates AI planning from execution and optimizes for human input in the planning loop, while keeping tasks model agnostic.</p><p><strong>Here&#8217;s how it works</strong>: you have a planning conversation with your favorite model about what to build. Bearing then runs each task in a fresh <code>claude -p </code>session.</p><p>Soon after my first post, Anthropic released the <a href="https://claude.com/blog/the-advisor-strategy">advisor strategy</a>&#8212; a server-side feature that pairs Sonnet as an executor with Opus as an on-demand advisor. Sonnet drives the session and escalates to Opus when it hits a decision it can&#8217;t solve alone. It&#8217;s a similar intuition to Bearing&#8217;s planning-with-Opus, execution-with-Sonnet split, but automated and without a human in the planning loop.</p><p>While the original <em>why</em> behind bearing revolved around AI workflow efficiency and model flexibility, I noticed two things in my daily use:</p><ul><li><p>I became increasingly <strong>tempted to manually control context to increase the signal-to-noise ratio</strong> of inputs.</p></li><li><p>I was painfully aware of both <strong>speed and quality dropping as conversations</strong> (or even just tasks) <strong>ran on in a single conversation</strong>.</p></li></ul><p>Based on my experience manipulating context, I saw significant headroom to make models (and by extension, harnesses) more efficient. This is where we dive into something a bit more research-oriented: I built a rough evaluation framework and ran several tests that I&#8217;ve laid out below. I even had to iterate on the tests to make sure I didn&#8217;t constantly hit API rate limits or have my computer falling asleep force a re-run of a 3-hour job (I learned that one the hard way).</p><p>The evaluation consists of a reproducible benchmark, automated quality scoring with an LLM as a judge, and a framework that runs the same tasks under different conditions and compares cost, token consumption, and output quality.</p><h2><strong>Building the Measurement Tool</strong></h2><p>I wanted to run my experiments using Claude Code directly, but as far as I understand, I can&#8217;t because <code>claude -p </code>cannot be interacted with between turns.</p><p>To get around this, I built a (very) minimal code agent using the Anthropic API directly. It includes three tools, read file, write file, run command, that execute in a straightforward loop: send message, receive tool calls, execute them, and then return results.</p><p>The first measurement was instructive:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!euwB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!euwB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 424w, https://substackcdn.com/image/fetch/$s_!euwB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 848w, https://substackcdn.com/image/fetch/$s_!euwB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 1272w, https://substackcdn.com/image/fetch/$s_!euwB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!euwB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png" width="1300" height="391" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:391,&quot;width&quot;:1300,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26100,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://rocketvish.substack.com/i/194145994?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png&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_!euwB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 424w, https://substackcdn.com/image/fetch/$s_!euwB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 848w, https://substackcdn.com/image/fetch/$s_!euwB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.png 1272w, https://substackcdn.com/image/fetch/$s_!euwB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04786320-225f-4cc8-acc5-465ddff81ddf_1300x391.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"><svg role="img" 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"><g><title></title><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"><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"><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>With the same tasks, the main difference is Claude Code&#8217;s system prompt, project scaffolding, and tool infrastructure, all of which get re-sent every turn.</p><p>per-turn accumulation showed linear growth as follows:</p><ul><li><p>Turn 1:   2,444 input tokens</p></li><li><p>Turn 5:   4,952</p></li><li><p>Turn 10:  8,303</p></li><li><p>Turn 15: 10,507</p></li><li><p>Turn 20: 14,082</p></li></ul><p>Every turn re-sends the full conversation history (as we expected). Turn 1 sends the initial prompt, while turn 20 re-sends the prompt plus every file it read, every command output it processed from previous turns, and so on.</p><p>The linear accumulation of conversation history, most of which decays in relevance within a few turns of being generated, ends up becoming a tax on token use.</p><h2><strong>What Worked</strong></h2><h3><strong>Mid-Conversation Compression</strong></h3><p>This intervention is straightforward. When the conversation history exceeds a threshold (12,000 tokens in these experiments), the agent pauses, generates a structured summary of everything accomplished so far, including files read, files written, commands run, errors encountered, and replaces the full history with that summary.</p><p>The token consumption pattern looks as follows:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sYDG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sYDG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 424w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 848w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 1272w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sYDG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png" width="1456" height="790" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:790,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:108633,&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;:&quot;https://rocketvish.substack.com/i/194145994?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png&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_!sYDG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 424w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 848w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.png 1272w, https://substackcdn.com/image/fetch/$s_!sYDG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff62deb9c-33c4-4ac4-bcac-13794d502916_1968x1068.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"><svg role="img" 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"><g><title></title><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"><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"><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 compression at turn 14 reduced the conversation from 12,733 to 2,255 tokens. The model continued from the summary and completed all remaining tasks without losing track of what it had already built.</p><p>Results across all eight 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_!8-B3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8-B3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 424w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 848w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 1272w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8-B3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png" width="1456" height="372" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/02327e21-ae13-4643-93c9-679427de87dd_1532x391.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;:40901,&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://rocketvish.substack.com/i/194145994?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.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_!8-B3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 424w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 848w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.png 1272w, https://substackcdn.com/image/fetch/$s_!8-B3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F02327e21-ae13-4643-93c9-679427de87dd_1532x391.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"><svg role="img" 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"><g><title></title><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"><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"><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">*Claude Code quality from the session isolation experiment; agent quality from the compression experiment. Both use Sonnet on the same benchmark.</figcaption></figure></div><h2><strong>Implications</strong></h2><p>Mid-conversation compression reduced input tokens by 25.6% versus the uncompressed agent, with no quality degradation (4.2 vs. 4.3 &#8212; essentially within noise on a 5-point scale). Against Claude Code, the compressed agent used 78.5% fewer input tokens at 44.4% lower cost.</p><p>That cost comparison is actually conservative. Claude Code benefits from prompt caching, and our agent currently does not. Adding caching to the agent should reduce its cost further. Preliminary estimates suggest $0.10&#8211;0.15, which would represent an 80%+ reduction versus Claude Code for the same work at comparable quality.</p><p>It&#8217;s important to keep in mind however, that Claude Code mitigates re-reading costs through prompt caching. Cached tokens cost 1/10th of regular input, so a well-optimized session hits a 90%+ cache rate. Our compression approach eliminates them entirely. The optimal strategy likely combines both: cache between compressions, accept the cache miss after each compression event, and let the cache rebuild. We&#8217;ll explore this more in future directions.</p><p>These findings align with a growing body of research on agent context management. <a href="https://blog.jetbrains.com/research/2025/12/efficient-context-management/">Lindenbauer et al. (NeurIPS 2025)</a> found that observation masking and LLM summarization both reduce costs in coding agents, but noted that the field still treats context management as an engineering detail rather than a core research problem.  Our 25% reduction through simple threshold-based summarization suggests there&#8217;s significant room for more sophisticated techniques.</p><h2><strong>Limitations</strong></h2><p>These results are preliminary. The experiments use one benchmark project, one model (Sonnet), and one run per condition. The findings need replication across project types, models, and multiple runs to establish reliability. The quality evaluation uses LLM-as-judge (Sonnet scoring Sonnet&#8217;s output).</p><p>The compression threshold (12,000 tokens) and summarization strategy (full-history summary) were chosen pragmatically based on turn outputs, and they&#8217;re not optimized. Different thresholds and compression techniques would produce different tradeoff curves.</p><h2><strong>What&#8217;s Next</strong></h2><p>This post establishes that mid-conversation history compression works &#8212; it reduces tokens significantly without degrading output quality. The next order of business is investigating how far the technique extends and what the optimal compression strategy looks like.</p><p>I&#8217;m exploring a few approaches that go beyond lossy summarization. There are techniques that preserve relevant parts of the original conversation verbatim while discarding the parts the model no longer needs. There are also interesting interactions between compression and prompt caching, since compression resets the cache and the two techniques need to be balanced. More on those in Part 3.</p><p>The code for Bearing, the evaluation framework, the benchmark, the custom agent, and the compression module are open source and available at <a href="https://github.com/rocketvish/bearing">github.com/rocketvish/bearing</a>.</p><div><hr></div><p><em>This is the second post in a series on context management for AI coding agents. The first, <a href="https://rocketvish.substack.com">&#8220;</a><a href="https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between">Why I stopped copy-pasting between Claude windows</a><a href="https://rocketvish.substack.com">&#8221;</a>, introduced <a href="https://github.com/rocketvish/bearing">Bearing</a> and the case for separating planning from execution.</em></p><div><hr></div><h2><strong>Appendix</strong></h2><h3><strong>What Didn&#8217;t Work</strong></h3><h4><strong>Experiment 1: Compressing Inter-Task Context</strong></h4><p>When Bearing completes a task, it passes a short summary to the next one &#8212; something like &#8220;[task-001: Database schema | files: src/db.js] Created SQLite tables for users, tasks, and reports.&#8221;</p><p>I built four strategies for compressing this handoff context: raw prose, structured JSON, embedding-based relevance scoring (using nomic-embed-text locally via Ollama to drop portions that score as irrelevant to the next task), and LLM-guided compression (using Gemma 4 26B locally to rewrite mid-relevance chunks with only the details relevant to the downstream task).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7YRr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7YRr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 424w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 848w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 1272w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7YRr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png" width="1300" height="460" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:460,&quot;width&quot;:1300,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53958,&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;:&quot;https://rocketvish.substack.com/i/194145994?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png&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_!7YRr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 424w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 848w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.png 1272w, https://substackcdn.com/image/fetch/$s_!7YRr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53b0ce91-ec79-483e-b790-43d5bd0abc08_1300x460.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"><svg role="img" 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"><g><title></title><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"><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"><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 wasn&#8217;t a meaningful difference in cost or quality. The embedding scorer never dropped a single portion across three full evaluation runs.</p><p>There were two issues.</p><ol><li><p>In a cohesive project, where tasks build on each other within the same codebase, everything scores as semantically related to everything else, which makes dropping portions difficult. Moreover, in a small project like our test benchmark, filtering out irrelevant files will result in minimal savings.</p></li><li><p>The inter-task handoff is approximately 200 tokens, while each task consumes 100,000&#8211;300,000 tokens during execution.</p></li></ol><p>This experiment turned out to test something different than I intended &#8212; I didn&#8217;t realize you can&#8217;t modify what happens inside <code>claude -p</code> between turns</p><h4><strong>Experiment 2: Do fresh windows save tokens?</strong></h4><p>I tested eight separate <code>claude -p</code> sessions versus one single <code>claude -p</code> call with all eight tasks consolidated into a mega-prompt. The benchmark was an 8-task Express API project covering database setup, authentication, CRUD routes, validation, middleware, reports, and integration tests.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dqk9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dqk9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 424w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 848w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 1272w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dqk9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png" width="1456" height="305" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:305,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36267,&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://rocketvish.substack.com/i/194145994?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.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_!dqk9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 424w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 848w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 1272w, https://substackcdn.com/image/fetch/$s_!dqk9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b3d8bdf-c892-4474-ae66-233ccef2f33a_1532x321.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The mechanism seems to be cold-start overhead. Each fresh Bearing session reads CLAUDE.md, scans the directory, reads package.json, reads existing source files before actually writing any code. Meanwhile, the single session only has to do that once vs. eight times.</p><p>Prompt caching compounds the disadvantage. Claude Code caches the conversation prefix at roughly 1/10th cost. In a single session, most tokens on turn 10 are cache hits from turns 1&#8211;9, while fresh sessions have nothing to cache.</p><h3><strong>Sources</strong></h3><ul><li><p><strong>Context degradation in long contexts</strong> Liu et al., &#8220;Lost in the Middle: How Language Models Use Long Contexts.&#8221; TACL 2024.<a href="https://arxiv.org/abs/2307.03172"> https://arxiv.org/abs/2307.03172</a></p></li><li><p><strong>Context management for coding agents</strong> Lindenbauer et al., TUM / JetBrains. Presented at NeurIPS 2025 (DL4Code workshop). Tests observation masking and LLM summarization on SE agents.<a href="https://blog.jetbrains.com/research/2025/12/efficient-context-management/"> https://blog.jetbrains.com/research/2025/12/efficient-context-management/</a></p></li><li><p><strong>Agent context compression framework</strong> Kang et al., &#8220;ACON: Optimizing Context Compression for Long-Horizon LLM Agents.&#8221; arXiv 2025. 26&#8211;54% token reduction on multi-step benchmarks.<a href="https://arxiv.org/abs/2510.00615"> https://arxiv.org/abs/2510.00615</a></p></li><li><p><strong>Claude Code autocompact reduction</strong> GitHub Issue #43989. Autocompact threshold reduced from ~1M to ~400K tokens in v2.1.92. <a href="https://github.com/anthropics/claude-code/issues/43989">https://github.com/anthropics/claude-code/issues/43989</a></p></li><li><p><strong>Prompt caching mechanics</strong> Anthropic API docs. Cache reads at 0.1x price, writes at 1.25x, 5-minute TTL. <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">https://platform.claude.com/docs/en/build-with-claude/prompt-caching</a></p></li><li><p><strong>Cache read tokens consume 99.93% of usage quota </strong><a href="https://github.com/anthropics/claude-code/issues/24147">https://github.com/anthropics/claude-code/issues/24147</a></p></li><li><p><strong>Advisor tool</strong> Anthropic blog, April 2026. Sonnet executor + Opus advisor. 2.7pp SWE-bench improvement, 11.9% cost reduction. <a href="https://claude.com/blog/the-advisor-strategy">https://claude.com/blog/the-advisor-strategy</a></p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This is the second post in a series on context management for AI coding agents. The first,<a href="https://rocketvish.substack.com"> &#8220;</a><strong><a href="https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between">Why I stopped copy-pasting between Claude windows</a></strong><a href="https://rocketvish.substack.com">&#8221;</a>, introduced <a href="https://github.com/rocketvish/bearing">Bearing</a> and the case for separating planning from execution.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>It&#8217;s interesting to note that Claude Code likely reduced the autocompact window to ~400K tokens on Opus 4.6, down from the full ~1M available in v2.1.91 and earlier (Source: <a href="https://github.com/anthropics/claude-code/issues/43989">Github</a>). This is an undocumented change that might be an effort to address context inefficiency in large context windows.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Why I stopped copy-pasting between Claude windows (and what I did instead)]]></title><description><![CDATA[AI is better at writing prompts for AI than humans are (for the purpose of writing code).]]></description><link>https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between</link><guid isPermaLink="false">https://rocketvish.substack.com/p/why-i-stopped-copy-pasting-between</guid><dc:creator><![CDATA[Vishnu Kalugotla]]></dc:creator><pubDate>Wed, 08 Apr 2026 04:11:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!H0a1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AI is better at writing prompts for AI than humans are (for the purpose of writing code).</p><p>Or at least that&#8217;s what it has felt like as of late. I&#8217;ve recently fallen into a pattern of copying and pasting generated prompts between multiple Claude Code and Claude windows (embarrassing &#8211; I know), and getting much better results than I would have otherwise.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>What started as an attempt to optimize my workflow led me down a rabbit hole to improve model + harness performance and trying to address longstanding issues with context window length. Namely that compaction is lossy and token-inefficient.</p><p>Here&#8217;s the long and short of what I learned:</p><p><strong>The Research</strong></p><ul><li><p>Models &#8220;attend&#8221; (pay attention) worse to mid-context information (it&#8217;s improved but not solved)</p></li><li><p>AI-generated prompts (might) outperform human ones on complex tasks</p></li></ul><p>The latter should be taken with a grain of salt, but at the very least might help reduce the amount of time it takes to translate <em><strong>human intent</strong></em> into an output or outcome.</p><p><strong>The Approach</strong></p><ul><li><p>Separate planning from execution context windows to keep both clean</p></li><li><p>Assist AI compaction to preserve relevant context, especially for long-running tasks</p></li><li><p>Keep the human in the planning loop to better achieve what you intend</p></li></ul><p>These are all implemented in <a href="https://github.com/rocketvish/bearing">Bearing</a>, an open-source tool that separates planning from execution across AI coding agents.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H0a1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H0a1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 424w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 848w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H0a1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg" width="1456" height="1062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg&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;:133809,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://rocketvish.substack.com/i/193216598?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!H0a1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 424w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 848w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!H0a1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F809f04d9-28ab-4652-b69a-6d30da4a6cd8_1713x1249.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"><svg role="img" 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"><g><title></title><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"><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"><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>Early Results</strong></p><p>In a long session, compaction can discard the vast majority of your conversation history. In one of my sessions, 99.5% was dropped, keeping decisions but losing the reasoning behind them. Bearing avoids this on the execution side entirely: each task starts with a fresh context window</p><h2><strong>The Attention Problem</strong></h2><p>In 2023, Stanford and Meta researchers (<a href="https://arxiv.org/abs/2307.03172">Liu et al., 2024</a>) documented the &#8220;Lost in the Middle&#8221; phenomenon: model performance follows a U-shaped curve, highest when relevant information is at the beginning or end of the context, degrading when it&#8217;s buried in the middle. GPT-3.5&#8217;s (yes that&#8217;s an old one, as are some of the ones below) accuracy dropped over 20% when key information sat mid-context.</p><p>Newer models, of course, have improved dramatically on this. As early as 2023, Anthropic showed that a simple prompt adjustment raised Claude 2.1&#8217;s retrieval accuracy from 27% to 98% across its 200K context window (<a href="https://www.anthropic.com/news/claude-2-1-prompting">Anthropic</a>).</p><p>Despite these improvements, 2026 best-practice guides still recommend placing critical information at the beginning and end of context windows. This practical problem persists in a different form: even if the model can technically attend to everything, a Claude Code session that&#8217;s accumulated five tasks worth of test output, and error traces has a much noisier context than a fresh session with just the task prompt. The signal-to-noise ratio degrades regardless of whether the model&#8217;s &#8220;positional attention&#8221; is uniform.</p><p>In other words: your intent from attempt 1 isn&#8217;t lost because the model can&#8217;t read the middle of its context. It&#8217;s lost because it&#8217;s competing for attention with dozens of other signals that have accumulated since then.</p><h2><strong>Why AI should (maybe) write prompts for AI</strong></h2><p>When you tell Claude Code &#8220;add dark mode,&#8221; your brain fills in 20 things you don&#8217;t say: where the toggle goes and what it looks like, how to persist the preference, how to contrast with the existing color scheme, and more. It&#8217;s difficult to figure out which details to fill in, and which an agent might fill in better than you might plan&#8212;worse, it&#8217;s tough to know what might anchor an agent on a suboptimal path.</p><p>This can be especially tough because an executing coding agent starts without much shared context (except what you painstakingly provide in markdown files, of course).</p><p>An AI planner writing a prompt for the executor doesn&#8217;t assume shared context &#8212; it knows the target session is clean. It specifies which files to read, what approach to take, what to verify when done.</p><p>There may be some reasons attributable to training that show why this works. Google DeepMind (<a href="https://arxiv.org/abs/2309.03409">Yang et al., 2023</a>) and Microsoft Research have both shown AI-optimized prompts outperforming human-written ones on benchmarks (OPRO, PromptAgent), though how directly this applies to coding agent prompts is still an open question. Models were optimized during RLHF against structured, complete instructions. An AI writing a prompt for another AI naturally produces text in that format.</p><p>There&#8217;s an added layer to all of this: as the world stands today, I believe that human + AI interaction can serve as a more effective planner in translating intent into outcomes than either alone. Many people writing about vibe coding have played with markdown files and prompt generation to make a coding agent one-shot most (easy) tasks quite effectively. That said, as tasks grow in complexity, this approach has its limits. Together, a human can bring taste, judgment, and domain knowledge, while the AI brings completeness, structure, and format the executor is optimized for.</p><h2><strong>Doesn&#8217;t Claude Code Already Do This?</strong></h2><p>Kind of. Claude Code already separates planning from execution. Plan mode creates a plan before writing code, subagents create workers, and agent teams have a lead that coordinates agents.</p><p>As far as I&#8217;ve seen though, the planner is the AI talking to itself. Plan mode plans, then executes with the same context window and without human input during the planning phase. Agent Teams have a lead, but that lead makes architectural decisions autonomously.</p><p>Claude Code&#8217;s plan mode likely won&#8217;t say &#8220;wait &#8211; we&#8217;re not thinking about [insert vital topic here]&#8221; It won&#8217;t say &#8220;actually, build the database layer first because everything depends on it&#8221; unless you thought to ask. It can&#8217;t bring your product instinct into the architectural conversation because it doesn&#8217;t have access to it.</p><p>The issue also isn&#8217;t planning versus execution. Given the way typical workflows are currently structured, it&#8217;s whether the human is in the planning loop or downstream of it.</p><h2><strong>What does Bearing do then?</strong></h2><p>I built a tool called Bearing to test these ideas. Here&#8217;s how it works:</p><ol><li><p>You open an interactive Claude Code session; that&#8217;s your planner (running Opus or another performant model) that&#8217;s focused on strategy. You have a real conversation to do anything from debating architecture to pushing back on complexity, and making decisions.</p></li><li><p>When you converge on a direction, the planner writes a structured task file. Each task specifies the CLI tool, model, budget, turn limit, which files are relevant, and a detailed prompt drawn from your conversation.</p></li><li><p>Then you run <code>bearing run .</code> and each task executes in a new, isolated <code>claude -p </code>session.</p></li><li><p>Results write back to a status file &#8211; the planner reads the results. You discuss what to adjust, and the cycle continues.</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_!mbXq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mbXq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mbXq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png" width="1024" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:608,&quot;width&quot;:1024,&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_!mbXq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 424w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 848w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.png 1272w, https://substackcdn.com/image/fetch/$s_!mbXq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb52db9d8-0c12-415e-a9c7-8c8dacaacdb2_1024x608.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"><svg role="img" 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"><g><title></title><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"><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"><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 wrong kind of bearing &#8212; very helpful though.</figcaption></figure></div><p>A couple benefits of this approach:</p><p><strong>Model-agnostic execution:</strong> Each task specifies which CLI runs it &#8212; Claude Code, Codex, or any custom agent. You can also mix them in the same task queue.</p><p><strong>Context focusing: </strong>Instead of the executor reading your entire codebase and hoping attention lands in the right place, each task specifies which files matter and which to skip. The executor sees <code>FOCUS: Read these files first</code> and <code>SKIP: Do not read or modify these before the task prompt</code>. This reduces token consumption and concentrates the model&#8217;s attention on relevant code. Quick note here &#8211; I&#8217;m working on a better approach that I&#8217;ll write a bit about next time.</p><p><strong>Auto-context propagation.</strong> When task-001 completes, its summary and file list automatically inject into every dependent task. That means task-002 knows what task-001 created without the human manually copying context between sessions.</p><p>This also means no more copying and pasting between chats, which is how this whole thing started, and AI handles the translation from intent to implementation.</p><h2><strong>The Deeper Problem: Context Compression</strong></h2><p>There&#8217;s a larger issue beneath all of this that hasn&#8217;t been solved (or even addressed, really) yet.</p><p>When a context window compacts, whether through Claude&#8217;s built-in summarization or simply through the model attending less to older content, information loss is unstructured &#8211; the model isn&#8217;t great at knowing what you consider important. Some big architecture decision from prompt 3 could get the same treatment as a debug trace from prompt 17 (most of you have probably seen a typical Claude memory reference to something entirely irrelevant &#8211; this is similar).</p><p>The planner layer offers a structural answer to this. Because the planner curates what context flows into each task &#8212; which files matter, what previous tasks accomplished, what the human decided and why &#8212; it&#8217;s performing a form of (slightly) intelligent compression that the model doesn&#8217;t do on its own.</p><p>It&#8217;s important to note that this attempt is quite early. The current implementation uses text summaries and file lists. A more ambitious version might generate structured relevance maps, prioritize context by impact, and compress differently for different task types, and that&#8217;s only one potential approach. It&#8217;s also possible or even likely that Anthropic and OpenAI will build some of this into their tools natively.</p><p>Regardless, I might contend though that a human-in-the-loop planning layer can make better context decisions than a model alone, at least in the current era of LLM-based agents.</p><h2><strong>Try It</strong></h2><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:&quot;37ee7cc4-dd62-4342-b37c-238cf57a2161&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">git clone https://github.com/rocketvish/bearing.git
cd bearing
uv tool install -e .
cd &lt;your-project-directory&gt;
bearing start .</code></pre></div><p>This is open source and has no dependencies. The repo includes examples and a planner prompt that teaches your AI session how to write task files.</p><p>The code is at <a href="https://github.com/rocketvish/bearing">github.com/rocketvish/bearing</a>. I&#8217;d love to hear what works and what doesn&#8217;t.</p><h2><strong>Final Thoughts</strong></h2><p>The aforementioned rabbit hole turns out to be deeper than I imagined. Context compression has always been lossy, and as far as I know, no one is solving it structurally yet. Bearing is a rudimentary attempt. If you&#8217;ve hit the same wall &#8212; your agent forgets what matters three tasks in &#8212; I&#8217;d love to hear how you&#8217;re solving it.</p><div><hr></div><h2><strong>Appendix</strong></h2><h3><strong>How this differs from the Landscape</strong></h3><p>The current ecosystem is focused on parallelism, running more agents simultaneously:</p><p><strong>Garry Tan&#8217;s gstack</strong> (<a href="https://github.com/garrytan/gstack">github</a>) assigns different personas to a single Claude Code session via 23 slash commands, but it&#8217;s still one context window accumulating everything.</p><p><strong>Steve Yegge&#8217;s Gas Town</strong> (<a href="https://github.com/steveyegge/gastown">github</a>) runs 20-30 parallel agents coordinated by a Mayor agent, with Polecats for execution, a Refinery for merge queues, and persistent state in Git via Beads. Architecturally ambitious &#8212; it&#8217;s designed for massive parallelization across large codebases.</p><p><strong>Anthropic&#8217;s Agent Teams</strong> (<a href="https://code.claude.com/docs/en/agent-teams">docs</a>) is Claude Code&#8217;s built-in multi-agent feature. One session acts as team lead, coordinating teammates that each get their own context window.</p><p><strong>Conductor</strong> (<a href="https://www.conductor.build/">Melty Labs</a>) is a YC-backed Mac app that gives you a visual UI for parallel Claude Code agents. If you want to run 5 agents on different features simultaneously, Conductor is excellent.</p><p><strong>What all of these share:</strong> they solve the problem of running more agents in parallel, coordinating their work, and managing conflicts, generally scaling throughput.</p><p><strong>What none of them address:</strong> the planning conversation. The back-and-forth between human and AI where you debate architecture, challenge complexity, make strategic decisions, and translate vague intent into precise tasks. In every tool above, the planning either happens in the same polluted context as execution (gstack), or is done autonomously by an AI lead without human input (Agent Teams, Gas Town), or isn&#8217;t part of the tool&#8217;s scope at all (Conductor).</p><p>Bearing doesn&#8217;t compete with these tools. You could use Bearing for planning and Conductor for parallel execution. The question Bearing answers is &#8220;how do I think clearly about what to build while AI builds it?&#8221;</p><h3><em>Sources:</em></h3><ul><li><p><em>Liu et al.,<a href="https://arxiv.org/abs/2307.03172"> &#8220;Lost in the Middle: How Language Models Use Long Contexts&#8221;</a> (TACL, 2024) &#8212; tested on GPT-3.5 and Claude 1.3; the positional attention effect has been reduced in newer models but the signal-to-noise principle still holds</em></p></li><li><p><em>He et al.,<a href="https://openreview.net/forum?id=fPmScVB1Td"> &#8220;Found in the Middle: How Language Models Use Long Contexts Better via Plug-and-Play Positional Encoding&#8221;</a> (2024) &#8212; proposes Ms-PoE to mitigate the lost-in-the-middle effect</em></p></li><li><p><em>Yang et al.,<a href="https://arxiv.org/abs/2309.03409"> &#8220;Large Language Models as Optimizers&#8221; (OPRO)</a> (Google DeepMind, 2023)</em></p></li><li><p><em>Wang et al.,<a href="https://arxiv.org/abs/2310.16427"> &#8220;PromptAgent: Strategic Planning with Language Models Enables Expert-level Prompt Optimization&#8221;</a> (2024)</em></p></li><li><p><em>Microsoft Research,<a href="https://www.microsoft.com/en-us/research/blog/promptwizard-the-future-of-prompt-optimization-through-feedback-driven-self-evolving-prompts/"> &#8220;PromptWizard&#8221;</a> (2025)</em></p></li><li><p><em>Ouyang et al.,<a href="https://arxiv.org/abs/2203.02155"> &#8220;Training language models to follow instructions with human feedback&#8221; (InstructGPT)</a> (OpenAI, 2022)</em></p></li><li><p><em>Bai et al.,<a href="https://arxiv.org/abs/2204.05862"> &#8220;Training a Helpful and Harmless Assistant with RLHF&#8221;</a> (Anthropic, 2022)</em></p></li><li><p><em>Addy Osmani,<a href="https://addyosmani.com/blog/code-agent-orchestra/"> &#8220;The Code Agent Orchestra&#8221;</a> (2026) &#8212; comprehensive overview of multi-agent coding patterns</em></p></li><li><p><em>Maggie Appleton,<a href="https://maggieappleton.com/gastown"> &#8220;Gas Town&#8217;s Agent Patterns, Design Bottlenecks, and Vibecoding at Scale&#8221;</a> (2026)</em></p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://rocketvish.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>