What's in the window: the anatomy of a Doric turn
We've written before about why AI threads rot — the slow slide from sharp to sludge as the context fattens. This is the companion piece: a look inside a single turn at what Doric actually hands the model, and the one design choice that makes the difference between a thread that gets pricier as it grows and one that doesn't.
Every turn is a fresh hand-off
An AI model is stateless — it remembers nothing between turns. So on every message, the system rebuilds the full briefing and sends the whole thing again: who this agent is, what the project is, the decisions that stand, the relevant slice of code, your last messages. There's no way around the resend — the model can only act on what's in front of it right now. Naïvely, that means re-buying the entire briefing on every single turn.
What saves you from that bill is caching — and caching is exactly where the design work lives.
The warm cache is the whole ballgame
The model providers build a strong cache in. The first time the model sees a chunk of text it's billed in full; if the next turn opens with the exact same chunk, that part is served warm — processed from cache at a small fraction of the price. On a steady thread, that warm cache is most of what you'd otherwise pay. The catch is unforgiving: the cache only holds for an unbroken prefix. The moment one byte changes, everything after that point is cold again and re-billed at full price.
So the resend itself is unavoidable; what's not fixed is how much of it lands warm. The provider gives you the cache — it doesn't decide how to lay out your prompt so the cache actually catches. That layout is the part we engineer, and it's where most of the win hides.
The rule that falls out of this: anything stable should sit before anything that changes. Mix one volatile line into a block of stable context, and you pay full price for the stable part too — every turn.
The mistake: organising by topic
The intuitive way to build the briefing is by subject — a persona section, a project section, a memory section, the relevant code, and so on. It reads cleanly. But it quietly breaks the cache, because topics don't share a clock. Inside that tidy "memory" section, ninety-five percent hasn't moved in days — but it's glued to a freshly-computed slice that changes every turn. Glued together, they share a fate: the small fresh part drags the large stable part out of the cache with it, and you re-buy the whole section on every message.
We had exactly this. The heaviest stable pieces of the briefing — an agent's accumulated memory, the standing catalogue of what it can do — were riding in the same cache region as the one slice that's rebuilt every turn. Tens of thousands of tokens of unchanged context, re-billed turn after turn, for no reason other than how they were grouped.
The fix: organise by how often things change
So we stopped sorting the briefing by topic and started sorting it by change-rate. Three bands:
Who I am — the agent's identity, role, and working stance. This is effectively fixed for the whole thread. It goes first, it caches once, and you never pay for it again.
What I know — the durable context: accumulated memory, the project's settled shape, the capability catalogue. This changes occasionally — when a decision lands or a memory is written — but not turn to turn. It caches until something actually moves it.
This turn — the genuinely live part: the code slice for what you just named, the freshest decisions, a returning expert's findings, your recent messages. This is small, and it's the only part that's re-billed each turn.
Same words, same briefing, same answer. We just stopped letting the small changing part hold the large stable part hostage. The thread feels the same; the bill stops climbing.
A detail that bit us: the moving moment
One of our agents — the strategist — gets a small, freshly-written nudge at the top of its briefing each turn, tuned to the shape of what you just asked. Useful. But it was sitting up in the "who I am" band, the part that's supposed to never change. One moving line at the top meant the entire identity band fell out of the cache on every strategist turn. The fix was just to move that one line down into the "this turn" band, where changing things belong. The nudge still lands exactly where it should in the conversation; the identity above it finally holds still.
That's the texture of context engineering: the architecture is simple, and most of the work is hunting down the one moving byte that's quietly invalidating everything beneath it.
Push less; pull what the turn needs
Caching stops you paying twice for the same context. The next question is whether you needed to send it at all. The old reflex is to push everything the model might want — the whole memory, a wide swath of project context — just in case. Most of it goes unread, and all of it costs.
We've been moving the heavy pieces from push to pull. Doric already reads your message, spots the real things it names — a file, a feature, a decision, a library — and attaches only the matching slice of the codebase and docs. On an ordinary message that attachment is empty; the briefing stays lean. It appears exactly when the turn points at something real. The next step is to put an agent's memory on that same footing: carry a short index always, and fetch the specific passage only when the turn calls for it — so a long memory stops being a tax on every message and becomes something retrieved on demand.
The floor that never drops
Trimming has a failure mode: trim the wrong thing and the agent loses the plot. So the budget has a floor it is never allowed to cut — the project's settled context, the decisions that stand, the thread's charter, and your recent messages. Everything else is ranked, and under real pressure the lowest-value extras shed first, in a fixed order, before anything load-bearing is touched. The briefing flexes; it never drops the things that keep the agent coherent.
Why we ship it behind a switch
A change to what the model sees on every turn is a change that can go subtly wrong everywhere at once. So none of this lands as a leap. Each move ships behind a flag, and every flag has an off position that restores the previous behaviour byte-for-byte. If a segmentation choice doesn't pay off, we flip it back without a redeploy. The worst case for the cache work is that it does nothing — it cannot make an answer worse, only the bill smaller. That reversibility is why we can be aggressive about cost without gambling with your threads.
What you get
Concretely: the longer you stay in a thread, the more of your briefing is served warm, so cost flattens instead of climbing as the project grows. The agents that carry the most context — the ones with long memories and a lot of standing decisions — get cheaper rather than heavier. And the briefing that reaches the model is smaller and more on-point, which means sharper answers, not just cheaper ones. The window stays small on purpose, turn after turn, on day 90 as on day 1.