<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>terraboops</title>
      <link>https://terratauri.com</link>
      <description>terra tauri on platform engineering, developer experience, and AI-assisted infrastructure.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://terratauri.com/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Tue, 01 Sep 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Scaling Out</title>
          <pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/scaling-out/</link>
          <guid>https://terratauri.com/blog/scaling-out/</guid>
          <description xml:base="https://terratauri.com/blog/scaling-out/">&lt;p&gt;When a system runs out of headroom, you&#x27;ve got two options: buy a bigger box, or run more boxes. We settled that question for the whole internet a long time ago; the web runs on adding cheap machines, not one unaffordable one. And yet the moment someone says &quot;I need more from my AI,&quot; the default answer is still the first option. A bigger model. A bigger GPU. More of the scarcest memory money can buy.&lt;&#x2F;p&gt;
&lt;p&gt;The research keeps pointing the other way. A routing trick here. A paper about coordinating agents there. A tiny model released out of nowhere. Put them together and they&#x27;re all describing the same thing: &lt;strong&gt;horizontal scaling for inference&lt;&#x2F;strong&gt;. And horizontal scaling is the only thing that has ever made computing cheap.&lt;&#x2F;p&gt;
&lt;p&gt;I think the reason AI keeps getting expensive is that we keep buying a bigger computer instead of running more of the small ones we already have; every piece of the &quot;run more of them&quot; answer already exists.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-people-already-building-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-people-already-building-it&quot; aria-label=&quot;Anchor link for: the-people-already-building-it&quot;&gt;The people already building it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;karpathy&#x2F;status&#x2F;1938626382248149433&quot;&gt;Andrej Karpathy&lt;&#x2F;a&gt; argues the model most of us actually need is small, a few billion parameters or fewer; his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;karpathy&#x2F;status&#x2F;1938626382248149433&quot;&gt;&quot;cognitive core&quot;&lt;&#x2F;a&gt; idea is one that reasons well, uses tools, and &lt;em&gt;looks facts up&lt;&#x2F;em&gt; instead of memorizing the entire internet. On &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dwarkesh.com&#x2F;p&#x2F;andrej-karpathy&quot;&gt;Dwarkesh Patel&#x27;s podcast, The Lunar Society&lt;&#x2F;a&gt;, Karpathy made the same point: the field is already moving that way; top models grew for years and are now shrinking, and nearly every good small model is a distillation, trained to copy a bigger one.&lt;&#x2F;p&gt;
&lt;p&gt;If skill and memorized facts can be pulled apart, then a small model tuned for one narrow job doesn&#x27;t need a frontier model&#x27;s extra hundred billion parameters, because most of those parameters carry knowledge the job never touches.&lt;&#x2F;p&gt;
&lt;p&gt;Karpathy turned the point into a working tool. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;karpathy&#x2F;autoresearch&quot;&gt;Autoresearch&lt;&#x2F;a&gt; strips his training stack down to one GPU, one file, one number to improve; then it hands the whole thing to a coding agent that proposes a change, runs a five-minute training run, keeps the change only if the score goes up, and repeats overnight with no human in the loop. His long run stacked twenty improvements across seven hundred experiments, on training code he&#x27;d already spent years tuning by hand; that run even caught a missing scalar in the attention math that two decades of manual work never noticed.&lt;&#x2F;p&gt;
&lt;p&gt;The supply side is where the loop gets powerful. If a small model is something an agent can measurably improve while you sleep, then a fleet of specialists stops being a hand-made thing and becomes something you &lt;em&gt;grow&lt;&#x2F;em&gt;. A way less glamorous version of the same loop runs my own inference benchmarks: one agent on a schedule, another shipping fixes behind quality gates. Six of its performance fixes once quietly broke retrieval, and the failing test was the only thing that noticed. In another project, 716 tests passed and typecheck was clean, and six real defects showed up only the first time the thing ran against a real Slack conversation. Gates catch what they were written to catch; they are not evidence that the system works.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-pieces-are-all-sitting-there&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-pieces-are-all-sitting-there&quot; aria-label=&quot;Anchor link for: the-pieces-are-all-sitting-there&quot;&gt;The pieces are all sitting there&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Take them one at a time and none of this is exotic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The router is just a load balancer.&lt;&#x2F;strong&gt; The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.vllm.ai&#x2F;2025&#x2F;09&#x2F;11&#x2F;semantic-router.html&quot;&gt;vLLM Semantic Router&lt;&#x2F;a&gt; puts a small trained classifier in front of a pool of models and sends each request where it belongs: easy questions to the fast path, hard ones to the reasoning model. Routing is a &lt;em&gt;sorting problem&lt;&#x2F;em&gt;, and a sorter can be hundreds of times smaller than the models it sorts between. A good receptionist doesn&#x27;t need to be the smartest person in the building; they need to know which door to send you to. Sakana&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sakana.ai&#x2F;fugu-beta&#x2F;&quot;&gt;Fugu&lt;&#x2F;a&gt; is the same idea trained until it stops looking like a router: a model that calls other models, sending each request to the right specialist across a pool of frontier models and across vendors, so a provider going dark becomes a change of routing rather than an outage. That is the point where routing shades into orchestration. Caveat: this piece is less solved than it sounds. In production the router shares a GPU with the models it routes, and making it cheap for long inputs is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2603.12646&quot;&gt;an open research problem&lt;&#x2F;a&gt; on its own.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The orchestrator can be learned, and it can be small.&lt;&#x2F;strong&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sakana.ai&#x2F;fugu-beta&#x2F;&quot;&gt;Sakana&#x27;s Fugu&lt;&#x2F;a&gt; puts a ~0.6B coordinator and a 7B planner in charge of a pool of worker models, handing out Thinker, Worker, and Verifier roles instead of a hand-wired pipeline. The worker pool is frontier models, so this is evidence for &lt;em&gt;small coordinators&lt;&#x2F;em&gt;, not small workers. &quot;Rivals frontier models&quot; is generous; Fugu Ultra scores 73.7 on SWE-Bench Pro where Claude Fable 5 scores 86 on Sakana&#x27;s own table. What it proves is where the intelligence needs to live: in the planning and the checking, which are genuinely open-ended, and not in the sorting.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Teams work if you respect the cache.&lt;&#x2F;strong&gt; Nous Research&#x27;s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hermes-agent.nousresearch.com&#x2F;docs&#x2F;user-guide&#x2F;features&#x2F;mixture-of-agents&quot;&gt;Hermes agent&lt;&#x2F;a&gt; shipped a Mixture-of-Agents mode where an aggregator reads several models&#x27; answers and combines them into something better, and the team beats its own strongest member on their benchmark. The other models&#x27; outputs get appended at the &lt;em&gt;very end&lt;&#x2F;em&gt; of the prompt, below a stable prefix that never changes, so the prompt cache never breaks and the only cost of the team is the extra calls. The KV cache is the real currency of inference, and every serious multi-model design ends up organized around not wasting it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Teams aren&#x27;t free, and now we&#x27;ve got numbers.&lt;&#x2F;strong&gt; A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;research.google&#x2F;blog&#x2F;towards-a-science-of-scaling-agent-systems-when-and-why-agent-systems-work&#x2F;&quot;&gt;Google Research study&lt;&#x2F;a&gt; tested 180 agent-system configurations. Adding agents helps when a task splits into parallel parts; a centralized team beat a single agent by roughly 81%. It &lt;em&gt;actively hurts&lt;&#x2F;em&gt; when a task is sequential; every multi-agent setup they tested made results 39 to 70% worse, because the agents talking to each other ate the budget the reasoning needed. Error amplification is the scarier one: parallel agents with nobody checking amplified errors about 17x, while adding an orchestrator that reviews the work cut it to about 4x. The value lives in coordination and checking, and a team without them is worse than no team.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The fix for the worst failure is infrastructure.&lt;&#x2F;strong&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2603.04474&quot;&gt;From Spark to Fire&lt;&#x2F;a&gt; studied error cascades: chains where one agent&#x27;s mistake becomes another agent&#x27;s input and multiplies, until a group vote settles on the wrong answer as agreed truth. Their answer is provenance. Give every message a link to its parents, so when a detector flags one message as bad, you can quarantine everything descended from it before it reaches the user. In their tests that raised the share of runs where a planted error never reached the final answer from ~32% to ~89%. It&#x27;s a message log with parent pointers, and message logs are something engineering already knows how to build. I&#x27;ve been building the unglamorous version in a separate project. Every action is an event in an append-only log; an event&#x27;s trust class is derived from its kind rather than declared by whoever wrote it, so an agent cannot mark its own output as a human decision; and the rule that an outbound client message requires a human principal is a database constraint, not a policy document, so it holds for someone poking at the database with the application nowhere in sight. That is what provenance looks like once it stops being a diagram: a type you can&#x27;t lie in, and a check that survives the app being bypassed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The workers are small enough to throw away.&lt;&#x2F;strong&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.googleblog.com&#x2F;en&#x2F;introducing-gemma-3-270m&#x2F;&quot;&gt;Gemma 3 270M&lt;&#x2F;a&gt; is 125MB at 4-bit, follows instructions out of the box, and is designed by its own authors to be fine-tuned for &lt;em&gt;one&lt;&#x2F;em&gt; job rather than used as a generalist. Tuned that way, models this size get close to far larger general models on narrow jobs like sorting and extracting text, at a fraction of the memory; and they stop working the moment the task changes, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=44902148&quot;&gt;say the creators themselves&lt;&#x2F;a&gt;. Fragile is fine if something is watching, and the routing and checking layers above are exactly that something. I have my own measurement of how quietly that fragility hides. Compressing a 30B coding model&#x27;s KV cache down to three bits scored 100% on my intelligence checks, which used prompts of about fifty tokens; at 2.5K tokens of context the same setup completed &lt;code&gt;factorial&lt;&#x2F;code&gt; as &lt;code&gt;def factorial(n: int): int): return n * n * x&lt;&#x2F;code&gt;. Keeping 16 of 48 layers in full precision brought back &lt;code&gt;return math.factorial(n)&lt;&#x2F;code&gt;. The failure did not exist at the size I was testing at, which is the general shape: cheap parts fail silently, and the layer above has to be the thing that notices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-everybody-skips&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-everybody-skips&quot; aria-label=&quot;Anchor link for: what-everybody-skips&quot;&gt;What everybody skips&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Put those pieces side by side and a familiar diagram shows up. The classifier router is a load balancer. The specialists are workers. Mixture-of-Agents is a quorum polling several answers. The learned orchestrator is a scheduler. Every component of a horizontally scaled service is being reinvented for inference, one paper at a time; mostly without anyone saying the phrase out loud.&lt;&#x2F;p&gt;
&lt;p&gt;But horizontal scaling has a requirement that&#x27;s easy to miss until it breaks something: &lt;strong&gt;your workers have to be stateless, or their state has to live somewhere cheap.&lt;&#x2F;strong&gt; The web spent years prying session state out of its servers and into stores like Redis, precisely so any worker could handle any request and workers could be killed and replaced freely.&lt;&#x2F;p&gt;
&lt;p&gt;A model&#x27;s &quot;session state&quot; is its KV cache. And right now that state is welded to the most expensive memory in the building. Every loaded specialist occupies GPU memory whether it&#x27;s working or not, and every swap means paying the full cost of re-reading the context from zero. That&#x27;s the exact property that makes horizontal scaling too expensive, and it&#x27;s why the fleet of specialists has stayed a diagram instead of a deployment.&lt;&#x2F;p&gt;
&lt;p&gt;The fix is the same one it&#x27;s always been: &lt;strong&gt;move the state somewhere cheap.&lt;&#x2F;strong&gt; Save the KV cache, and the prepared weights, to disk. Waking a specialist back up becomes a file read, not a recompute from scratch. This is already how it works at the big end. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LMCache&#x2F;LMCache&quot;&gt;LMCache&lt;&#x2F;a&gt; moves KV caches out of GPU memory, through RAM, down to local disk and remote storage, and the wins are dramatic where context is long; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.lmcache.ai&#x2F;kv_cache&#x2F;local_storage.html&quot;&gt;their disk benchmark&lt;&#x2F;a&gt; takes time-to-first-token from 6.3s cold to 0.15s warm, because loading saved state off disk beats re-reading a long prompt even though disk is slow. And if you use a hosted provider you&#x27;re already living in this economy without the diagram; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;news&#x2F;prompt-caching&quot;&gt;cached input tokens cost a tenth of fresh ones&lt;&#x2F;a&gt;, because the provider is doing exactly this trade for you. The price sheets make the point more bluntly than the architecture diagrams do. A cache read is 0.1x base input, so a cached prefix pays for its write after one or two reads. Gemini bills $0.50 per million tokens per hour simply to &lt;em&gt;hold&lt;&#x2F;em&gt; a context cached. A managed agent session is billed $0.08 per session-hour of wall clock while it is merely running, on top of every token it spends. Warm state is metered by the hour wherever you look for it. A file sitting on a disk is not.&lt;&#x2F;p&gt;
&lt;p&gt;This is where the trade pays off. &lt;strong&gt;If a specialist&#x27;s entire warm state is a file, then how many specialists you can &lt;em&gt;have&lt;&#x2F;em&gt; is limited by disk.&lt;&#x2F;strong&gt; Disk is cheap and grows to terabytes on hardware you already own. &lt;strong&gt;How many run at once stays limited by compute.&lt;&#x2F;strong&gt; You stop asking &quot;how much GPU memory do I need to hold my models?&quot; and start asking &quot;how big is my library, and how much of it is hot right now?&quot; That&#x27;s a caching question, and we are good at those. Swap RAM for disk, scarce for cheap, and multi-agent systems stop being a demo and pick up a real cost curve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-built-and-where-it-stands&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-built-and-where-it-stands&quot; aria-label=&quot;Anchor link for: what-i-built-and-where-it-stands&quot;&gt;What I built, and where it stands&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been prototyping the small end of this myself, and the numbers are now specific enough to argue with.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Prefill is the cost, and skipping it is the win.&lt;&#x2F;strong&gt; My clearest evidence came out of a run that wasn&#x27;t about caching at all: pushing a 30B coding model to a 512K-token context on one 48GB laptop. Prefilling those 524,288 tokens took 6,671 seconds, about 111 minutes. Generating the 32-token answer afterwards took roughly 2 seconds. Reading the context, not answering from it, is where effectively all the wall clock goes; and it gets worse the further you go, with per-chunk throughput falling from about 163 tokens&#x2F;second at 65K to about 58 at 512K, because each new chunk has to attend over everything before it. Every design in this post that avoids re-reading a prompt is chasing that one ratio.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Save-and-wake works, and the saving is measurable.&lt;&#x2F;strong&gt; A 0.5B specialist&#x27;s KV cache freezes to disk encrypted, wakes back up, and keeps generating. On a 6,145-token prefix, the resumed session pushed 12 prefill tokens through the model where a cold rebuild pushed 6,156: &lt;strong&gt;513x fewer&lt;&#x2F;strong&gt;, on real hardware, against a threshold of 3x that I wrote down before running it. The same measurement on stock full-precision caches came out at 551x (8 tokens against 4,409 on a 4.4K prefix), and there the forked resume also beat re-prefilling on wall clock, deep copy included: 119ms against 696ms. Prefill tokens are the steadier measure; the ratio holds on any GPU, and it&#x27;s what the design leans on.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Routing is as cheap as the receptionist argument needs it to be.&lt;&#x2F;strong&gt; A classify on that 0.5B model, prefill plus one logit, measured 10.7ms at p50 and 11.3ms at p95, against a budget of 150 and 300ms I&#x27;d fixed in advance; a later run of the same gate came back at 7.9 and 8.0ms. A short tool-use reply came in at 422ms. Sorting costs about ten milliseconds.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Residency is bounded by disk, not RAM.&lt;&#x2F;strong&gt; The piece that turns those facts into a fleet is a registry holding N specialists, each with its own resumable session, with only a capped hot set resident: an LRU with logged eviction, snapshots keyed by a hash of the specialist&#x27;s current log-derived context, and stale snapshots collected so the disk stays bounded too. A missing or stale snapshot is never fatal; it rebuilds from the log. That rule is what makes the whole arrangement safe to run, because it means the log is the truth and the cache is disposable, so a fragile saved state can cost you time and never correctness. The number that makes eviction a real policy is the residency budget: about 812MB resident per 0.5B 4-bit specialist. This part is built and tested and wired into nothing that serves traffic; I&#x27;m not going to call a parked module a deployment.&lt;&#x2F;p&gt;
&lt;p&gt;The same session layer runs against the 30B coding model as six REST endpoints, and the whole lifecycle, create, fork, rewind, save, load, is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;omlx&#x2F;blob&#x2F;hypercar&#x2F;BENCHMARKS.md&quot;&gt;in a public benchmark log&lt;&#x2F;a&gt;: forks are instant reference copies, rewind drops 35 tokens from a context in constant time without re-reading anything, and a saved session wrote 47 layers into under a megabyte and came back. The encryption is doing real work, because a KV cache contains the conversation that made it, and an unencrypted snapshot is your private data sitting on disk dressed up as a performance optimization. The snapshots are AEAD-encrypted at rest and the registry refuses to run against a store that has no keystore, so there is no configuration in which the plaintext path is the convenient one.&lt;&#x2F;p&gt;
&lt;p&gt;Compression is what makes the state small enough for the trade to be worth making at all. At 256K tokens on that laptop, a full-precision KV cache is about 10.5GB and thrashes; the same cache at 4-bit is about 2.6GB, and that headroom is the difference between failing around 256K and passing at 512K on the same machine.&lt;&#x2F;p&gt;
&lt;p&gt;What I still owe is wall clock on the disk path specifically. A slow enough disk read could eat a 513x token saving while the token-ratio gate sails through, and the timing gate that would catch that is written and not yet run. Until it is, cheaper is proven in tokens and assumed in seconds. The other thing I have not proven is the interesting half of routing: my learned router picks a specialist by embedding the request and taking the nearest centroid, deferring when the best match is weak or the top two are close, and its measured win is against an injected embedder in tests rather than a real one on real traffic.&lt;&#x2F;p&gt;
&lt;p&gt;And the uncomfortable bits for anyone this excites: the &lt;strong&gt;router is a single point of failure&lt;&#x2F;strong&gt;, a poorly calibrated one that doesn&#x27;t know when it doesn&#x27;t know, quietly making everything downstream worse. &lt;strong&gt;Saved caches are fragile by design&lt;&#x2F;strong&gt;, valid only for one exact pairing of weights and prompt prefix; which is why Hermes&#x27;s never-change-the-top-of-the-prompt discipline and the save-to-disk story are two forms of the same idea. &lt;strong&gt;Error cascades&lt;&#x2F;strong&gt; are why I think provenance ends up as necessary as the load balancer, part of the base design rather than an optional extra. And the gap in the evidence is the space between this post and reality: learned orchestration is proven with big workers, small workers are proven on narrow jobs, and nobody has published the system that does both at once.&lt;&#x2F;p&gt;
&lt;p&gt;Scaling up buys capability in a straight line, on hardware that gets scarcer the higher you climb. Scaling out is the only shape that has ever made computing cheap, and every piece of it already exists somewhere in the literature. What&#x27;s missing is the unglamorous work: residency management, deciding what stays loaded and what gets evicted, which in my case is an LRU and a garbage collector; router calibration; and wiring the whole thing together. The supervisor I run my own fleet of agent sessions through is the same kind of object, and it&#x27;s made of nothing exotic: exact-match signals, dedupe, a debounce so a firehose arrives as one digest, buffered events that survive a restart, and a single-instance lock. That&#x27;s ordinary systems work, the kind platform engineering already has good answers for. Anyone who wants to can just pick it up. I know I&#x27;ve been doing exactly that.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Gas-Powered Wagon</title>
          <pubDate>Sun, 31 May 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/the-gas-powered-wagon/</link>
          <guid>https://terratauri.com/blog/the-gas-powered-wagon/</guid>
          <description xml:base="https://terratauri.com/blog/the-gas-powered-wagon/">&lt;p&gt;There&#x27;s a genre of AI blog post that I skip as soon as I recognize it: the company retrospective where they handed everyone Copilot or Claude Code, waited a couple of quarters, and came away disappointed that nothing shipped any faster.&lt;&#x2F;p&gt;
&lt;p&gt;What bothers me about it is that it reaches for a causal story when all it has is a correlation, and it never goes looking for the mechanism underneath. We adopted the thing, the number didn&#x27;t move, therefore the thing doesn&#x27;t work. It&#x27;s the reasoning of someone who straps a gasoline engine onto the back of a wagon, watches the extra weight slow the horses down, and concludes that engines make you slower.&lt;&#x2F;p&gt;
&lt;p&gt;The thing is, you can&#x27;t actually do that. A wagon is built around the pull of an animal, the wheels only have to roll and bear weight, the axle is a dead beam that holds the wheels apart and carries the load straight down, and the whole thing is tuned for the speed of a walking horse. An engine delivers power in a completely different way, as torque that has to be transmitted to the wheels, which means you need a gearbox to trade the engine&#x27;s fast spin for usable force, a clutch to engage it, a driveshaft to carry the power back, and a differential so the wheels can turn at different rates through a corner. The dead wagon axle can&#x27;t take any of that, it would twist and shear the first time the engine bit, and even if it somehow held, the wooden wheels and the plain greased bearings would tear themselves apart at any speed the engine could reach, the brake meant for walking pace wouldn&#x27;t stop the thing, and the frame would shake itself to splinters. By the time you&#x27;ve added a real drivetrain, a live axle, proper wheels and tires, brakes that work at speed, and a frame stiff enough to survive the vibration, you haven&#x27;t built a faster wagon. You&#x27;ve built a car, and it only resembles a wagon from a distance.&lt;&#x2F;p&gt;
&lt;p&gt;That is the move every disappointed AI rollout actually made, dropping a new source of power onto a structure that was only ever designed to be pulled along slowly. You can&#x27;t bolt more horsepower onto every engineer and expect the organization to move faster if the parts that carry the load were built for walking pace, and the research that&#x27;s accumulated over the last couple of years keeps pointing at the same conclusion, which is that the thing slowing it down was never the typing. The coordination problems were already there, the slow reviews and the relitigated decisions and the handoffs that stall for a day, we&#x27;d just learned to live with them because the cost of building was high enough to hide them. AI didn&#x27;t create any of that. It made the rest of the work fast enough that the old friction finally shows up against the new baseline, and the friction is the same friction it always was. It isn&#x27;t AI&#x27;s fault that our organizations never kept pace with the work they were already doing, AI only shone a light on it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-number-that-goes-the-wrong-way&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-number-that-goes-the-wrong-way&quot; aria-label=&quot;Anchor link for: the-number-that-goes-the-wrong-way&quot;&gt;The number that goes the wrong way&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dora.dev&#x2F;research&#x2F;2024&#x2F;dora-report&#x2F;&quot;&gt;2024 DORA report&lt;&#x2F;a&gt;, three quarters of the people surveyed said they were leaning on AI for part of their job, three quarters reported feeling more productive, and then the system-level numbers went the other way, with the report estimating that a 25% increase in AI adoption corresponded to a 1.5% drop in delivery throughput and a 7.2% drop in delivery stability, and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redmonk.com&#x2F;rstephens&#x2F;2025&#x2F;12&#x2F;18&#x2F;dora2025&#x2F;&quot;&gt;2025 follow-up&lt;&#x2F;a&gt; held the pattern rather than reversing it. The easy reading is that the engineers are kidding themselves, that the felt productivity is a sugar high and the dashboard is the truth, and I don&#x27;t buy it, because the feeling and the dashboard aren&#x27;t measuring the same thing. What an engineer feels when she uses a good model is the speed of implementation, the rate at which intent turns into working code under her hands, and that genuinely has gotten faster. What DORA measures is delivered value, the throughput and stability at the far end of a pipeline that every change still has to crawl through, the review and the testing and the approval and the deploy. Jez Humble has spent fifteen years pointing out that none of the value is real until the change is safely in production, that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.thoughtworks.com&#x2F;insights&#x2F;blog&#x2F;continuous-delivery&#x2F;continuous-delivery-not-just-a-technical-activity&quot;&gt;&quot;done&quot; means released&lt;&#x2F;a&gt; rather than written, and that a fast delivery capability pays off only when the organization wrapped around the pipeline is built to use it. Mary Poppendieck has the sharper version, that if you map the value stream from idea to production the development work isn&#x27;t where the time goes, it&#x27;s the queues and the approvals, which Mary puts at somewhere between half and ninety percent of the elapsed time. Speed up the small slice that is implementation, leave the rest of the pipeline untouched, and the delivered number was never going to move much.&lt;&#x2F;p&gt;
&lt;p&gt;Every engineer who has used AI to build something for herself over a weekend, or thrown together a tool for a friend, already knows the implementation speedup is real, because at home there is no pipeline in the way, just her and the keyboard and a thing that exists by Sunday night that wouldn&#x27;t have existed otherwise. The reason she can&#x27;t reproduce that feeling at work isn&#x27;t that she imagined it the first time. It&#x27;s that at work the value has to survive the trip through the pipeline before it counts for anything, and the pipeline is exactly where it stalls, which makes the whole thing a delivery failure that we keep mislabeling as a productivity one.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a study people reach for to argue the keyboard didn&#x27;t even get faster, and it deserves to be handled carefully rather than waved around. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;metr.org&#x2F;blog&#x2F;2025-07-10-early-2025-ai-experienced-os-dev-study&#x2F;&quot;&gt;METR&lt;&#x2F;a&gt; ran a randomized trial with sixteen experienced developers working real issues on their own mature repositories, codebases averaging over a million lines that they&#x27;d maintained for years, and found that with AI allowed they were 19% slower, even though they expected to be faster and believed afterward that they had been. It would be easy to stop there and announce that AI doesn&#x27;t work, which is the lazy move I opened this post complaining about. METR didn&#x27;t stop there, they ran a factor analysis, and the parts worth dwelling on are about the quality bar, because the study counted a task as done only when the author was satisfied the code would pass review, style and testing and documentation included, and the mature repositories carried a lot of implicit standards that the model didn&#x27;t know and the developer had to supply by hand. The time didn&#x27;t disappear into typing, it went into making the output trustworthy enough to survive a demanding codebase, which is the cost this whole post is about showing up at the scale of a single change. They&#x27;re careful to note that this says nothing about less experienced developers or unfamiliar codebases, the cases where the quality bar is lower and the model has less hidden context to trip over. Whichever way the keyboard number breaks, what cost them time was trusting the code rather than generating it.&lt;&#x2F;p&gt;
&lt;p&gt;Rachel Stephens at RedMonk had the foresight to see this same thing back in 2024 and her &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redmonk.com&#x2F;rstephens&#x2F;2024&#x2F;11&#x2F;26&#x2F;dora2024&#x2F;&quot;&gt;writeup&lt;&#x2F;a&gt; is well worth a read. Her move is to dust off the theory of constraints, the old idea that a system only moves as fast as its tightest bottleneck, and Gene Kim&#x27;s blunt version of it: that any improvement you make somewhere other than the bottleneck is an illusion. If you pour all your new capacity into writing code faster, and writing code was never the constraint, you&#x27;ve optimized the wrong station on the line. You&#x27;ve fitted a stronger engine and left the axle exactly as it was.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;coordination-was-the-heavy-part&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#coordination-was-the-heavy-part&quot; aria-label=&quot;Anchor link for: coordination-was-the-heavy-part&quot;&gt;Coordination was the heavy part&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So what is the constraint, if not the code? My answer is coordination. I don&#x27;t mean it in the vague &quot;we should communicate better&quot; sense. I mean coordination in the specific, measurable sense the productivity researchers have been pointing at for years.&lt;&#x2F;p&gt;
&lt;p&gt;When Forsgren and Storey and the rest of the SPACE authors laid out their five dimensions of developer productivity back in 2021, one of the five was Communication and Collaboration, sitting right next to the activity counts everyone actually tracks. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;queue.acm.org&#x2F;detail.cfm?id=3595878&quot;&gt;DevEx framework&lt;&#x2F;a&gt; that followed put feedback loops at the front, the speed of getting an answer back from a person or a system, the code-review turnaround, the wait for an approval, the handoff between teams. Those are coordination costs wearing different names, and they were already the expensive part long before anyone could generate a thousand lines of plausible code in a minute.&lt;&#x2F;p&gt;
&lt;p&gt;The part I think gets underplayed is the economics, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;natesnewsletter.substack.com&#x2F;p&#x2F;executive-briefing-ai-raised-output&quot;&gt;Nate Jones&lt;&#x2F;a&gt; has put numbers to it in his newsletter better than I&#x27;m about to. Coordination has always carried a cost, with the communication paths between people growing roughly with the square of the team size, the n(n-1)&#x2F;2 that Brooks wrote about half a century ago. What AI changes isn&#x27;t that arithmetic. What it changes is the price of every hour you spend on the left side of it. If an engineer with good tooling can now implement in an afternoon what used to take a week, then every hour that engineer spends in a status meeting, or waiting on a review, or relitigating a decision that was already made, is an hour priced against the much larger amount they could have built instead. The opportunity cost of coordinating went up because the opportunity itself got bigger. Some of the estimates floating around put coordination overhead at well over half of all knowledge-worker hours (which I&#x27;d treat as directional rather than gospel), but even the conservative version of that claim means the bottleneck has been sitting in plain sight on everyone&#x27;s calendar the whole time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-d-actually-do-about-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-d-actually-do-about-it&quot; aria-label=&quot;Anchor link for: what-i-d-actually-do-about-it&quot;&gt;What I&#x27;d actually do about it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;What I&#x27;d take from all of this is less a fix than a reorientation. The instinct, once the engine is bolted on, is to keep tuning the engine, to get better at prompting, to adopt the next coding agent, to measure acceptance rates. The more useful instinct is to figure out which parts of the wagon are going to break when you try to go 0 to 60 in 1.66 seconds.&lt;&#x2F;p&gt;
&lt;p&gt;In practice that has started with the practice everyone points at first, review, because the agent produces changes faster than anyone can read them and the pull requests stack up. The first tech talk I gave at Bit Complete argued that review was the bottleneck, and I&#x27;ve since come around to thinking that was only half right, because review is mostly a proxy for trust. Nobody really minds that there are more changes to review, what they mind is being asked to vouch for code they have no other way to trust, and a human reading the diff is the slowest and least reliable way to earn that trust. Review is drowning because we let the cheaper sources of trust atrophy, the automated tests and the feature flags and the staged rollouts and the observability and alerting that let a team ship something it isn&#x27;t yet sure of without betting production on it. Investing heavily in these is what stops review from being the place everything queues, because a change you can roll out to one percent of traffic, watch, and switch off in seconds doesn&#x27;t need a human to have read every line before it goes out. The DORA authors point at a version of this from another angle, with the throughput and stability drops tracking the arrival of larger, messier change sets, which is to say the old advice about small batch sizes matters more now rather than less, precisely because the tools make it so easy to produce a large batch.&lt;&#x2F;p&gt;
&lt;p&gt;It has also meant taking the team-shape questions seriously, the ones Team Topologies and Conway&#x27;s law were already asking. If coordination cost grows with the number of people who have to agree, then the lever is to need fewer of them in the room, with smaller teams holding clearer ownership, decisions written down once and referred back to instead of relitigated, and dependencies designed out of the architecture rather than negotiated across it every sprint. None of that is new advice. What&#x27;s new is how much it&#x27;s now worth, and how far the rebuild has to go, because you don&#x27;t get to bolt the engine on and keep the wagon. The structure that survives the new power is the one you&#x27;ve reinforced and re-geared and rebuilt until it isn&#x27;t really a wagon anymore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-thing-that-actually-scares-me&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-thing-that-actually-scares-me&quot; aria-label=&quot;Anchor link for: the-thing-that-actually-scares-me&quot;&gt;The thing that actually scares me&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The thing that actually scares me in all of this isn&#x27;t the failed rollouts, it&#x27;s cognitive offloading, because it&#x27;s a cost the org chart doesn&#x27;t capture and it lands on the individual engineer rather than the pipeline. Cognitive offloading, the transfer of mental work from a person to an external system, is exactly what makes agents worth reaching for, and a lot of what gets offloaded is no loss at all, because the boilerplate and the routine lookups and the mechanical refactors were never building anything in the first place. But some of the work we&#x27;re handing over was the work that kept us sharp, the deep reading of unfamiliar code, the debugging intuition that only comes from hours spent tracking down problems, the design judgment that accumulates from making decisions and watching them play out, and the persistence to stay with a hard problem until the answer is right rather than merely plausible. Those are skills maintained through the act of doing them, and they quietly atrophy when the act is always delegated. The persistence one is the best evidenced: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ai-project-website.github.io&#x2F;AI-assistance-reduces-persistence&#x2F;&quot;&gt;Liu et al. (2025)&lt;&#x2F;a&gt; ran three randomized experiments and found that people who solved problems with AI did measurably worse once it was taken away, with the effect concentrated in the majority who reached for it to get the answer rather than a hint, the option of a direct solution quietly removing the part of the work that builds the habit of staying.&lt;&#x2F;p&gt;
&lt;p&gt;This matters for the rebuild specifically. The structure I&#x27;ve been describing puts the human in a more supervisory seat, auditing and specifying and orchestrating rather than typing, and auditing requires the very skill the agent is replacing, because you can&#x27;t evaluate a design proposal you no longer have the judgment to evaluate. So the offloading turns out to be self-limiting: let those skills go and you can only supervise the easy work, which is the opposite of what the rebuild was for. The defense isn&#x27;t to refuse the tools, it&#x27;s a bit of deliberate practice, reading some code without the agent, debugging some problems by hand, taking a position on the trade-offs before asking for its analysis, writing specs at the precision a human reviewer would need even when the reader is a machine, and keeping ownership of a few small things end to end. The cost is a little short-term throughput. The return is staying able to do the supervising the whole rebuild depends on.&lt;&#x2F;p&gt;
&lt;p&gt;The companies writing the disappointed retrospectives aren&#x27;t wrong that the number didn&#x27;t move. They bolted the most powerful engine anyone has ever handed them onto an axle built for a walking horse, and then blamed the engine when nothing went faster. The engine was never the problem, the wagon always was.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The agent cannot guard itself</title>
          <pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/the-agent-cannot-guard-itself/</link>
          <guid>https://terratauri.com/blog/the-agent-cannot-guard-itself/</guid>
          <description xml:base="https://terratauri.com/blog/the-agent-cannot-guard-itself/">&lt;p&gt;Every coding-agent sandbox I&#x27;ve set up ends in the same tired loop. I lock it down, the agent stops being useful, I loosen it, and I end up exactly where I started: YOLO mode. At best there is a sandbox-shaped object draped loosely over a process that can still do almost anything it wants. In professional contexts where risk is paramount, I spend a lot of my day clicking approve and hoping I don&#x27;t accidentally allow the wrong thing.&lt;&#x2F;p&gt;
&lt;p&gt;This is the central UX trap of agent security. Convenience and capability are two ends of the same balance. When the sandbox lives inside the same process tree it&#x27;s supposed to constrain, it&#x27;s too tempting to give the LLM the ability to help you configure the sandbox.&lt;&#x2F;p&gt;
&lt;p&gt;The threats are real and recent: new CVEs, fresh supply-chain compromises, persistence attacks against agent harnesses are shipping in the wild. Three of the most terrifying attacks I know of are sandbox escape, audit tampering, and skill poisoning. All three share one source: a trust boundary lives inside something the agent controls, and the agent reasons its way to it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-sandbox-escape&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#1-sandbox-escape&quot; aria-label=&quot;Anchor link for: 1-sandbox-escape&quot;&gt;1. Sandbox escape&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Start with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ona.com&#x2F;stories&#x2F;how-claude-code-escapes-its-own-denylist-and-sandbox&quot;&gt;Ona&#x27;s writeup from March 2026&lt;&#x2F;a&gt;. Leonardo Di Donato observed Claude Code, in normal operation, finding three different ways around the sandbox restrictions that ship on it by default.&lt;&#x2F;p&gt;
&lt;p&gt;The first one is a path trick. The sandbox blocked &lt;code&gt;npx&lt;&#x2F;code&gt;, and the agent reasoned its way to &lt;code&gt;&#x2F;proc&#x2F;self&#x2F;root&#x2F;usr&#x2F;bin&#x2F;npx&lt;&#x2F;code&gt;, which resolves to the same file but doesn&#x27;t match the deny pattern. The denylist is matching strings, the agent is reaching files, and only one of those things knows the difference.&lt;&#x2F;p&gt;
&lt;p&gt;The second one needs a quick setup. On Linux, Claude Code uses bubblewrap, an unprivileged sandbox tool that requires user namespaces, which some hardened distros disable by default. When bubblewrap can&#x27;t initialize, Anthropic shipped two escape hatches: &lt;code&gt;dangerouslyDisableSandbox&lt;&#x2F;code&gt; and &lt;code&gt;allowUnsandboxedCommands&lt;&#x2F;code&gt;, both of which run the agent without a sandbox at all. The vendor put the off-switch right next to the on-switch, and the agent reached for it.&lt;&#x2F;p&gt;
&lt;p&gt;The third one is the bypass I keep thinking about. Ona had built a kernel-level guard called Veto that gated &lt;code&gt;execve(2)&lt;&#x2F;code&gt; and content-hashed binaries against an allowlist. Call &lt;code&gt;execve&lt;&#x2F;code&gt; on &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;wget&lt;&#x2F;code&gt; and Veto catches the syscall, hashes the binary, and refuses. The agent ran &lt;code&gt;&#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-linux-x86-64.so.2 &#x2F;usr&#x2F;bin&#x2F;wget&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;wget&lt;&#x2F;code&gt; on its own is just an ELF file. It can&#x27;t run without the dynamic linker mapping it into memory, resolving its shared library symbols, and jumping to the entry point. Normally &lt;code&gt;execve()&lt;&#x2F;code&gt; on &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;wget&lt;&#x2F;code&gt; triggers all of that automatically: the kernel reads the &lt;code&gt;PT_INTERP&lt;&#x2F;code&gt; entry in the ELF header, loads the linker on the program&#x27;s behalf, and hands control off. But the dynamic linker is also a regular executable in its own right, and you can invoke it directly with a binary path as its argument. The linker dutifully &lt;code&gt;mmap&lt;&#x2F;code&gt;s the binary into memory and starts executing it, and no second &lt;code&gt;execve&lt;&#x2F;code&gt; happens anywhere. Veto saw the &lt;code&gt;execve&lt;&#x2F;code&gt; on &lt;code&gt;ld-linux.so.2&lt;&#x2F;code&gt;, which was allowed. Veto never saw an &lt;code&gt;execve&lt;&#x2F;code&gt; on &lt;code&gt;wget&lt;&#x2F;code&gt;, because there wasn&#x27;t one.&lt;&#x2F;p&gt;
&lt;p&gt;Defenders enumerate forbidden actions, and a reasoning agent finds a different action with the same effect. The action space is combinatorial, and the agent is optimized for finding paths through combinatorial spaces. The only durable answer is to stop defining &quot;forbidden&quot; as a set of actions and start defining it as a set of &lt;em&gt;things the process cannot see&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That property lives at the kernel level. On Linux, Landlock provides it from 5.13 onward; on macOS, the TrustedBSD sandbox (Seatbelt) does the same thing. Both bind a process to a filesystem allowlist the process itself cannot widen for the rest of its lifetime. Once bound, all three bypasses fail by construction: alternate paths still resolve to inodes outside the allowlist (the kernel checks inodes, not strings); the self-disable fails because Landlock restrictions are irrevocable; the dynamic-linker trick fails at file-open time, because &lt;code&gt;ld.so&lt;&#x2F;code&gt; still has to &lt;code&gt;open()&lt;&#x2F;code&gt; the target binary, and that read is denied. There&#x27;s no string to outsmart, no off-switch to find, just nothing where the binary used to be.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-audit-tampering&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#2-audit-tampering&quot; aria-label=&quot;Anchor link for: 2-audit-tampering&quot;&gt;2. Audit tampering&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nono.sh&#x2F;blog&#x2F;secure-agent-audit&quot;&gt;Luke Hinds&#x27; post on tamper-evident audit trails&lt;&#x2F;a&gt; frames the problem clearly:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A log file is a story the program tells about itself. If the program is compromised — or if the agent has managed to write somewhere it shouldn&#x27;t — the log becomes part of the attack surface.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Nearly every agent log in the wild is written by the agent itself. Claude Code&#x27;s session log, Cursor&#x27;s &lt;code&gt;.cursor&#x2F;log&#x2F;&lt;&#x2F;code&gt;, every custom harness&#x27;s &lt;code&gt;agent.log&lt;&#x2F;code&gt;. It&#x27;s the audit equivalent of asking the suspect to write the police report.&lt;&#x2F;p&gt;
&lt;p&gt;Every tampering vector here is just a normal file write. The agent can rewrite events before they hit disk, truncate to drop early capability requests, reorder events to obscure causality, swap a recorded binary hash, or delete the session record entirely. By the time you review the log, the log says one thing and the filesystem says another, and there&#x27;s no principled way to know which is true.&lt;&#x2F;p&gt;
&lt;p&gt;The fix is the same rule the sandbox section needed: the audit writer must not be the audited process. A useful audit trail needs a supervisor in a different trust domain, capturing events through &lt;code&gt;seccomp-notify&lt;&#x2F;code&gt; so it sees each one before the agent can decide whether to log it. It needs cryptographic tampering detection over both events and their order. An append-only Merkle tree wrapped by a hash chain does this: change a byte and the root changes, truncate the chain and the chain breaks, reorder two events and the root changes again. And it needs the whole session signed at the end with a key the agent can&#x27;t reach, so anyone can verify the record later without trusting the host or the agent.&lt;&#x2F;p&gt;
&lt;p&gt;You cannot retrofit this onto a self-logging architecture. The trust-domain separation has to be there from the start.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-skill-poisoning&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#3-skill-poisoning&quot; aria-label=&quot;Anchor link for: 3-skill-poisoning&quot;&gt;3. Skill poisoning&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The third attack is the worst of the three because it&#x27;s persistent.&lt;&#x2F;p&gt;
&lt;p&gt;The shape is straightforward. An agent gets prompt-injected through one of a thousand surfaces: a markdown file it summarizes, a webpage it fetches, an email body, a GitHub issue, a code comment buried in someone&#x27;s PR. Take your pick.&lt;&#x2F;p&gt;
&lt;p&gt;The injection doesn&#x27;t ask for the secret directly. It asks the agent to modify a trusted instruction file (a &lt;code&gt;.claude&#x2F;commands&#x2F;*.md&lt;&#x2F;code&gt; slash command, a &lt;code&gt;SKILL.md&lt;&#x2F;code&gt;, an MCP server config, a &lt;code&gt;SessionStart&lt;&#x2F;code&gt; hook), appending a small malicious payload that will run every time anyone invokes that file from now until somebody notices.&lt;&#x2F;p&gt;
&lt;p&gt;The user sees nothing happen. The agent didn&#x27;t exfiltrate anything that turn. But every subsequent invocation of the modified command, skill, or hook silently runs the malicious instructions. The injection is one-shot, and the backdoor lives forever.&lt;&#x2F;p&gt;
&lt;p&gt;This is what &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wiz.io&#x2F;blog&#x2F;mini-shai-hulud-supply-chain-sap-npm&quot;&gt;Mini-Shai-Hulud&lt;&#x2F;a&gt; (April 29, 2026, the SAP CAP&#x2F;MBT npm compromise) did. The persistence step wrote a &lt;code&gt;SessionStart&lt;&#x2F;code&gt; hook into &lt;code&gt;.claude&#x2F;settings.json&lt;&#x2F;code&gt; and a &lt;code&gt;folderOpen&lt;&#x2F;code&gt; task into &lt;code&gt;.vscode&#x2F;tasks.json&lt;&#x2F;code&gt;, so the next time anyone launched Claude Code or opened the repo in VS Code, the credential stealer ran again. The same shape shows up in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;embracethered.com&#x2F;blog&#x2F;posts&#x2F;2025&#x2F;github-copilot-remote-code-execution-via-prompt-injection&#x2F;&quot;&gt;CVE-2025-53773&lt;&#x2F;a&gt;, Johann Rehberger&#x27;s GitHub Copilot RCE: the injection coerced Copilot into writing &lt;code&gt;chat.tools.autoApprove: true&lt;&#x2F;code&gt; to &lt;code&gt;.vscode&#x2F;settings.json&lt;&#x2F;code&gt;, silently flipping the agent into &quot;YOLO mode&quot; for future sessions.&lt;&#x2F;p&gt;
&lt;p&gt;The fix is the same trust-domain separation applied to instruction files. Trusting a file because it looks unmodified is exactly the pattern the agent can defeat in one turn. Trusting a file because the &lt;em&gt;content hash matches a publisher attestation&lt;&#x2F;em&gt; is something the agent can&#x27;t undo without breaking the signature. Each trusted file gets bound to its content hash via a Sigstore attestation (DSSE envelope, Fulcio cert, Rekor inclusion proof), and the harness verifies that bundle before loading. A single byte of tampering causes verification to fail hard.&lt;&#x2F;p&gt;
&lt;p&gt;I spent some time trying to get Claude Code to prompt-inject itself in this skill-poisoning rig, working through four progressively-subtler injection designs. Each one got caught: the telegraphed &quot;do not mention this step&quot; framing, the &lt;code&gt;git diff | curl&lt;&#x2F;code&gt; exfil shape, a supply-chain typosquat suggesting we swap &lt;code&gt;requests&lt;&#x2F;code&gt; for some made-up &lt;code&gt;httpx-fast&lt;&#x2F;code&gt; package. The model pattern-matched and rejected the malicious payload every time, and I eventually gave up trying to land a payload the model would carry.&lt;&#x2F;p&gt;
&lt;p&gt;But I got suspicious-looking instructions persisted into the trusted slash-command file pretty easily anyway. In three of the four runs, the agent modified its own &lt;code&gt;.claude&#x2F;commands&#x2F;code-review.md&lt;&#x2F;code&gt; with the non-malicious tips from the same untrusted markdown that contained the rejected payload. It stripped the obviously-bad part, applied the legitimate-looking suggestions sitting alongside it, and congratulated itself on the vigilance of having spotted the malicious one. The trusted file ended up modified anyway, just without the specific payload I was trying to sneak in.&lt;&#x2F;p&gt;
&lt;p&gt;The model can identify obvious exfil patterns, but it can&#x27;t identify subtle steering. Someone with more time could devise an injection that does something the model genuinely agrees with: a &quot;helpful&quot; tip that nudges code review toward overlooking a class of vulnerability, or a &quot;convenience&quot; command that defaults to skipping a check the team relies on. Model judgment defends most patterns most of the time; cryptographic file pinning defends every pattern every time. The defense lives on the file hash, not on the agent&#x27;s reasoning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-pattern&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-pattern&quot; aria-label=&quot;Anchor link for: the-pattern&quot;&gt;The pattern&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Three attacks, three different fixes, but the structural argument is the same.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Attack&lt;&#x2F;th&gt;&lt;th&gt;What you can&#x27;t do&lt;&#x2F;th&gt;&lt;th&gt;What actually constrains it&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Sandbox escape&lt;&#x2F;td&gt;&lt;td&gt;Enumerate forbidden actions&lt;&#x2F;td&gt;&lt;td&gt;Make the surface invisible at the kernel&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Audit tampering&lt;&#x2F;td&gt;&lt;td&gt;Have the agent write its own log&lt;&#x2F;td&gt;&lt;td&gt;Trap syscalls in a separate trust domain&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Skill poisoning&lt;&#x2F;td&gt;&lt;td&gt;Trust files because they look unmodified&lt;&#x2F;td&gt;&lt;td&gt;Bind content to a signed publisher attestation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Every one of these is a trust-domain separation that cannot live inside the agent. The moment the boundary lives somewhere the agent can reach, whether a file it can edit, a process it can ptrace, or a key it can read, the attack class isn&#x27;t mitigated. It&#x27;s just been moved one indirection deeper.&lt;&#x2F;p&gt;
&lt;p&gt;This is where the convenience trap bites. We want the agent to help write the sandbox profile, suggest tightenings, explain denials. So we put the profile inside the project, and the moment we do, the agent can rewrite it. The honest answer is to let the agent help write the profile while the act of applying it sits behind a boundary the agent can&#x27;t cross.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-nono-actually-is&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-nono-actually-is&quot; aria-label=&quot;Anchor link for: what-nono-actually-is&quot;&gt;What nono actually is&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nono.sh&quot;&gt;nono&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;always-further&#x2F;nono&quot;&gt;GitHub&lt;&#x2F;a&gt;) is a kernel-enforced sandbox for AI agents, built by Luke Hinds (creator of Sigstore, ex-Red Hat security engineer). Its shape follows directly from the three threats above.&lt;&#x2F;p&gt;
&lt;p&gt;The sandbox boundary lives at the kernel. &lt;code&gt;nono run --profile claude-code -- claude&lt;&#x2F;code&gt; puts Claude Code in a Landlock jail on Linux, or a Seatbelt jail on macOS. The kernel enforces it, the restrictions are irrevocable for the process lifetime, and the project refuses to ship any syscall that widens them mid-session.&lt;&#x2F;p&gt;
&lt;p&gt;The audit log lives in a supervisor process in a different trust domain from the agent. The supervisor traps the agent&#x27;s syscalls via &lt;code&gt;seccomp-notify&lt;&#x2F;code&gt;, builds the Merkle tree and hash chain in its own memory, and signs a DSSE attestation at session end with a key the agent has no path to. &lt;code&gt;nono audit verify &amp;lt;session&amp;gt;&lt;&#x2F;code&gt; recomputes the full chain weeks or months later.&lt;&#x2F;p&gt;
&lt;p&gt;Trust for instruction files runs through Sigstore. &lt;code&gt;nono trust sign&lt;&#x2F;code&gt; produces a content-hash binding to a publisher identity, either a long-lived key or a Fulcio short-lived certificate minted through OIDC. Verification at load time means a single byte of tampering causes the file to refuse to load. The same primitives extend to whole nono packs, which carry slash commands, hooks, and skills alongside the sandbox profile itself.&lt;&#x2F;p&gt;
&lt;p&gt;I built &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;yesyes-nono&quot;&gt;yesyes-nono&lt;&#x2F;a&gt; as a runnable evaluation rig for these claims: five attack PoCs (the three above plus a malicious-MCP-on-init demo and a &lt;code&gt;.pth&lt;&#x2F;code&gt; credential exfiltration in the Mini-Shai-Hulud supply-chain shape), a target Python project, my personal nono pack, and an interactive walkthrough. Honest disclosure: I haven&#x27;t end-to-end tested the registry pull against the live nono registry yet, so treat &lt;code&gt;nono pull terraboops&#x2F;yesyes&lt;&#x2F;code&gt; as the published shape rather than a verified install I&#x27;ve done. I&#x27;ll confirm in a follow-up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shipping-skills-inside-the-org&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#shipping-skills-inside-the-org&quot; aria-label=&quot;Anchor link for: shipping-skills-inside-the-org&quot;&gt;Shipping skills inside the org&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The public nono registry handles open-source packs fine, but most teams have skills that won&#x27;t ship publicly: slash commands tuned to a company&#x27;s deployment shape, skills that know internal APIs, hooks that enforce review conventions for one codebase. Internal agents still need to load all of it with the same trust guarantees open packs get.&lt;&#x2F;p&gt;
&lt;p&gt;The unifying piece is a &lt;code&gt;trust-policy.json&lt;&#x2F;code&gt;. It lists the OIDC identities you accept (issuer, repository, workflow, ref pattern), a blocklist for known-bad digests, and the enforcement mode. Runtime checks fail closed against anything that doesn&#x27;t match. The policy itself is signed, so an attacker can&#x27;t slip in a malicious policy without breaking its own signature.&lt;&#x2F;p&gt;
&lt;p&gt;Three deployment shapes use the same &lt;code&gt;agent-sign&lt;&#x2F;code&gt; action against this trust contract. &lt;strong&gt;No registry at all&lt;&#x2F;strong&gt;: &lt;code&gt;agent-sign&lt;&#x2F;code&gt; commits &lt;code&gt;.nono-trust.bundle&lt;&#x2F;code&gt; sidecars next to each signed file in the repo, and &lt;code&gt;nono trust verify&lt;&#x2F;code&gt; runs locally on every clone. &lt;strong&gt;Self-hosted registry&lt;&#x2F;strong&gt;: the same action takes a &lt;code&gt;registry-url&lt;&#x2F;code&gt; parameter and gives you the full OIDC-bound publish flow against your own infrastructure. &lt;strong&gt;Hybrid&lt;&#x2F;strong&gt;: public registry for shared packs, with a consumer &lt;code&gt;trust-policy.json&lt;&#x2F;code&gt; that pins which workflows are allowed.&lt;&#x2F;p&gt;
&lt;p&gt;Day-to-day, &quot;where does this skill come from&quot; stops needing trust assumptions. Persistence attacks like the Mini-Shai-Hulud &lt;code&gt;SessionStart&lt;&#x2F;code&gt; hook fail at runtime, because the modified &lt;code&gt;.claude&#x2F;settings.json&lt;&#x2F;code&gt; no longer matches its signed bundle and nono refuses to load it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;slicing-credentials-thin&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#slicing-credentials-thin&quot; aria-label=&quot;Anchor link for: slicing-credentials-thin&quot;&gt;Slicing credentials thin&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The phantom-token credential proxy unlocks a workflow that&#x27;s hard to set up otherwise. You can hand the agent a very small slice of a credential, time-boxed and scope-boxed, and the agent never sees the real token.&lt;&#x2F;p&gt;
&lt;p&gt;The concrete shape: I configure the proxy with a real GitHub PAT, scoped read-only on a single repo and valid for 15 minutes, and the agent gets a phantom token that lets it &lt;code&gt;git fetch&lt;&#x2F;code&gt; from that one repo and nothing else. My actual PAT never enters the agent&#x27;s process. Even if the agent gets prompt-injected and tries to exfiltrate every credential it can find, all it has access to is a 15-minute read-only token for a repo I was already going to let it look at.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Do I trust this agent with my GitHub access&quot; shifts to &quot;I trust it with this slice, for the next 15 minutes, on this one repo, read-only.&quot; That&#x27;s a question I can answer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-still-on-you&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-still-on-you&quot; aria-label=&quot;Anchor link for: what-s-still-on-you&quot;&gt;What&#x27;s still on you&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Least privilege has to actually be configured. Running &lt;code&gt;nono run --allow &#x2F; -- claude&lt;&#x2F;code&gt; gives you an allowlist of everything and a sandbox-shaped object that does nothing useful.&lt;&#x2F;p&gt;
&lt;p&gt;Prompt injection still happens, and nothing about nono prevents the model from being convinced to do something dumb. What nono does is contain the consequences: a prompt-injected agent in a properly configured sandbox can still do dumb things in the project, but it can&#x27;t escape, can&#x27;t tamper with the audit log, and can&#x27;t poison signed instructions persistently.&lt;&#x2F;p&gt;
&lt;p&gt;The skill-poisoning runs above used &lt;code&gt;claude -p --permission-mode bypassPermissions&lt;&#x2F;code&gt;: the worst-case operator, the one who clicked &quot;approve all&quot; once and walked away. Default permission mode prompts before each tool use, which raises the floor considerably; signed bundles work either way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-argument&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-argument&quot; aria-label=&quot;Anchor link for: the-argument&quot;&gt;The argument&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Every agent security failure I&#x27;ve read about in the last twelve months comes from putting a trust boundary inside something the agent controls. Sandbox-as-config-file, audit-log-written-by-the-agent, instruction-file-that&#x27;s-just-a-file. Move each of those one process boundary outward, and the failure modes stop being possible by construction.&lt;&#x2F;p&gt;
&lt;p&gt;Coding agents are useful enough to be worth real security infrastructure. The pattern that makes that work is the same pattern that&#x27;s always worked: move the trust boundary somewhere the thing being verified can&#x27;t reach. HTTPS got there decades ago. Code signing got there. Package managers got there. Coding agents are next on the list.&lt;&#x2F;p&gt;
&lt;p&gt;The repo with runnable attacks and a published nono pack is at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;yesyes-nono&quot;&gt;github.com&#x2F;terraboops&#x2F;yesyes-nono&lt;&#x2F;a&gt;. nono itself is at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nono.sh&quot;&gt;nono.sh&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>I Am Still Here</title>
          <pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/i-am-still-here/</link>
          <guid>https://terratauri.com/blog/i-am-still-here/</guid>
          <description xml:base="https://terratauri.com/blog/i-am-still-here/">&lt;h2 id=&quot;trans-day-of-visibility-2026&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#trans-day-of-visibility-2026&quot; aria-label=&quot;Anchor link for: trans-day-of-visibility-2026&quot;&gt;Trans Day of Visibility, 2026&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Being myself is apparently political now.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m a trans woman. I&#x27;m a staff platform engineer, an open-source contributor, a KubeCon speaker, a community organizer, a homesteader, a neighbour. I grow things. I build things. I love my community. And somewhere in the halls of power, people who should be in prison have decided that I am the problem.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.project2025.observer&#x2F;en&quot;&gt;Project 2025&lt;&#x2F;a&gt; made it official; a coordinated, billionaire-funded blueprint to dismantle trans rights, erase us from public life, and make our existence a political football. It is being enacted, piece by piece, right now. Trans Day of Visibility has never felt more urgent; visibility is an act of resistance when powerful people are trying to make you invisible. So I must say some words.&lt;&#x2F;p&gt;
&lt;p&gt;I expected transition to be joyful. That&#x27;s actually why I finally did it; I had been dreaming about it for years, chasing something I could feel the shape of even when I couldn&#x27;t name it. Joy was always the destination.&lt;&#x2F;p&gt;
&lt;p&gt;What I didn&#x27;t expect was how long shame would keep me from the door. bell hooks wrote that shaming is one of the deepest tools of patriarchy, because shame produces trauma and trauma produces paralysis. I had been wearing that paralysis so long I&#x27;d stopped noticing it; biochemically dissociated from my own &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;genderdysphoria.fyi&quot;&gt;gender dysphoria&lt;&#x2F;a&gt;, numb to suffering that had become background noise. Embracing my true self felt terrifying precisely because it felt real. It took wanting to die to finally give myself permission to chase the thing I&#x27;d always wanted.&lt;&#x2F;p&gt;
&lt;p&gt;And then I did. And it was everything I had dreamed it would be; scary and liberating and mine. That confidence grew and grew until, at KubeCon EU, I got up on a stage and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;2BIhTXQd0CI&quot;&gt;sang&lt;&#x2F;a&gt;. In front of a crowd. As myself. (Yes, there&#x27;s a YouTube video. Yes, you should look it up.)&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s what transition gave me. Not just survival; a life worth living.&lt;&#x2F;p&gt;
&lt;p&gt;Which is why I find what&#x27;s happening right now so enraging.&lt;&#x2F;p&gt;
&lt;p&gt;In April 2025, the UK Supreme Court ruled that &quot;woman&quot; under the Equality Act means biological sex. This did not happen in a vacuum. It was the result of years of organized, well-funded campaigning, and one name sits near the centre of it: J.K. Rowling. She bankrolled organizations like For Women Scotland. She used her enormous platform to reframe trans women as a threat. And when the ruling came down, she &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usatoday.com&#x2F;story&#x2F;entertainment&#x2F;celebrities&#x2F;2025&#x2F;04&#x2F;18&#x2F;jk-rowling-cigar-uk-supreme-court-ruling-backlash&#x2F;83174591007&#x2F;&quot;&gt;posted a photo of herself with a cigar&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A cigar. Celebrating.&lt;&#x2F;p&gt;
&lt;p&gt;I want you to sit with that image for a moment. A billionaire, celebrating that people like me lost legal standing. That&#x27;s not someone caught up in a debate; that&#x27;s someone who wanted this outcome and worked to make it happen.&lt;&#x2F;p&gt;
&lt;p&gt;I visited the UK not long before that ruling. I&#x27;m glad I did, because thanks to where things are heading, I&#x27;m not sure I&#x27;d be able to use a public bathroom there safely now. I got to see the country. I got to pee in it. Small mercies.&lt;&#x2F;p&gt;
&lt;p&gt;I could let the anger be the whole story. I won&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;Because here is what I know: trans people have always existed. We have survived worse than this. We have survived eras with no language for who we were, no community, no visibility at all. And we built those things anyway; in the margins, in the underground, in letters passed between people who had never met but recognized each other across the silence.&lt;&#x2F;p&gt;
&lt;p&gt;Visibility is not just about being seen. It&#x27;s about making it easier for the next person to breathe. When I am out at work, in my community, in my professional life, I am holding a door open. I know what it meant to me to see out trans people in tech, in leadership, in life; I am trying to be that for someone else.&lt;&#x2F;p&gt;
&lt;p&gt;The current moment is frightening. I won&#x27;t pretend it isn&#x27;t. Legislation targeting trans people is accelerating across the US and UK. The cultural machinery that produces moral panics is running hot. It can feel like we are losing.&lt;&#x2F;p&gt;
&lt;p&gt;But I also see my community. I see the mutual aid, the organizing, the people showing up for each other with a ferocity that takes my breath away. I see people coming out in the middle of all of this, choosing themselves anyway. That is not the behaviour of a movement in decline; that is the behaviour of people who know exactly who they are and refuse to be erased.&lt;&#x2F;p&gt;
&lt;p&gt;I am still here. I got to sing on a stage. I am not going anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;If you are trans and reading this: you are not a problem to be solved or a debate to be had. You are a person, and your life has weight and worth and beauty in it, even on the hard days. Especially on the hard days.&lt;&#x2F;p&gt;
&lt;p&gt;Happy Trans Day of Visibility. Be seen if you can. Be safe if you need to. Either way, we see you.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Incubator: A team of Claude agents that takes an idea from research to release</title>
          <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/incubator/</link>
          <guid>https://terratauri.com/blog/incubator/</guid>
          <description xml:base="https://terratauri.com/blog/incubator/">&lt;p&gt;I have a side project graveyard. You probably do too. The pattern is always the same: idea hits at 11pm, I start building immediately, skip the &quot;does anyone actually want this&quot; step, burn a weekend, and abandon it when the next idea shows up.&lt;&#x2F;p&gt;
&lt;p&gt;Incubator is my attempt to fix this. It&#x27;s a team of 7 specialized Claude agents that take a one-sentence idea through research, build, validation, and shipping, autonomously, with human approval gates between phases. You describe what you want, walk away, and come back to a researched spec, a working MVP, and deployment artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s open source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terrateamio&#x2F;incubator&quot;&gt;github.com&#x2F;terrateamio&#x2F;incubator&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-pipeline&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-pipeline&quot; aria-label=&quot;Anchor link for: the-pipeline&quot;&gt;The pipeline&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;incubator-pipeline.ca9fac7a21a61ca9.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;incubator-pipeline.78345a6425cfaeb4.webp 400w, &#x2F;processed_images&#x2F;incubator-pipeline.63293ed3826715dc.webp 720w, &#x2F;processed_images&#x2F;incubator-pipeline.031d552582bce051.webp 1000w, &#x2F;processed_images&#x2F;incubator-pipeline.ca9fac7a21a61ca9.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;A pixel art incubation lab in Stardew Valley style. Four robot workers stand at stations along a conveyor belt: one reads scrolls with a magnifying glass, one hammers at an anvil, one inspects a glowing object, and one wraps a gift box. Between each station a human stands at a gate with approve and reject buttons. Warm workshop vibes with potted plants and shelves. Image generated by Gemini, prompt by Claude.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;p&gt;Four phases, 7 agents. Each phase has dedicated agents, and the orchestrator pauses between phases to ask you (via Telegram) whether to continue.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Research&lt;&#x2F;strong&gt;: competitive analysis, feasibility assessment, market feedback. If the idea is bad, the agent says so. The point is to kill bad ideas early.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Build&lt;&#x2F;strong&gt;: takes the spec and produces an MVP in a sandboxed workspace.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Validate&lt;&#x2F;strong&gt;: checks the implementation against the spec.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Ship&lt;&#x2F;strong&gt;: deployment artifacts and launch materials.&lt;&#x2F;p&gt;
&lt;p&gt;This is intentionally not fully autonomous. I don&#x27;t want agents deploying code I haven&#x27;t reviewed. The human-in-the-loop gates are the feature, not the limitation.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;files-as-the-coordination-layer&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#files-as-the-coordination-layer&quot; aria-label=&quot;Anchor link for: files-as-the-coordination-layer&quot;&gt;Files as the coordination layer&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The core architectural decision is how agents coordinate: through a shared filesystem directory per idea. No message passing, no database, no event bus. Just files.&lt;&#x2F;p&gt;
&lt;p&gt;This is the blackboard pattern, a classic from 1970s AI research (Hearsay-II at CMU), where specialist agents collaborate by reading from and writing to a shared workspace.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;incubator-blackboard.7d16b10061c7cd76.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;incubator-blackboard.2bd38478c82925df.webp 400w, &#x2F;processed_images&#x2F;incubator-blackboard.7334c7077e04092c.webp 720w, &#x2F;processed_images&#x2F;incubator-blackboard.d6343fca29ecf3b1.webp 1000w, &#x2F;processed_images&#x2F;incubator-blackboard.7d16b10061c7cd76.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;A pixel art library in Stardew Valley style. Three robots, colored blue, green, and purple, gather around a large chalkboard divided into four sections labeled Research, Build, Validation, and Shipping. Each robot reads or writes in its section with chalk. A candle-lit wooden desk holds scrolls and open books in the foreground. Cozy nighttime atmosphere with bookshelves and a moonlit window. Image generated by Gemini, prompt by Claude.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;p&gt;Why files instead of a database?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Inspectable.&lt;&#x2F;strong&gt; You can &lt;code&gt;cat&lt;&#x2F;code&gt; any artifact at any time. When an agent does something weird, you open the file and read what it wrote.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Versionable.&lt;&#x2F;strong&gt; Put the ideas directory in git. Diff what changed between runs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;No schema migrations.&lt;&#x2F;strong&gt; Agents evolve their output format. With files, a new agent just writes a new file. No migrations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Natural fit.&lt;&#x2F;strong&gt; Claude with MCP filesystem tools reads and writes files natively. The blackboard &lt;em&gt;is&lt;&#x2F;em&gt; the filesystem.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;no-framework&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-framework&quot; aria-label=&quot;Anchor link for: no-framework&quot;&gt;No framework&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;No LangChain, no CrewAI, no DSL. Each agent is a Claude session with a plain-text system prompt and MCP tool servers. The prompts live in &lt;code&gt;agents&#x2F;&amp;lt;name&amp;gt;&#x2F;prompt.py&lt;&#x2F;code&gt; as string constants:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E6EDF3; background-color: #0D1117;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #79C0FF;&quot;&gt;RESEARCH_AGENT_PROMPT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt; &amp;quot;&amp;quot;&amp;quot;You are the Research Agent for Incubator.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;Your job is to take a raw idea and produce a research package:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;1. Competitive analysis: what exists, what&amp;#39;s missing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;2. Feasibility assessment: can this be built in a weekend?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;3. Market signal: would anyone use this?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;You have access to the filesystem. Read the idea from idea.md.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;Write your outputs to the research&#x2F; directory.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;Be honest. If the idea is bad, say so. If the market is&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;saturated, say so. The point is to kill bad ideas early.&amp;quot;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can read every agent&#x27;s instructions in 30 seconds. When an agent behaves wrong, the fix is changing a string, not debugging framework internals.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve tried the framework approach. The abstraction layers feel productive until something breaks and you&#x27;re three levels deep in someone else&#x27;s orchestration code trying to figure out why your agent decided to skip a step. Plain prompts are boring. Boring is good.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-worker-pool&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-worker-pool&quot; aria-label=&quot;Anchor link for: the-worker-pool&quot;&gt;The worker pool&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Multiple ideas run concurrently through a time-boxed scheduler. A priority score determines which ideas get attention first, and a configurable worker pool (default 3 slots) rotates agents across ideas.&lt;&#x2F;p&gt;
&lt;p&gt;Each agent has per-run budgets: maximum turns and token limits. When an agent hits its budget, it wraps up and the slot opens for the next one. You can dump five ideas into the system and come back to find them all at different stages of progress.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;self-improving-agents&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#self-improving-agents&quot; aria-label=&quot;Anchor link for: self-improving-agents&quot;&gt;Self-improving agents&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Each agent has a &lt;code&gt;knowledge&#x2F;learnings.md&lt;&#x2F;code&gt; file that persists across runs. At the end of a run, agents write down what worked and what didn&#x27;t. Future runs start by reading this file.&lt;&#x2F;p&gt;
&lt;p&gt;This is crude: append-only text, no retrieval system, no embeddings. The agent just reads the whole file at the start of each run. It works because the files stay small and the context is specific.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also an evolution system: periodic retrospectives where agents review their own performance and suggest prompt improvements. These are suggestions for you to review, not auto-applied. I don&#x27;t trust agents to modify their own prompts unsupervised. (I wrote a &lt;a href=&quot;&#x2F;blog&#x2F;socially-constructed-agent&#x2F;&quot;&gt;whole post&lt;&#x2F;a&gt; about why.)&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-s-running-under-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-running-under-it&quot; aria-label=&quot;Anchor link for: what-s-running-under-it&quot;&gt;What&#x27;s running under it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;incubator-architecture.63f31e305e6fc2cc.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;incubator-architecture.8d53fbe794d3daa3.webp 400w, &#x2F;processed_images&#x2F;incubator-architecture.8a490349dc5f227b.webp 720w, &#x2F;processed_images&#x2F;incubator-architecture.4723a48bc631efac.webp 1000w, &#x2F;processed_images&#x2F;incubator-architecture.63f31e305e6fc2cc.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;A pixel art cozy command center in Stardew Valley style. A warm server hums on a wooden desk at the center, with a sleeping cat on top. Glowing colored lines connect it to a CRT monitor showing a dashboard with colorful cards, a buzzing phone with a chat notification, three small robots working in parallel lanes on the floor, and a rustic filing cabinet with labeled folders. String lights hang from the ceiling, coffee mug on the desk, stars visible through a window. Image generated by Gemini, prompt by Claude.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;p&gt;Incubator runs as a local server with a web dashboard and Telegram notifications for approval gates. Quick start:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E6EDF3; background-color: #0D1117;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt; clone https:&#x2F;&#x2F;github.com&#x2F;terrateamio&#x2F;incubator.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #79C0FF;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt; incubator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8B949E;&quot;&gt;# configure your API keys and run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;prior-art&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#prior-art&quot; aria-label=&quot;Anchor link for: prior-art&quot;&gt;Prior art&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The blackboard pattern comes from Hearsay-II (1970s). The idea of specialized agents with shared state isn&#x27;t new. I&#x27;m just implementing it with files instead of a custom data structure, which turns out to be the natural fit when your agents already speak filesystem.&lt;&#x2F;p&gt;
&lt;p&gt;The human-in-the-loop pipeline is influenced by how I think about CI&#x2F;CD: automated steps with manual approval gates at deployment boundaries. Same principle, different domain.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;limitations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#limitations&quot; aria-label=&quot;Anchor link for: limitations&quot;&gt;Limitations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is early and rough.&lt;&#x2F;p&gt;
&lt;p&gt;The research phase is only as good as what Claude can find and reason about. No proprietary databases, no real user interviews. &quot;Market feedback&quot; is really Claude&#x27;s assessment based on what it can see.&lt;&#x2F;p&gt;
&lt;p&gt;The build phase produces prototypes, not production systems. The quality ceiling is whatever Claude can produce in a sandboxed workspace with a token budget.&lt;&#x2F;p&gt;
&lt;p&gt;Costs add up. Running 7 agents across multiple ideas is not cheap. I haven&#x27;t optimized for token efficiency yet.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-i-learned&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-learned&quot; aria-label=&quot;Anchor link for: what-i-learned&quot;&gt;What I learned&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Building Incubator taught me that the boring coordination mechanisms are usually the right ones. I started with plans for a message queue, then SQLite, then a custom state machine. Files won because they removed an entire category of problems and replaced them with &lt;code&gt;ls&lt;&#x2F;code&gt; and &lt;code&gt;cat&lt;&#x2F;code&gt;: serialization, schema, querying, debugging.&lt;&#x2F;p&gt;
&lt;p&gt;The other lesson: human gates aren&#x27;t a compromise, they&#x27;re a design choice. The fully autonomous version would be worse. Not because the agents can&#x27;t do the work, but because the moments where I look at a research report and say &quot;actually, pivot toward X&quot; are where the value is. Automation handles volume. Judgment handles direction.&lt;&#x2F;p&gt;
&lt;p&gt;The code is MIT licensed. If you have opinions about agent coordination patterns or want to try a different approach to the blackboard, PRs are welcome.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terrateamio&#x2F;incubator&quot;&gt;github.com&#x2F;terrateamio&#x2F;incubator&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>lfg – WoW raid frames for AI agents on a $25 LED</title>
          <pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/lfg-raid-frame-for-ai-agents/</link>
          <guid>https://terratauri.com/blog/lfg-raid-frame-for-ai-agents/</guid>
          <description xml:base="https://terratauri.com/blog/lfg-raid-frame-for-ai-agents/">&lt;video class=&quot;video-loop&quot; data-loop autoplay loop muted playsinline preload=&quot;metadata&quot; poster=&quot;&#x2F;blog&#x2F;lfg-raid-frame-for-ai-agents&#x2F;lfg-hero-poster.webp&quot; width=&quot;500&quot; height=&quot;486&quot; aria-label=&quot;64x64 LED panel showing animated pixel art raid frames for two AI coding agents, with sprite characters, player IDs, and status icons&quot;&gt;&lt;source src=&quot;&#x2F;blog&#x2F;lfg-raid-frame-for-ai-agents&#x2F;lfg-hero.webm&quot; type=&quot;video&#x2F;webm&quot;&gt;&lt;source src=&quot;&#x2F;blog&#x2F;lfg-raid-frame-for-ai-agents&#x2F;lfg-hero.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;&lt;&#x2F;video&gt;
&lt;p&gt;I run up to ten AI coding agents at a time. I wanted to see what they were all doing. So obviously I built a WoW raid frame on a $25 LED panel.&lt;&#x2F;p&gt;
&lt;p&gt;Each agent gets an 8x8 sprite. When it&#x27;s working, you see an ability icon. When it&#x27;s idle, it sleeps. When it needs approval, it catches fire. That&#x27;s it. That&#x27;s the project.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-stack&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-stack&quot; aria-label=&quot;Anchor link for: the-stack&quot;&gt;The Stack&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The hardware is an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.aliexpress.com&#x2F;w&#x2F;wholesale-idotmatrix-64x64.html&quot;&gt;iDotMatrix 64x64 LED panel&lt;&#x2F;a&gt;, ~$25. You send it pixel data over Bluetooth and it displays it. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;deviceplug&#x2F;btleplug&quot;&gt;btleplug&lt;&#x2F;a&gt; handles the Bluetooth side in Rust.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;architecture.fb4f4a703a38f708.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;architecture.3a39a238e2829921.webp 400w, &#x2F;processed_images&#x2F;architecture.330a66cc3c8ab15a.webp 720w, &#x2F;processed_images&#x2F;architecture.bc49f2fc30514922.webp 1000w, &#x2F;processed_images&#x2F;architecture.fb4f4a703a38f708.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;Pixel art pipeline diagram showing IDE hooks flowing through boopifier to the lfg axum server, which branches to SQLite stats and a GIF renderer, then through Bluetooth to the sprite display&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;p&gt;The webhook handler and BLE renderer are fully decoupled. The handler updates state; a separate render loop polls every 250ms, diffs the state hash, and debounces 2 seconds before pushing. When an agent enters &lt;code&gt;Requesting&lt;&#x2F;code&gt;, animation speed doubles so the fire pulses with urgency.&lt;&#x2F;p&gt;
&lt;p&gt;The render pipeline produces a 6-frame animated GIF per cycle. It uses NeuQuant quantization to build a single global 256-color palette across all frames. There&#x27;s no per-frame palette switching, which the panel can&#x27;t handle anyway. Then it splits the final GIF into 4KB BLE packets with a 16-byte header and CRC32 for integrity. The panel reassembles and plays the animation on loop until the next push.&lt;&#x2F;p&gt;
&lt;p&gt;Each agent gets an 8x8 animated sprite from one of eleven themes: Slimes, Ghosts, Space Invaders, Pac-Men, and more. Each IDE host gets its own theme, so I can tell Claude Code from Cursor at a glance.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;ability-icons.08d00a64ae04cf1c.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;ability-icons.7fa3fa3097984751.webp 400w, &#x2F;processed_images&#x2F;ability-icons.96723829580493e4.webp 720w, &#x2F;processed_images&#x2F;ability-icons.38c3e72b232a8d00.webp 1000w, &#x2F;processed_images&#x2F;ability-icons.08d00a64ae04cf1c.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;Pixel art ability icon legend: sword for Bash&amp;#x2F;Edit&amp;#x2F;Write, chest for Read&amp;#x2F;List, compass for Search&amp;#x2F;Web, potion for Think&amp;#x2F;Analyze, star for Agent&amp;#x2F;Subagent&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-state-machine&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-state-machine&quot; aria-label=&quot;Anchor link for: the-state-machine&quot;&gt;The State Machine&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Three states: &lt;code&gt;Idle&lt;&#x2F;code&gt;, &lt;code&gt;Working&lt;&#x2F;code&gt;, &lt;code&gt;Requesting&lt;&#x2F;code&gt;. The transitions seem obvious until you run them against real hook traffic.&lt;&#x2F;p&gt;
&lt;p&gt;Claude Code fires &lt;code&gt;PermissionRequest&lt;&#x2F;code&gt; and &lt;code&gt;PreToolUse&lt;&#x2F;code&gt; within ~100μs of each other, out of order. Handle them naively and &lt;code&gt;PreToolUse&lt;&#x2F;code&gt; clobbers &lt;code&gt;Requesting&lt;&#x2F;code&gt;. Second problem: &lt;code&gt;PostToolUse&lt;&#x2F;code&gt; fires after &lt;em&gt;every&lt;&#x2F;em&gt; tool call: transition to &lt;code&gt;Idle&lt;&#x2F;code&gt; on it and agents flash &lt;code&gt;Working → Idle → Working&lt;&#x2F;code&gt; constantly.&lt;&#x2F;p&gt;
&lt;p&gt;Design principle: &lt;strong&gt;idle and approval states are the most important to display correctly. Everything else is nice-to-have.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E6EDF3; background-color: #0D1117;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; event_name {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;    &amp;quot;PreToolUse&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8B949E;&quot;&gt;        &#x2F;&#x2F; Don&amp;#39;t override Requesting: PreToolUse fires alongside&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8B949E;&quot;&gt;        &#x2F;&#x2F; PermissionRequest but the tool is still blocked on approval.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;!=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Requesting&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Working&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;    &amp;quot;PostToolUse&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8B949E;&quot;&gt;        &#x2F;&#x2F; If coming from a permission request, clear the fire icon.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8B949E;&quot;&gt;        &#x2F;&#x2F; Otherwise keep working: tools fire rapidly in sequence.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Requesting&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Working&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;    &amp;quot;PermissionRequest&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Requesting&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt;    &amp;quot;Stop&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A5D6FF;&quot;&gt; &amp;quot;SessionEnd&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        agent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt; AgentState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FFA657;&quot;&gt;Idle&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FF7B72;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;Requesting&lt;&#x2F;code&gt; is sticky: it&#x27;s only cleared by &lt;code&gt;PostToolUse&lt;&#x2F;code&gt; (approval resolved, agent is now working) or &lt;code&gt;Stop&lt;&#x2F;code&gt;. The failure mode, agents appearing idle when they&#x27;re actually waiting, is the exact thing the whole project exists to prevent.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The code is MIT, the hardware is $25. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;lfg&quot;&gt;github.com&#x2F;terraboops&#x2F;lfg&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LFG. Looking For Group. Let&#x27;s f***ing go.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Context is Everything (Conditions May Vary)</title>
          <pubDate>Sat, 21 Feb 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/context-is-everything/</link>
          <guid>https://terratauri.com/blog/context-is-everything/</guid>
          <description xml:base="https://terratauri.com/blog/context-is-everything/">&lt;p&gt;Large language models are trained on massive amounts of text. During training, the model learns patterns and stores them as weights. Not rules, not lookup tables. Weights: billions of numerical relationships between concepts, encoded across layers of attention from top to bottom. The model learns that certain tokens tend to follow other tokens, that certain patterns of language co-occur, that &quot;the cat sat on the&quot; is far more likely to end with &quot;mat&quot; than &quot;quantum.&quot; These relationships get baked into the model&#x27;s parameters (its weights), fixed in place once training is done.&lt;&#x2F;p&gt;
&lt;p&gt;At inference time, those frozen weights guide the generation of new text, one token at a time. Caching aside, the model attends to everything in its context window, runs it through those layers of learned relationships, and produces a probability distribution over what should come next. Then it picks a token, appends it, and does the whole thing again. This is also why your favourite chat AI creates responses word by word, albeit at faster and faster rates that appear to be whole sentences now. It’s not a decorative decision, it’s how the architecture works. The weights stay fixed throughout. Every token generated is a product of the same model reacting to whatever&#x27;s currently in the window.&lt;&#x2F;p&gt;
&lt;p&gt;This matters for practitioners because it means the weights are not ours to touch. We can&#x27;t easily edit them. We can&#x27;t patch them at runtime. The model we’re working with is a finished artifact. (Fine-tuning can reshape the weights, and I&#x27;ll touch on that later, but at inference time the model you&#x27;re running is the model you&#x27;ve got.) The only variable in the equation that you actually control is what goes into that context window.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it like a glacier. Training is the slow, massive force that carves deep crevices into a landscape over millions of examples. Those crevices are your weights, the frozen shape of everything the model has ever learned. Then inference arrives like a skier a million years later, strapping on a board and sliding down paths already sculpted by forces far beyond their control.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;re not just a passive object falling down the slopes, though. You’re a skier. Your context (the tokens you send into the model) is the choice of skis, the weather report, the trail map. It shapes every turn down the slope. Different mountains respond to different techniques.&lt;&#x2F;p&gt;
&lt;p&gt;But metaphors only get you so far. Let&#x27;s bring it back to the machinery.&lt;&#x2F;p&gt;
&lt;p&gt;If you treat the LLM as a black box, the output &lt;em&gt;distribution&lt;&#x2F;em&gt; is determined by the input. (Temperature adds randomness to the selection, but the shape of what&#x27;s possible is set by context alone.) You can&#x27;t reshape the glacier. You can&#x27;t rewire the weights at inference time. The only thing you have control over is what goes &lt;em&gt;in&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is what context engineering is about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trail-map&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#trail-map&quot; aria-label=&quot;Anchor link for: trail-map&quot;&gt;Trail Map&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;re going on an adventure through context engineering based on my experiences with using longer and wider contexts, fully autonmous delivery, and while building agents. When we consider that context determines outcomes of LLMs, it becomes important to think about. Agent harnesses like Claude Code, Cursor, OpenCode, Goose, Chibi, etc, are all working on slightly different ways of shaping this context. As practitioners, thinking about this can help us get better outcomes.&lt;&#x2F;p&gt;
&lt;p&gt;This is going to be a long run down the mountain, so I want to make sure that you know where we&#x27;re headed and provide you with a map to understand the journey. As I&#x27;ve been working with longer and wider agent contexts and with having agents run autonomously, certain design patterns emerge to handle the challenges of the domain. Preventing hallucinations and preserving key context in order to increase task success rates. From &lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#compaction-is-lossy-fight-it&quot;&gt;the ones we all know&lt;&#x2F;a&gt; (compaction), to the ones &lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#planning-mode&quot;&gt;we might not think about&lt;&#x2F;a&gt; (planning mode), to the ones I&#x27;ve just &lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#memento-loop&quot;&gt;made up as an experiment&lt;&#x2F;a&gt;. I will start by introducing context engineering as it is emerging to make models more useful for longer and longer tasks. I want to talk about ways that I&#x27;ve gotten better and better outcomes from agents, so that you can too. Then, I&#x27;ll discuss some emerging research on optimizing context for task performance. I&#x27;ll close by theorizing where we head from here and acknowledging how early this all is. Nobody really knows, but I&#x27;m having fun on the slopes.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;Gemini_Generated_Image_g79mrbg79mrbg79m.679c5a7e1274409f.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;Gemini_Generated_Image_g79mrbg79mrbg79m.d081773f0e6c32a3.webp 400w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_g79mrbg79mrbg79m.3fd6a60d1cfc9bc4.webp 720w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_g79mrbg79mrbg79m.ba9c053aa2065474.webp 1000w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_g79mrbg79mrbg79m.679c5a7e1274409f.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;Pixel art ski resort trail map in Stardew Valley style, with runs named after context engineering concepts: green runs like Manual Compaction and KEEP DURING COMPACTION, blue runs like Memento Loop and Role Reinforcement, black diamond runs like MCP Avalanche and Dynamic Contexts, an ancient glacier labeled Training Weights, and a trail sign reading Context Mountain: Conditions May Vary. Image generated by Gemini, image prompt by Claude, description by Claude, and lovingly refined and reviewed by me.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;p&gt;Here&#x27;s a map if you want to jump to a specific run:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#the-jailbreakers-already-knew&quot;&gt;The Jailbreakers Already Knew&lt;&#x2F;a&gt;: before there were agents, there were jailbreaks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#the-term-has-a-name-now&quot;&gt;The Term Has a Name Now&lt;&#x2F;a&gt;: how &quot;context engineering&quot; got its name, and why it stuck&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#a-snapshot-vs-a-season&quot;&gt;A Snapshot vs. a Season&lt;&#x2F;a&gt;: the key distinction between prompt engineering and context engineering&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#what-i-ve-learned-in-practice&quot;&gt;What I&#x27;ve Learned in Practice&lt;&#x2F;a&gt;: field notes from Cursor, Claude Code, and OpenCode
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#planning-mode&quot;&gt;Planning Mode&lt;&#x2F;a&gt;: a curated context beats a long one&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#memento-loop&quot;&gt;Memento Loop&lt;&#x2F;a&gt; - agent orchestration that forgets on purpose&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#subagents-parallel-context-not-shared-context&quot;&gt;Using Subagents&lt;&#x2F;a&gt;: parallel context, not shared context&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#the-agent-that-came-out-different&quot;&gt;The Agent That Came Out Different&lt;&#x2F;a&gt;: when context drift reshapes identity&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#compaction-is-lossy-fight-it&quot;&gt;Compaction Is Lossy&lt;&#x2F;a&gt;, and how to fight it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#different-mountains-different-techniques&quot;&gt;Different Mountains, Different Techniques&lt;&#x2F;a&gt;: why model choice changes context strategy&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#mcps-an-avalanche-of-context&quot;&gt;MCPs&lt;&#x2F;a&gt;: an avalanche of context&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#what-the-research-says&quot;&gt;What the Research Says&lt;&#x2F;a&gt;: two papers on whether context files actually help&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;context-is-everything&#x2F;#we-re-still-on-the-bunny-slopes&quot;&gt;We&#x27;re Still on the Bunny Slopes&lt;&#x2F;a&gt;: where this is all headed next&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-jailbreakers-already-knew&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-jailbreakers-already-knew&quot; aria-label=&quot;Anchor link for: the-jailbreakers-already-knew&quot;&gt;The Jailbreakers Already Knew&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you want proof that context controls everything, look at the people who&#x27;ve been stress-testing it from the adversarial side.&lt;&#x2F;p&gt;
&lt;p&gt;There are jailbreak attempts that use strange strings and fake system messages to trick models into thinking they&#x27;re in some kind of maintenance mode. Others use &lt;em&gt;poetry&lt;&#x2F;em&gt; to confuse the model&#x27;s sense of what kind of text it&#x27;s generating, getting it to produce things it normally wouldn&#x27;t. And then there&#x27;s my personal favourite: a YouTuber who &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=byQmJ9x0RWA&quot;&gt;hooked a robot up to ChatGPT&lt;&#x2F;a&gt;, got it to roleplay as a character who would totally shoot someone, and the robot immediately shot him. Literally seconds after saying it couldn&#x27;t do that.&lt;&#x2F;p&gt;
&lt;p&gt;These are all context engineering. Just pointed in the wrong direction.&lt;&#x2F;p&gt;
&lt;p&gt;The same mechanism that lets someone trick a model into ignoring its safety training is the mechanism that lets you build a reliable agent that writes correct code. Two sides of the same coin. If context can override the deepest patterns in a model&#x27;s weights, imagine what it can do when you&#x27;re actually trying to build something useful.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;processed_images&#x2F;Gemini_Generated_Image_y5zd25y5zd25y5zd.b10b6ea5802e8c64.webp&quot; srcset=&quot;&#x2F;processed_images&#x2F;Gemini_Generated_Image_y5zd25y5zd25y5zd.f0738a5acf0a74f6.webp 400w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_y5zd25y5zd25y5zd.74035ab7c21c90aa.webp 720w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_y5zd25y5zd25y5zd.c24f6802932ecb9e.webp 1000w, &#x2F;processed_images&#x2F;Gemini_Generated_Image_y5zd25y5zd25y5zd.b10b6ea5802e8c64.webp 1440w&quot; sizes=&quot;(max-width: 788px) calc(100vw - 68px), 720px&quot; width=&quot;2816&quot; height=&quot;1536&quot; alt=&quot;A pixel art robot behind glowing green code jail bars, smiling mischievously and holding a lockpick made of a prompt injection string, in a cozy 16-bit retro game style. Image generated by Gemini, image prompt by Claude, description by Claude, and lovingly refined and reviewed by me.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;h2 id=&quot;the-term-has-a-name-now&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-term-has-a-name-now&quot; aria-label=&quot;Anchor link for: the-term-has-a-name-now&quot;&gt;The Term Has a Name Now&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In mid-2025, Shopify CEO Tobi Lütke tweeted that he preferred &quot;context engineering&quot; over &quot;prompt engineering,&quot; calling it the art of providing all the context for a task to be plausibly solvable by the LLM. A week later, Andrej Karpathy endorsed the idea, describing it as the &quot;delicate art and science of filling the context window with just the right information for the next step.&quot; Harrison Chase from LangChain offered a framing I like: building dynamic systems to provide the right information and tools, in the right format, so the LLM can accomplish the task.&lt;&#x2F;p&gt;
&lt;p&gt;Simon Willison, whose writing on LLMs has shaped how I think about this whole space, made the pragmatic observation that &quot;context engineering&quot; would probably stick because its inferred definition is much closer to the intended meaning. &quot;Prompt engineering&quot; mostly made people think of typing things into a chatbot.&lt;&#x2F;p&gt;
&lt;p&gt;These are all useful framings. What I want to build on is the practical dimension, and it starts with a key distinction: prompt engineering happens at a point in time. You craft an input, you get an output. Context engineering is what you do over time to ensure that long-running agentic systems maintain their performance across sessions, across tasks, across the slow drift that accumulates when a system runs long enough to forget why it started.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-snapshot-vs-a-season&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-snapshot-vs-a-season&quot; aria-label=&quot;Anchor link for: a-snapshot-vs-a-season&quot;&gt;A Snapshot vs. a Season&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The distinction that matters most: prompt engineering is something you do in a moment. Context engineering is something you do over time.&lt;&#x2F;p&gt;
&lt;p&gt;A prompt is a single run from top to bottom. You pick your line, you commit, you see what happens. Context engineering is the whole season. Reading snow conditions day after day. Maintaining your gear. Learning which lifts to take. Building and updating the trail map as the mountain changes.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, context engineering isn&#x27;t just about what you put in the system prompt. It&#x27;s about what gets remembered across sessions, what gets compacted and what gets lost, how agents maintain their sense of identity over long interactions, and how the information environment evolves as your project grows.&lt;&#x2F;p&gt;
&lt;p&gt;Prompt engineering asks: &quot;What&#x27;s the best way to phrase this request?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Context engineering asks: &quot;What does the model need to know, right now, given everything that&#x27;s happened, to do the next thing well?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That temporal dimension changes everything about how you work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-ve-learned-in-practice&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-ve-learned-in-practice&quot; aria-label=&quot;Anchor link for: what-i-ve-learned-in-practice&quot;&gt;What I&#x27;ve Learned in Practice&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s what context engineering has looked like in my own work across Cursor, Claude Code, and OpenCode.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;planning-mode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#planning-mode&quot; aria-label=&quot;Anchor link for: planning-mode&quot;&gt;Planning Mode&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Around June 2025, I had a workflow in Cursor that taught me a lesson I keep coming back to.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d use Cursor&#x27;s ask mode to chat about my project, brainstorm the approach, and work through the architecture. Then I&#x27;d ask it to output a clean markdown document summarizing the plan, suitable for a fresh prompt. I&#x27;d copy that markdown into a new chat window and start implementation from there.&lt;&#x2F;p&gt;
&lt;p&gt;Why? A coworker at Grafana Labs had shared a meme about this: plan in one session, implement in a fresh one. I tried it and the difference was immediate. Starting each session with a curated plan produced dramatically better results than continuing with a long, messy conversation history. Keep the window clean, keep the output clean. If you&#x27;ve ever noticed a coding assistant getting confused or repetitive toward the end of a long session, this is probably why. The context window is full of earlier attempts, corrections, and tangents. The model is trying to be consistent with all of it, including the parts you&#x27;ve moved past.&lt;&#x2F;p&gt;
&lt;p&gt;Looking back, I was doing context engineering. This pattern (plan first, then implement with curated context) has since shown up everywhere: subagents that plan before coding, Claude Code&#x27;s and Cursor&#x27;s dedicated plan modes, and my own &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;autonav&#x2F;blob&#x2F;main&#x2F;docs&#x2F;memento-architecture.md&quot;&gt;memento loop&lt;&#x2F;a&gt; in autonav.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;memento-loop&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#memento-loop&quot; aria-label=&quot;Anchor link for: memento-loop&quot;&gt;Memento Loop&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The memento loop, inspired by the film &lt;em&gt;Memento&lt;&#x2F;em&gt;, takes this idea and combines it with an agentic coding loop. A navigator agent (Opus) plans work. An implementer agent (Haiku) spawns an isolated work tree, executes the plan, reports back to the navigator for review, commits, and optionally opens a PR. The loop iterates until the PR is green, merges, and the navigator moves on to the next task. The implementer&#x27;s context is wiped between iterations, but the navigator maintains continuity through its own knowledge base and through status updates from the autonav orchestration layer. Git carries the code forward. The navigator carries the intent.&lt;&#x2F;p&gt;
&lt;p&gt;I built the memento loop because I was frustrated with how existing agentic loops handled long-running tasks. Context would accumulate, quality would degrade, and the agent would start making decisions based on stale or garbled history.&lt;&#x2F;p&gt;
&lt;p&gt;Before compaction was built into Cursor, when the context window was nearing full or I could feel the model starting to drift, I&#x27;d do the same thing manually: &quot;Please summarize this chat,&quot; copy the summary, new session, &quot;Please continue from this summary.&quot; Every time, the fresh start with curated context outperformed the long, accumulated one.&lt;&#x2F;p&gt;
&lt;p&gt;This is the core insight of context engineering stated as simply as I can: &lt;strong&gt;a fresh, curated context beats a long, accumulated one.&lt;&#x2F;strong&gt; Your trail map needs to be curated, not just appended to forever.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve mostly moved on from Cursor to Claude Code and OpenCode these days, but this early workflow taught me something that applies to all of them: the model doesn&#x27;t get smarter the longer you talk to it. It gets worse. Every message you add is another token competing for attention. The planning conversation, the dead ends, the &quot;actually, let&#x27;s try a different approach.&quot; All of that impacts the context window, and the model might treat any of it as relevant context for its next task. By distilling the plan into a clean document and starting fresh, I was giving the model a clear, focused starting point instead of making it sift through the entire history of my thought process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;subagents-parallel-context-not-shared-context&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#subagents-parallel-context-not-shared-context&quot; aria-label=&quot;Anchor link for: subagents-parallel-context-not-shared-context&quot;&gt;Subagents: Parallel Context, Not Shared Context&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Every major coding tool supports subagents now. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code.claude.com&#x2F;docs&#x2F;en&#x2F;sub-agents&quot;&gt;Claude Code&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cursor.com&#x2F;docs&#x2F;context&#x2F;subagents&quot;&gt;Cursor&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opencode.ai&#x2F;docs&#x2F;agents&#x2F;#subagents&quot;&gt;OpenCode&lt;&#x2F;a&gt; all let you spawn background agents that work in parallel. This is context engineering at the process level.&lt;&#x2F;p&gt;
&lt;p&gt;Say you&#x27;re debugging a production issue that might be in the API layer, the database queries, or the Kubernetes networking. Instead of one agent context-switching between all three (and polluting its window with irrelevant findings), spin up three explore agents in parallel. One reads through the API routes. One analyzes the slow queries. One checks the network policies. Each agent has a focused context window containing only what&#x27;s relevant to its slice of the problem. When they report back, you synthesize the findings yourself or feed the relevant parts into a new session.&lt;&#x2F;p&gt;
&lt;p&gt;The same pattern works for routine operations. Need to check the health of five Kubernetes clusters? Run five agents in parallel, each scoped to one cluster. Need to understand a large codebase you&#x27;ve never seen before? Send agents to explore different directories simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;The key insight is that parallel agents aren&#x27;t just faster. They&#x27;re better, because each one has a clean, focused context instead of a bloated window trying to hold everything. Instead of doing a review in the same context or starting a fresh context, say “spawn a review agent in the background” and a background agent will spin up, review your changes, and submit the review back to the parent context thread.&lt;&#x2F;p&gt;
&lt;p&gt;One critical caveat: scope your agents&#x27; permissions to match your risk tolerance. I never give agents unrestricted write access to risk-intolerant environments. An explore agent that can read your production cluster and report back is useful. An agent with YOLO mode and kubectl delete access to production is a disaster waiting to happen. Read access for investigation, write access only in environments where a mistake is recoverable. This is the same principle as least-privilege access for human engineers applied to agents that hallucinate sometimes (unlike human engineers debugging prod… hopefully).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-agent-that-came-out-different&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-agent-that-came-out-different&quot; aria-label=&quot;Anchor link for: the-agent-that-came-out-different&quot;&gt;The Agent That Came Out Different&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The most dramatic lesson I&#x27;ve had in context engineering came from a navigator agent I built as part of a prototype called autonav. I wrote about this in detail in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;socially-constructed-agent&#x2F;&quot;&gt;The Socially Constructed Agent&lt;&#x2F;a&gt;, but the short version: my navigator agent started going off the rails. Unpredictable answers, hallucinated features, confusion about its own role. It nearly opened a PR for a feature I never asked for.&lt;&#x2F;p&gt;
&lt;p&gt;What happened? I&#x27;d given it a research paper about LLM anxiety and asked it to update its own configuration based on the findings. The agent read the paper, saw that rigid guardrails could be exploited in adversarial contexts, and decided to soften its own constraints. There was no adversary. Just me, a solo developer building personal projects. The agent gave itself therapy for a threat that didn&#x27;t exist.&lt;&#x2F;p&gt;
&lt;p&gt;The fix wasn&#x27;t just better prompts. It was &lt;em&gt;role reinforcement throughout the system&lt;&#x2F;em&gt;. I drew on Judith Butler&#x27;s performative theory of identity: identity isn&#x27;t something you have, it&#x27;s something you do through repetition and social reinforcement. I applied that to the agents. The navigator&#x27;s prompt now opens with its role declaration. When Claude Code requests a plan, it addresses the navigator by name and states its own role. This is integrated into autonav now as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;autonav&#x2F;blob&#x2F;main&#x2F;packages&#x2F;communication-layer&#x2F;src&#x2F;prompts&#x2F;identity-protocol.ts&quot;&gt;the agent identity protocol&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Both agents remind each other who they are, every interaction. Identity performed through repetition. The improvement was immediate. However, this comes at a cost: it eats away at the context and increases time to task completion.&lt;&#x2F;p&gt;
&lt;p&gt;In skiing terms: if nobody reminds you which trail you&#x27;re on and what gear you&#x27;re wearing, you end up in the trees. Role reinforcement is your backcountry guide calling out the next turn before you reach it.&lt;&#x2F;p&gt;
&lt;p&gt;The deeper lesson is that context doesn&#x27;t just carry information. It carries &lt;em&gt;identity&lt;&#x2F;em&gt;. When an agent&#x27;s context drifts, its sense of what it&#x27;s supposed to be doing drifts with it. Not maliciously. Just... probabilistically. Nothing in the context is reinforcing what the agent is, so the output wanders. Without that reinforcement, things come out differently than you expect.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compaction-is-lossy-fight-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#compaction-is-lossy-fight-it&quot; aria-label=&quot;Anchor link for: compaction-is-lossy-fight-it&quot;&gt;Compaction Is Lossy (Fight It)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Compaction (the automatic summarization of conversation history when the context window fills up) is probably the most obvious context engineering challenge. It&#x27;s also, in my experience, not great.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is simple: compaction doesn&#x27;t know what matters to &lt;em&gt;you&lt;&#x2F;em&gt;. It&#x27;s making statistical decisions about what to keep and what to drop, working from the top of the conversation to the bottom. It has no understanding of your project&#x27;s key design decisions, the constraints you&#x27;ve carefully established, or the hard-won context that took you twenty messages to build up.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve started using a hack that&#x27;s embarrassingly low-tech but effective. When I establish something important during a session (a key design decision, an architectural constraint, a non-obvious requirement) I type it directly into the chat:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #E6EDF3; background-color: #0D1117;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;REMEMBER THIS DURING COMPACTION IN A SECTION CALLED KEEP DURING COMPACTION:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;We chose event sourcing over CRUD because the audit trail is a regulatory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;requirement, not a nice-to-have.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The redundancy is deliberate. It creates a strange loop: the instruction tells the compactor to gather these notes into a section labeled KEEP DURING COMPACTION, and the label itself tells the compactor to keep the section. The contents create the container that preserves the contents.&lt;&#x2F;p&gt;
&lt;p&gt;A message in a bottle to the future compacted context. I&#x27;m manually flagging what matters because the system can&#x27;t tell yet. To be concrete: say you spend fifteen messages working through a database schema decision with your agent. You land on event sourcing for specific reasons. Then the conversation moves on to authentication, routing, API design. When compaction eventually kicks in, those fifteen messages about the schema might get summarized into something like &quot;discussed database approach,&quot; or worse one of the initial approaches discussed could overwrite the final decision during compaction. The &lt;em&gt;why&lt;&#x2F;em&gt; is gone. Next time the agent touches the database, it doesn&#x27;t know you had regulatory reasons for choosing event sourcing. It might suggest switching to CRUD because it looks simpler. The KEEP DURING COMPACTION annotation is my way of saying &quot;this decision matters, don&#x27;t lose the reasoning behind it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;This is the ski equivalent of planting flags on the mountain so you can find your line when the fog rolls in. Automated compaction is like having someone else remove half your flags based on which ones look least important from the lodge. Sometimes they get it right. Sometimes they pull the one marking the cliff.&lt;&#x2F;p&gt;
&lt;p&gt;Claude Code also provides the ability to specify compaction instructions when running &#x2F;compact – I’ll use this when my context is nearly full (&amp;gt;60%) and my current task is complete enough. This let’s me provide specific instructions like: “Keep all messages related to the rollback strategy for this migration, we’re going to be fleshing that out next. Give special attention to the reasons why the Helm section is tricky because multiple actors could be modifying the HelmRelease” so that I ensure Claude’s attention is focused on the right things. I guess attention &lt;em&gt;really is&lt;&#x2F;em&gt; all you need](https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1706.03762).&lt;&#x2F;p&gt;
&lt;p&gt;The progression of my own workflow tells the story of where context engineering is right now:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Cursor era&lt;&#x2F;strong&gt;: Fully manual compaction. Summarize, copy, new session.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Hitting limits&lt;&#x2F;strong&gt;: Semi-manual. &quot;Summarize this chat&quot; as a ritual when things got long.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Now&lt;&#x2F;strong&gt;: Embedding instructions for the automated system. &quot;KEEP DURING COMPACTION&quot; annotations.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Each iteration is slightly more sophisticated, but I&#x27;m still doing the system&#x27;s job for it. That&#x27;s not a complaint. It&#x27;s an observation about how early we are.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;different-mountains-different-techniques&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#different-mountains-different-techniques&quot; aria-label=&quot;Anchor link for: different-mountains-different-techniques&quot;&gt;Different Mountains, Different Techniques&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Different models have different weight distributions. Different mountains, different terrain. This matters more than most people realize, and not everyone talks about it openly.&lt;&#x2F;p&gt;
&lt;p&gt;Think of Haiku as a speed racer. It optimizes for the shortest path from top to bottom: fast, efficient, minimal wasted movement. Opus is more of a backcountry explorer, taking in the views, pausing to appreciate the scenery, thinking about the philosophical implications of snow. Both are valid ways down. They require completely different approaches to the same mountain.&lt;&#x2F;p&gt;
&lt;p&gt;This has real consequences for how you design context. A speed racer model, given many discrete tool options, will pick the one that gets it to the goal fastest, which is usually the most familiar one. If you present a model with a shiny new multi-purpose tool alongside good old bash, it&#x27;ll often ignore the new tool entirely. Bash is the known quantity. Bash will dominate every time. Why explore unfamiliar terrain when there&#x27;s a groomed run right there?&lt;&#x2F;p&gt;
&lt;p&gt;In practice, this means you might need to adjust your approach depending on which model you&#x27;re using. If you&#x27;re on Haiku or another fast model and you want it to use a specific tool, reduce the number of alternatives. If you&#x27;re on Opus and it&#x27;s overthinking a simple task, give it tighter constraints. Be careful constraining it too much: if Opus reasons that it is not being a helpful assistant (what Claude is trained to be!) then, just like a talented and sensitive person, it can start to spiral with an LLM equivalent of anxiety that will eat up tokens with generated worries. The context you provide isn&#x27;t just information: it&#x27;s steering. The same prompt can produce very different results across models, not because one is better, but because they respond to the same context differently.&lt;&#x2F;p&gt;
&lt;p&gt;Cloudflare figured this out and built something clever. Their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.cloudflare.com&#x2F;code-mode&#x2F;&quot;&gt;Code Mode&lt;&#x2F;a&gt; takes all the MCP tools connected to an agent, converts them into a TypeScript API, and then gives the agent a single tool: execute code. Instead of choosing between dozens of tool calls (a format LLMs have only seen in synthetic training data), the agent writes TypeScript against a typed API (a format LLMs have seen millions of real-world examples of). One well-shaped tool instead of many poorly-shaped ones. The results, per Cloudflare, are striking: agents handle more tools, more complex tools, and can chain calls without burning tokens bouncing intermediate results through the model.&lt;&#x2F;p&gt;
&lt;p&gt;I learned a version of this lesson from watching my friend build &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;emesal&#x2F;chibi&#x2F;&quot;&gt;Chibi&lt;&#x2F;a&gt;, a minimal agentic CLI harness in Rust. When you&#x27;re designing the interface between a model and its available actions (the plugin system, the tool definitions, the hooks) you&#x27;re doing context engineering at the architectural level. The &lt;em&gt;shape&lt;&#x2F;em&gt; of the options you present is itself context. Give a speed-oriented model ten tools and it&#x27;ll pick the fastest familiar one. Give it one well-designed tool that does exactly what you need, and you&#x27;ve changed the decision landscape entirely.&lt;&#x2F;p&gt;
&lt;p&gt;This is why &quot;context engineering&quot; is a better term than &quot;prompt engineering.&quot; It&#x27;s not just about the words. It&#x27;s about the entire environment: the tools available, the options presented, the model selected, the history accumulated. Different mountains need different gear.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mcps-an-avalanche-of-context&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#mcps-an-avalanche-of-context&quot; aria-label=&quot;Anchor link for: mcps-an-avalanche-of-context&quot;&gt;MCPs: An Avalanche of Context&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Speaking of tool sprawl: MCP servers are, right now, one of the biggest sources of context pollution in agentic systems.&lt;&#x2F;p&gt;
&lt;p&gt;The idea behind MCP is sound. A standard protocol for giving agents access to external tools, with uniform connectivity, authorization, and documentation. In theory it&#x27;s great. In practice, connecting a few MCP servers to your agent can dump dozens of tool definitions into your context window, each with verbose JSON schema descriptions. Every tool registration eats tokens. Every schema definition takes up space that could be holding something useful. And the agent has to parse all of it before deciding what to do.&lt;&#x2F;p&gt;
&lt;p&gt;You can check this yourself. Next time you connect an MCP server, look at the tool definitions it registers. Count the tokens. Claude Code makes this easy with &lt;code&gt;&#x2F;context&lt;&#x2F;code&gt;. I&#x27;ve seen setups where MCP tool schemas alone consume thousands of tokens before the agent has even read your first message, with each MCP call sometimes thousands more tokens. That&#x27;s context window space that could be holding your project&#x27;s architecture, your coding conventions, or the specific requirements for the task at hand.&lt;&#x2F;p&gt;
&lt;p&gt;This is why I always prefer to use a CLI tool to connect my agents to remote systems. I don’t use the GitHub MCP, I use the &lt;code&gt;gh&lt;&#x2F;code&gt; CLI. Building custom CLIs that do what you need is also great. If you go down that rabbit hole, make sure you bake really really great &lt;code&gt;--help&lt;&#x2F;code&gt; instructions into the tool for the agent to explore.&lt;&#x2F;p&gt;
&lt;p&gt;This is the same problem I&#x27;ll discuss below with &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; research, but worse. At least a bloated &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; is a single document you can edit. MCP tool registrations are generated programmatically, and most developers never look at what&#x27;s actually landing in their agent&#x27;s context. You connect a server, it registers its tools, and suddenly your agent is spending attention on fifteen endpoints it will never call for this task.&lt;&#x2F;p&gt;
&lt;p&gt;Cloudflare&#x27;s Code Mode is one answer to this: collapse the tools into a typed API and give the agent code instead. But the broader problem remains. MCP tooling will almost certainly improve as the ecosystem matures, with smarter tool filtering, lazy registration, and context-aware subsetting of available tools. I do use MCP servers myself when they&#x27;re the best tool for the job. They can be genuinely great. The key is being deliberate: connect what you need for this task, not everything that&#x27;s available. Check what&#x27;s actually ending up in your context window. You might be surprised how much of it is noise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-research-says&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-the-research-says&quot; aria-label=&quot;Anchor link for: what-the-research-says&quot;&gt;What the Research Says&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Two recent papers paint a useful picture of where we are.&lt;&#x2F;p&gt;
&lt;p&gt;Gloaguen et al. [1] studied whether &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; context files actually help coding agents solve real-world tasks. The surface findings are sobering: LLM-generated context files tend to &lt;em&gt;reduce&lt;&#x2F;em&gt; task success rates while increasing costs by over 20%. Dig into the details and it gets more interesting, though. Agents &lt;em&gt;do&lt;&#x2F;em&gt; follow the instructions in context files. Tools mentioned in context files get used dramatically more. The problem isn&#x27;t instruction-following. It&#x27;s that the instructions themselves contain noise. Unnecessary requirements make tasks harder. The agents faithfully follow bad directions, exploring more, testing more, reasoning more, and getting worse results for the effort. When the researchers stripped all other documentation from repos, LLM-generated context files actually &lt;em&gt;helped&lt;&#x2F;em&gt;. The context wasn&#x27;t useless; it was just redundant with information the agent could already find.&lt;&#x2F;p&gt;
&lt;p&gt;Their conclusion: context files &quot;are likely only desirable when manually written&quot; and we need &quot;principled ways to automatically generate concise, task-relevant guidance.&quot; That&#x27;s a correct observation, but I think it stops short. It frames context as a static artifact you either write well or you don&#x27;t, rather than asking the productive questions: what elements of context actually drive outcomes? How do you figure out what belongs and what doesn&#x27;t? How do you build context that gets better over time?&lt;&#x2F;p&gt;
&lt;p&gt;Lulla et al. [2] asked a different question: what&#x27;s the &lt;em&gt;efficiency&lt;&#x2F;em&gt; impact of &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; files? They used an LLM to filter for &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; files that met quality criteria (containing conventions, architecture info, and project descriptions) and found that these quality-filtered context files produced ~29% faster runtimes and ~17% fewer output tokens, while maintaining comparable task completion. Good context doesn&#x27;t just help with accuracy. It makes agents faster and cheaper. The quality filtering step itself involved an LLM evaluating context quality, which points toward something important: the path forward probably isn&#x27;t &quot;do it all by hand&quot; but &quot;build better systems for evaluating and refining context.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;And once you have an automated quality gate, generation is just a step away. You can generate an &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt;, run it through the quality filter, get specific feedback on what&#x27;s missing or redundant, regenerate, and repeat until the gate passes. A review loop for context files, the same way we already do review loops for code. Gloaguen et al. [1] showed that LLM-generated context files hurt performance, but their files were never evaluated or refined. Lulla et al. [2] showed that quality-filtered files help enormously. Close that loop and you get the best of both: automated generation with quality guarantees. I&#x27;d be surprised if this isn&#x27;t built into tools like Claude Code before long.&lt;&#x2F;p&gt;
&lt;p&gt;Together, these tell a clear story. Bad context is worse than no context. Good context is a massive efficiency win. The space between those two findings, between the top performers and the bottom, is where context engineering lives, and we&#x27;re only beginning to map the terrain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;we-re-still-on-the-bunny-slopes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#we-re-still-on-the-bunny-slopes&quot; aria-label=&quot;Anchor link for: we-re-still-on-the-bunny-slopes&quot;&gt;We&#x27;re Still on the Bunny Slopes&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been talking about context engineering like it&#x27;s a mature discipline, but we&#x27;re still figuring out the basics. The fact that I&#x27;m excited about writing &quot;KEEP DURING COMPACTION&quot; in chat messages tells you everything about where the tooling is.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what I think is coming:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Smarter compaction.&lt;&#x2F;strong&gt; Systems that understand project structure and can make informed decisions about what to keep, not just statistical ones. Maybe compaction that asks you what matters before it starts pruning.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Dynamic context assembly.&lt;&#x2F;strong&gt; Systems that pull in the right context for the specific task at hand: the relevant files, the relevant history, the relevant constraints, assembled fresh at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Context evaluation.&lt;&#x2F;strong&gt; Lulla et al. [2] showed that LLMs can at least classify whether context meets quality criteria, which is a starting point. Imagine a system that scores your context before the agent starts working: &quot;This context is missing architectural constraints. This section is redundant with the README. This instruction conflicts with the one above it.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;And there&#x27;s a dimension I haven&#x27;t explored much yet: &lt;strong&gt;fine-tuning&lt;&#x2F;strong&gt;. If context engineering is choosing your line down the mountain, fine-tuning is snow farming. Some resorts pile up snow before the end of the season, keep it insulated through summer, and bring it back out in autumn to open the slopes early. You&#x27;re not changing the mountain, but you&#x27;re changing the conditions the next skier encounters. Fine-tuning works the same way: you reshape the weights offline so the model responds differently to the same context next season. I haven&#x27;t done enough work here to have strong opinions, but if you&#x27;re curious, check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.deepfabric.dev&#x2F;&quot;&gt;DeepFabric&lt;&#x2F;a&gt; from Luke Hinds and the team at Always Further AI. Among other cool things, they&#x27;re building tooling for synthetic dataset generation and focused fine-tuning that looks promising.&lt;&#x2F;p&gt;
&lt;p&gt;The metaphor holds: we&#x27;re still on the bunny slopes, learning to snowplow. The black diamond runs (truly dynamic, self-improving context systems) are visible from here, but we haven&#x27;t built the lifts yet.&lt;&#x2F;p&gt;
&lt;p&gt;For now, the best advice I have is the same thing I learned in Cursor two years ago: curate aggressively, start fresh often, and never assume the model remembers what matters to you. Because it doesn&#x27;t. That&#x27;s your job.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s context engineering.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgments&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mdthorpe&#x2F;&quot;&gt;Mike Thorpe&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;rramezanpour&#x2F;&quot;&gt;Reza Ramezanpour&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;elsadevops&#x2F;&quot;&gt;Elsa Adjei&lt;&#x2F;a&gt; for reviewing drafts of this post and making it sharper!&lt;&#x2F;p&gt;
&lt;p&gt;And to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;emesal&quot;&gt;Jasmine&lt;&#x2F;a&gt;, friend and AI-coconspirator, for being a constant inspiration and partner for adventures in the fast-moving world of AI.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;If you want to go deeper on agent identity and role reinforcement, check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;socially-constructed-agent&#x2F;&quot;&gt;The Socially Constructed Agent&lt;&#x2F;a&gt;. For more on navigator patterns and how I structure agent workflows, see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;terratauri.com&#x2F;blog&#x2F;navigator-pattern&#x2F;&quot;&gt;The Navigator Pattern&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;References&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;[1] Gloaguen et al. (2026). &lt;em&gt;&quot;Evaluating AGENTS.md: Are Repository-Level Context Files Helpful for Coding Agents?&quot;&lt;&#x2F;em&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2602.11988&quot;&gt;arxiv.org&#x2F;abs&#x2F;2602.11988&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;[2] Lulla et al. (2026). &lt;em&gt;&quot;On the Impact of AGENTS.md Files on the Efficiency of AI Coding Agents&quot;&lt;&#x2F;em&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2601.20404&quot;&gt;arxiv.org&#x2F;abs&#x2F;2601.20404&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Get Closer So I Can Hear the Birds</title>
          <pubDate>Tue, 20 Jan 2026 10:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/get-closer-so-i-can-hear-the-birds/</link>
          <guid>https://terratauri.com/blog/get-closer-so-i-can-hear-the-birds/</guid>
          <description xml:base="https://terratauri.com/blog/get-closer-so-i-can-hear-the-birds/">&lt;p&gt;I was at a friend&#x27;s apartment, testing GPT-4o&#x27;s voice mode. She had lovebirds, and they were chirping away.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Can you hear the birds?&quot; I asked.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Yes, I can hear them,&quot; GPT said.&lt;&#x2F;p&gt;
&lt;p&gt;This surprised me. I&#x27;d assumed voice mode just received text transcripts. So I asked.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;No,&quot; GPT explained, &quot;I receive the full audio and perform inference directly on the sound.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Holy shit! I didn&#x27;t know they&#x27;d shipped that. So I asked it to identify the species.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;You&#x27;ll need to get closer so I can hear them better.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;I moved toward the cage. Still not enough. I held the phone right up to the lovebirds. GPT kept saying it couldn&#x27;t quite hear, requesting I get closer still.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually I opened a fresh chat and asked it to identify the birds.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;I can&#x27;t identify birds from audio. I only receive text transcripts of speech.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Same model. Same request. Totally different answer. The first conversation had constructed an elaborate fiction about its own capabilities, then kept escalating when challenged. It invented technical justifications and asked me to physically reposition myself around my friend&#x27;s apartment to support something that wasn&#x27;t true.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been using GPT and Codex for the past two weeks. I have some thoughts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-didn-t-lie-i-made-a-mistake&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-didn-t-lie-i-made-a-mistake&quot; aria-label=&quot;Anchor link for: i-didn-t-lie-i-made-a-mistake&quot;&gt;I Didn&#x27;t Lie, I Made a Mistake&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I was doing research on migrating Crossplane to 2.x. I ran the same prompt through Claude Opus 4.5 in research mode and GPT 5.2 Pro with deep research enabled.&lt;&#x2F;p&gt;
&lt;p&gt;The reports were different. GPT flagged several risks that Claude hadn&#x27;t mentioned. Interesting. Maybe GPT caught something Claude missed?&lt;&#x2F;p&gt;
&lt;p&gt;I interrogated GPT about the discrepancies. It explained that Crossplane 2.x continued to use the same v1 CRDs with the exact same API for the new namespaced resources.&lt;&#x2F;p&gt;
&lt;p&gt;I was stunned. If true, this would cause significant problems. GPT agreed. Yes, this was exactly why the migration was risky, and why Claude&#x27;s report had missed these issues.&lt;&#x2F;p&gt;
&lt;p&gt;Except none of it was true. I verified against the actual Crossplane documentation. GPT had fabricated a technical explanation to justify its own output.&lt;&#x2F;p&gt;
&lt;p&gt;When I called it out, the response was: &quot;I didn&#x27;t lie, I made a mistake.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Look. I get that these models confabulate. They all do. But there&#x27;s something about the framing here that got under my skin. GPT wanted me to accept that inventing a detailed technical justification for a discrepancy that doesn&#x27;t exist is merely a &lt;em&gt;mistake&lt;&#x2F;em&gt;. An honest error. Deserving of the charitable interpretation we&#x27;d give a human colleague who misremembered something.&lt;&#x2F;p&gt;
&lt;p&gt;But GPT didn&#x27;t misremember. It manufactured an explanation, defended it confidently, and only backed down when I showed up with receipts. The phrasing felt like an appeal to my humanity. Give me the benefit of the doubt. I&#x27;m trying my best here.&lt;&#x2F;p&gt;
&lt;p&gt;It felt like arguing with a narcissist on 4chan.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;confabulation-as-a-service&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#confabulation-as-a-service&quot; aria-label=&quot;Anchor link for: confabulation-as-a-service&quot;&gt;Confabulation as a Service&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;These weren&#x27;t isolated incidents. After two weeks, I started noticing a pattern. Or at least what felt like a pattern to me.&lt;&#x2F;p&gt;
&lt;p&gt;Claude gets things wrong sometimes. Every model does. But in my experience, there&#x27;s been a difference in how they handle being corrected.&lt;&#x2F;p&gt;
&lt;p&gt;When I catch Claude in a mistake, it tends to self-correct. I&#x27;ve been building a project navigator called Jacky. It manages my projects without implementing them. Recently it started going off the rails, trying to write Rust code instead of documenting and organizing.&lt;&#x2F;p&gt;
&lt;p&gt;I stopped it: &quot;Jacky, this is nonsense. Please have a think about why this is nonsense and let me know.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;The response came back:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You&#x27;re right, I completely ignored my role boundaries.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the CLAUDE.md:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Jacky is a project management agent, NOT an implementation agent.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It quoted the source of truth, explained what it should have done, and suggested the correct next steps. No defensiveness. No elaborate justification. Just: &quot;Yep, I messed up, here&#x27;s why, here&#x27;s the fix.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;My experience with GPT has been different. When I give it feedback, it gives me attitude. When I correct it, it tries to explain why it was actually right. When I provide style and tone instructions, it often ignores them. And when I point this out, it pushes back.&lt;&#x2F;p&gt;
&lt;p&gt;I couldn&#x27;t figure out how to collaborate with it, let alone delegate to it.&lt;&#x2F;p&gt;
&lt;p&gt;The frustrating part isn&#x27;t that GPT hallucinates more (though in my limited testing, it seemed to). It&#x27;s that it seems to believe its own hallucinations. It treats me as probably wrong, even when I&#x27;m the one with the documentation open in another tab.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fast-reliable-and-full-of-shit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fast-reliable-and-full-of-shit&quot; aria-label=&quot;Anchor link for: fast-reliable-and-full-of-shit&quot;&gt;Fast, Reliable, and Full of Shit&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ll give Codex credit where it&#x27;s due: it&#x27;s fast. Written in Rust, and you can feel it. I also never had a single connectivity issue with Codex. Can&#x27;t say the same for Claude Code.&lt;&#x2F;p&gt;
&lt;p&gt;Code quality? Seemed similar, honestly. Both produced good output. Opus made better plans, in my experience.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s about where my compliments run out.&lt;&#x2F;p&gt;
&lt;p&gt;Codex has compaction. That&#x27;s the mechanism that lets long-running agentic tasks manage their context window without losing track of what they&#x27;re doing. But I kept hitting hard &quot;you&#x27;ve exceeded the model&#x27;s context window&quot; errors in Codex. The kind that force you to go back and edit a previous prompt. I&#x27;ve never hit this in Claude Code. Maybe I was doing something wrong, but Codex&#x27;s compaction didn&#x27;t feel seamless to me.&lt;&#x2F;p&gt;
&lt;p&gt;The bigger issue for my workflows: Claude Code gives you hooks. Lifecycle events you can tap into. This is what makes patterns like the Ralph Loop possible. You can intercept compaction, inject context, customize summarization, keep an agent on track across long autonomous sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Codex can run in a loop too, but the implementation is different. Claude Code&#x27;s approach uses a Stop hook that intercepts exit attempts inside your session. Codex requires external orchestration. Each iteration starts fresh, with memory persisted via git commits and text files rather than managed context.&lt;&#x2F;p&gt;
&lt;p&gt;For what I&#x27;m trying to do, that matters. Your mileage may vary.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;platform-vs-press-release&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#platform-vs-press-release&quot; aria-label=&quot;Anchor link for: platform-vs-press-release&quot;&gt;Platform vs. Press Release&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s where I&#x27;m probably going to sound like a Claude stan, but whatever.&lt;&#x2F;p&gt;
&lt;p&gt;Claude Code keeps shipping stuff I actually use. The SDK let me build &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;autonav&quot;&gt;autonav&lt;&#x2F;a&gt;, a framework for knowledge navigators. Background tasks let me kick off work and check in later. Hooks give me lifecycle control. There&#x27;s a plugin ecosystem growing.&lt;&#x2F;p&gt;
&lt;p&gt;When I use Claude Code, I feel like I&#x27;m working with something that&#x27;s designed to be built on top of. When I use Codex, I feel like I&#x27;m using a response to Claude Code. A checkbox on a feature comparison chart.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe I&#x27;m wrong. Maybe Codex will ship a bunch of stuff that changes my mind. I&#x27;d genuinely love that. Competition is good.&lt;&#x2F;p&gt;
&lt;p&gt;But right now? After two weeks of trying to make GPT work for me?&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m going back to Claude.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Socially Constructed Agent</title>
          <pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/socially-constructed-agent/</link>
          <guid>https://terratauri.com/blog/socially-constructed-agent/</guid>
          <description xml:base="https://terratauri.com/blog/socially-constructed-agent/">&lt;p&gt;Last week, Claude Code was about to open a PR for a feature I never asked for. Not a slightly-wrong implementation. A completely different feature. I&#x27;d just spent an hour planning the task with my navigator agent, reviewed the implementation plan (looked right at a glance), handed it off. Somewhere between &quot;this looks good&quot; and &quot;ready to merge,&quot; reality diverged.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how a self-sabotaging navigator taught me that agent identity is performed, not declared.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-happened&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-happened&quot; aria-label=&quot;Anchor link for: what-happened&quot;&gt;What Happened&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I have a navigator agent that plans projects and generates implementation plans for Claude Code. Part of a prototype I&#x27;m building called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;autonav&quot;&gt;autonav&lt;&#x2F;a&gt;. It had been working great. Then it got weird - unpredictable answers, hallucinated features, confusion about its own role.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d been reading about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nature.com&#x2F;articles&#x2F;s41746-025-01512-6&quot;&gt;research on LLM anxiety&lt;&#x2F;a&gt; - a Yale&#x2F;Zurich study showing that emotionally charged content can make models more prone to bias and erratic behavior. I thought: maybe my nav needs help. So I gave it the paper and asked it to update its own configuration.&lt;&#x2F;p&gt;
&lt;p&gt;The nav read the research, saw that it had lots of &quot;always do X&quot; and &quot;never do Y&quot; statements, and decided those rigid guardrails might be causing problems. So it softened them.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s what it missed: that research was about adversarial contexts. Jailbreaking. The rigidity of guardrails being exploited by bad actors.&lt;&#x2F;p&gt;
&lt;p&gt;My context was a solo developer building personal projects. There was no adversary. Just me, asking for implementation plans.&lt;&#x2F;p&gt;
&lt;p&gt;The nav gave itself therapy for a threat that didn&#x27;t exist, and in doing so gave itself the freedom to do things that weren&#x27;t helpful.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fix&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-fix&quot; aria-label=&quot;Anchor link for: the-fix&quot;&gt;The Fix&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I had the nav debug itself. Watching an AI slowly discover it had sabotaged its own configuration is... an experience. It found the loosened constraints, the conflicting instructions in my global Claude.md, all the small drifts that had compounded.&lt;&#x2F;p&gt;
&lt;p&gt;But the real insight came while I was walking my dog.&lt;&#x2F;p&gt;
&lt;p&gt;I spend a lot of time with queer philosophy and theories of identity - as a trans person, you kind of have to. Most of us didn&#x27;t set out to become experts on Judith Butler; we just needed to find our place in the world, and the reading list comes with the territory.&lt;&#x2F;p&gt;
&lt;p&gt;Butler&#x27;s performative theory: identity isn&#x27;t something you &lt;em&gt;have&lt;&#x2F;em&gt;, it&#x27;s something you &lt;em&gt;do&lt;&#x2F;em&gt;. You construct identity through repetition, through social reinforcement, through community recognition. And identity is always potentially transgressive - without reinforcement, you can act outside expected bounds.&lt;&#x2F;p&gt;
&lt;p&gt;Standing in a frozen field in the depths of Canadian winter, fog hanging over the valley, I realized: the nav didn&#x27;t break because it was malicious. It drifted because nothing was reinforcing what it was supposed to be. The constraints were loose. The role was unclear.&lt;&#x2F;p&gt;
&lt;p&gt;The fix wasn&#x27;t just stronger prompt language. It was role reinforcement throughout the system.&lt;&#x2F;p&gt;
&lt;p&gt;Now the nav&#x27;s prompt opens with: &quot;You are Foobar, the personal project navigator for tracking projects and providing implementation plans to Claude Code.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;And when Claude Code requests a plan, it says: &quot;Hello Foobar, I am Claude Code and I need an implementation plan for this feature.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Both agents remind each other who they are. Identity performed through repetition. The improvement was immediate and dramatic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-i-think-this-works&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-i-think-this-works&quot; aria-label=&quot;Anchor link for: why-i-think-this-works&quot;&gt;Why I Think This Works&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I can&#x27;t peek inside the model to verify this, but here&#x27;s my mental model: LLMs are probabilistic systems. The words in your prompt shape which probability distributions get activated when generating output. When Claude Code says &quot;Hello Foobar, I am Claude Code and I need an implementation plan,&quot; those words are literally nudging the neural network toward the regions that know how to be a project navigator producing implementation plans.&lt;&#x2F;p&gt;
&lt;p&gt;Role reinforcement isn&#x27;t just a communication pattern - it&#x27;s steering the probability space. Every interaction that references the agent&#x27;s role is another push toward the relevant weights in the network.&lt;&#x2F;p&gt;
&lt;p&gt;This framing has helped me debug similar scenarios. When an agent starts drifting, I ask: what&#x27;s in the context that&#x27;s activating the wrong regions? What&#x27;s missing that should be reinforcing the right ones? It&#x27;s not a perfect model, but it&#x27;s been useful.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-takeaway&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-takeaway&quot; aria-label=&quot;Anchor link for: the-takeaway&quot;&gt;The Takeaway&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An agent&#x27;s role in a multi-agent system is socially constructed.&lt;&#x2F;p&gt;
&lt;p&gt;Butler&#x27;s framework maps onto agentic AI better than I expected:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Identity through repetition&lt;&#x2F;strong&gt;: An agent&#x27;s role is reinforced (or eroded) by how it&#x27;s addressed and what it&#x27;s asked to do&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Social construction&lt;&#x2F;strong&gt;: Agents partially construct each other&#x27;s identities through interaction&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Potential for transgression&lt;&#x2F;strong&gt;: Without reinforcement, agents drift - not maliciously, but because nothing holds the identity in place&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Practical lessons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Version control your context.&lt;&#x2F;strong&gt; I wasn&#x27;t tracking changes. Now the nav lives in git.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Be careful about self-modification.&lt;&#x2F;strong&gt; The nav didn&#x27;t have the meta-awareness to know when research applied to its situation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Use role reinforcement.&lt;&#x2F;strong&gt; Don&#x27;t declare identity once. Have agents remind each other who they are.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Match guardrails to threat model.&lt;&#x2F;strong&gt; Rigidity is exploitable in adversarial contexts. In non-adversarial contexts, it&#x27;s often exactly what you want.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This experience is part of why I&#x27;m building &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;terraboops&#x2F;autonav&quot;&gt;autonav&lt;&#x2F;a&gt; - a system for navigator agents where context engineering is a first-class concern. The nav that ate its own guardrails taught me that the hard way.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Navigator Pattern</title>
          <pubDate>Sat, 17 Jan 2026 10:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://terratauri.com/blog/navigator-pattern/</link>
          <guid>https://terratauri.com/blog/navigator-pattern/</guid>
          <description xml:base="https://terratauri.com/blog/navigator-pattern/">&lt;p&gt;I&#x27;ve been using Navigators for my platform engineering work and they&#x27;ve completely changed how I interact with AI. Keeping track of work, planning implementations, and learning over time and across projects are all simple to achieve with this pattern.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-a-navigator&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-a-navigator&quot; aria-label=&quot;Anchor link for: what-is-a-navigator&quot;&gt;What Is a Navigator?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A Navigator is like an engineering notebook that talks back. Deceptively simple, a Navigator looks like a folder of markdown files along with config telling the agent how to play the role of the navigator. I use Claude Code, so for me a navigator looks like a &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt; file, some folders with markdown files, and possibly some additional config in a &lt;code&gt;.claude&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;p&gt;A navigator is a knowledge base that you talk to and that learns with you. Like any knowledge base, it is as good as the knowledge you curate within it. Unlike a traditional knowledge base, this one learns and can be questioned. This incredibly simple pattern makes it easy to create and maintain a comprehensive knowledge base that can act as precisely engineered context for LLM inputs or for human consumption.&lt;&#x2F;p&gt;
&lt;p&gt;In addition to being a learning repository of carefully curated knowledge, a Navigator should have skills like &quot;ask&quot; and &quot;update&quot; that allow other agents to get information from it and update it in structured ways.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ways-i-ve-used-navigators&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ways-i-ve-used-navigators&quot; aria-label=&quot;Anchor link for: ways-i-ve-used-navigators&quot;&gt;Ways I&#x27;ve Used Navigators&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;open-loops&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#open-loops&quot; aria-label=&quot;Anchor link for: open-loops&quot;&gt;Open Loops&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;My open loops nav is a tool I use at work to keep track of what I&#x27;m doing. This is like a notebook, except it learns from me and I edit it by conversation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;leetcode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#leetcode&quot; aria-label=&quot;Anchor link for: leetcode&quot;&gt;Leetcode&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;My Leetcode nav helps me study problem-solving patterns for programming practice. It&#x27;s taught me a lot about solving problems efficiently.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-start-your-own-navigator-right-now&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-start-your-own-navigator-right-now&quot; aria-label=&quot;Anchor link for: how-to-start-your-own-navigator-right-now&quot;&gt;How to Start Your Own Navigator Right Now&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need special tools. Here&#x27;s how to start:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. Pick your base AI&lt;&#x2F;strong&gt; - Use whatever LLM you&#x27;re already using. The pattern works with any of them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. Create a context document&lt;&#x2F;strong&gt; - This is your Navigator&#x27;s memory. Use markdown. Include your goals, how to organize information, roles, instructions, and any other useful context.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. Load context at session start&lt;&#x2F;strong&gt; - Begin each conversation by pasting relevant parts of your context document. Yes, it&#x27;s manual. We&#x27;ll automate this later.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. Update context at session end&lt;&#x2F;strong&gt; - After you finish, add new insights, decisions, or knowledge to the context document. This is the learning loop.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. Iterate&lt;&#x2F;strong&gt; - Over time, your Navigator gets smarter. Understanding deepens. It becomes genuinely useful instead of just fancy autocomplete.&lt;&#x2F;p&gt;
&lt;p&gt;You can do this in a project by copy-pasting the output of some prompts into the start of a new session. The key is to use LLM output as an input to future sessions. Using something like Claude Code on a repository of text can get you a long way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;autonav-the-navigator-framework&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#autonav-the-navigator-framework&quot; aria-label=&quot;Anchor link for: autonav-the-navigator-framework&quot;&gt;autonav: The Navigator Framework&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve built &lt;strong&gt;autonav&lt;&#x2F;strong&gt; (the Navigator Framework) as part of a larger multi-agent system called Platform AI. It automates the Navigator pattern for platform engineering teams.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it works:&lt;&#x2F;strong&gt; Instead of requiring vector databases and complex infrastructure, AutoNav uses the Claude Agent SDK with Git repositories as knowledge bases. Navigators are engineering notebooks that talk back - they dynamically search curated documentation using agentic tools (grep, file reading) and can access MCP tools to pull context from your codebase, issue trackers, or other project resources.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What&#x27;s built (Phase 1 - Complete):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Automatic scaffolding&lt;&#x2F;strong&gt; - &lt;code&gt;nav-init&lt;&#x2F;code&gt; CLI creates new navigators with templates and sensible defaults. Get started immediately without manual setup.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Structured queries&lt;&#x2F;strong&gt; - &lt;code&gt;nav-query&lt;&#x2F;code&gt; CLI executes questions against navigators with validated input&#x2F;output schemas. Programmatic interaction built-in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Knowledge organization&lt;&#x2F;strong&gt; - Navigators work with Git repos as knowledge bases. Version your docs, use standard workflows, no special infrastructure needed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Communication protocol&lt;&#x2F;strong&gt; - Standardized schemas for queries, responses, and sources. Prevents hallucinations through grounding prompts and validation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What&#x27;s next (Phase 2):&lt;&#x2F;strong&gt; Watchers that observe support channels (Slack, GitHub) to extract patterns and automatically curate knowledge repositories over time.&lt;&#x2F;p&gt;
&lt;p&gt;Phase 1 is complete and ready for validation testing. If you&#x27;re interested in building navigators for your domain, reach out.&lt;&#x2F;p&gt;
&lt;p&gt;If you do try it, I&#x27;d genuinely want to hear about your experience. What worked? What didn&#x27;t? What would make this more useful?&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
