Introduction
Every context engineering task is a search for the minimal set of tokens that reliably produces the result. Context is all the information that reaches the model before it gives an answer. My favourite way of putting it: good context engineering means finding the smallest possible set of high-signal tokens that maximise the likelihood of our desired outcome. Every word in that sentence matters. Behind each one there’s a fairly large layer of technology. DOWNLOAD THE SLIDES (in Russian)
Why the era of “magic prompts” is ending
A while ago, especially in 2024–2025, prompt engineering was hugely popular in its simplified form: you just have to find the right words. People sold whole packs of “perfect prompts”, collections of five hundred prompts for marketing, programming, sales, anything at all. There was a belief that a magic combination of tokens existed that would crack the model open and make it produce the result you needed.
Now that story is gradually fading into the past. People are getting a bit smarter and starting to understand that the prompt is only a small part of the whole system. Especially when we’re talking not about a simple chat, but about complex projects, products, agent scenarios, code, tools, memory and so on. The more complex your system, the less weight the piece of text you typed into the input by hand carries.
Roughly speaking, in a big modern session your hand-written prompt can make up anywhere from zero to one per cent of the real context. Hoping that this one per cent alone determines the result is naive by now. So today it matters more to understand how the whole context around those words is built than to hunt for “perfect words”.
A prompt is not context
When I say “context”, I don’t just mean your last question in the chat. Context is a much broader construction.
If you take apart a modern agent session, say in Claude Code, Codex or similar systems, there are several layers.
First, the model weights. What’s already baked into the model itself, and what we can’t influence at all.
Second, the system prompt.
Third, memory, a layer that appeared relatively recently.
Next come tools: your code, integrations, MCP servers, search mechanisms, the instruments the agent knows how to use.
Then skills, if you’ve made any.
Then the project files the model pulls in as needed, that is, just in time.
And only at the very end is the history of your conversation, which most people take to be “the whole context”.
In reality, most of what actually affects the answer isn’t visible to the user at all. And many people simply ignore everything above the level of the ordinary chat. They connect a pile of servers, bolt on integrations, install everything in sight, and then wonder why half of their context window is already taken at the start of a session. I’ve seen many times how people set up so much that 100,000 or 200,000 tokens were already used at the beginning of a session. That’s simply a huge overspend.
The context window isn’t “memory” but a surface of attention
When I talked about the context window a year ago, I described it fairly simply too: as what the model sees. Back then that was still tolerable, because windows were smaller, 60,000 or 100,000 tokens, and the problem of attention getting spread thin wasn’t so obvious.
Now I find it much more useful to think of the context window as a surface of attention. It’s a bit like your desk. If your desk is covered in rubbish, irrelevant documents, folders, extra files, it’s hard to work out what to tackle first. If the desk holds only what relates to the current task, work is easier: the signal is stronger and there’s less noise.
The same happens with a model. When it answers, each token is related to the other tokens. Inside a transformer it all comes down to an attention matrix: what relates to what, what affects what, what should be weighted more and what less. And the more rubbish you’ve loaded into the window, the worse. The model is simply forced to spread its limited attention across a huge number of tokens. The important signal gets weaker, the noise stronger.
That’s exactly why the more elements there are in the context, the harder it is to hold on to the signal. The more historical rubbish and unstructured data there is, the higher the chance the model goes off in the wrong direction.
Why “more context” doesn’t mean “a better result”
Now many people see that models have windows of hundreds of thousands and even a million tokens, and think: great, that means you can just load everything in there. But in practice it doesn’t work that straightforwardly.
In all the charts and experiments I’ve seen, the overall trend is the same: the more tokens we load into the context, the lower the chance that the model finds exactly the fact or exactly the answer we need.
If you’re just writing text, this may not be so noticeable. But if you’re writing code, it becomes critical. It’s enough for one function, one class, one dependency or one important link to get lost in the noise, and the model starts working worse. People complain: “The model has got bad at writing code.” And then you look at their project and it’s just a dump. Documentation, rubbish, extra files, pointless instructions, random leftovers from old tasks.
I usually advise asking yourself a simple question: could a person solve this task with the inputs you’re giving the model right now? If a person would struggle with it, so will the model. That means the problem isn’t only the model. It means the way you’ve packaged your data and documents simply isn’t good enough.
Attention, reasoning and the two ways long context degrades
When a model works, it recalculates the relationships between tokens every time. Very roughly, that’s why long context is expensive, slow and not always high quality.
As I see it, long context degrades in two main ways.
The first is ordinary context rot. The more tokens there are, the less attention can be given to the pieces that really matter.
The second is the degradation of reasoning. When a model has thinking or a reasoning mode switched on, it has an extra budget for thinking things through. But the bigger your input, the less budget is left for the reasoning itself. So the model spends its resources not on thinking well, but simply on digesting all that volume.
I recently came across a big study where the author compared current Anthropic models and concluded that the quality of their reasoning had deteriorated noticeably at roughly the same time as the heavy usage limits began. My feeling is that this is because they’re training new big models at the same time and simply don’t have enough resources. In that scenario, the first thing they start squeezing is thinking. So when you have reasoning switched on, I’d keep one simple thing in mind: there’s a good chance it’s being “throttled” too, and the bigger your context, the smaller the real budget for that thinking.
Here’s something even more curious: when they rolled out recent updates, they encrypted the thinking blocks. The official explanation is that it stops people trying to inject their prompts into the thinking mechanism. But there’s another view: that it was also done so that from the outside you couldn’t so easily see how much the internal reasoning had really deteriorated. You used to be able to read this reasoning; now in Claude Code you can’t see it any more. It’s encoded and unavailable to the user. I don’t think that’s a coincidence.
Why it’s so expensive to compute
Put very simply, the attention mechanism relies on matrix multiplication. And this is where the fundamental computational cost of the whole thing begins.
When a model generates the next token, it relates the tokens to each other. If you have 100 tokens of input, that’s one kind of maths. If it’s 40,000, it’s a completely different kind. And a million even more so. The problem is that the growth here isn’t linear but quadratic. It’s not that we made the context ten times bigger and got ten times the cost. We got n².
That’s exactly why I’m sceptical of all the stories about a “real million tokens”. Yes, formally you may have a million. But if you honestly calculate the real computational price, it becomes clear that it can’t work without compromises. Most likely the window gets cut into pieces, put together synthetically, attention gets redistributed somehow, engineering tricks get used. So it’s not the kind of “million” in which each next token is taken into account equally well. Beyond a certain volume, quality will drop anyway.
In this sense a context engineer manages inference compute. The fewer tokens, the less computation, the faster the answer, the lower the cost and the higher the accuracy. That’s exactly why writing everything into one chat, about health, work, code, personal stuff, is a bad idea. And putting a pile of files into one project and then telling the model “read everything” is a bad idea too.
Model weights: the foundation we don’t touch
The lowest layer of context is the model weights. This is what has already been trained on a huge body of data and converted into mathematical form. In essence, it’s a pre-baked internet turned into vectors. It’s thanks to this that the model knows “hello” is often followed by “how are you”, understands the basic semantics of language and generally has some idea of the world.
We have almost no influence on this. Yes, some people like training their own models and playing with small experimental versions. At a simple level it really isn’t that hard. But if we’re talking about full-scale large models, that’s months of training and enormous computing power.
Sometimes models are fine-tuned for a region. That’s why, say, YandexGPT, Sber GPT, Mistral, Chinese models or any regional builds may behave slightly differently. I even had a funny example with Telegram Translator. If you paste in certain political wording about Taiwan, Xi Jinping and Tiananmen Square and press Fix, then by my observations it doesn’t just “correct” the text but starts producing a version that’s ideologically correct for China. From this you can draw a fairly plausible conclusion that there’s a Chinese model under the bonnet.
It’s a good example of how pre-training and fine-tuning really do affect a model’s behaviour, even if the user doesn’t see it.
The system prompt and the behavioural frame
The next layer is the system prompt. This is no longer just knowledge about the world, but a description of what the model is, how it should behave, what its language is, what roles, rules and restrictions it has.
For example, if you change the language in the config, that’s not some magical reflashing of the model. You’re just changing a piece of text in the system prompt that says: this user prefers such-and-such a language. That’s it. The model may pay attention to it, or it may not. Sometimes it will still drift into English or another language, because it’s an instruction, not hard wiring.
The same goes for all the descriptions of the environment. It might say that you’re a technical agent, you have access to such-and-such tools, you must act in such-and-such a way and observe such-and-such restrictions. All of it is just a big body of instructions.
There’s also a separate layer, the behavioural frame. For myself I sometimes call it the model’s “soul”, loosely speaking. The point is that language statistics alone are no longer enough. If a model is pre-trained on the internet, and the internet has a huge amount of aggression, war, violence and other noise, then it has to be told separately what’s considered acceptable in the human world and what isn’t. It’s not just a list of bans along the lines of “don’t give out the recipe for gunpowder”. It’s more an attempt to pass on a set of behavioural norms to the model, the way parents pass them on to a child: better not do it like this, better do it like that.
Memory: from personalisation to a project’s working memory
When memory first appeared, it looked like a fairly raw personalisation mechanism. ChatGPT could pick up some facts about you and put them into memory. The problem was that far too much rubbish often ended up there.
With Claude Code the story went a bit further. It got a mechanism called dreaming. And I find this thing very interesting. Before that, its memory worked in roughly the same way: you do something, mention to the system in passing that you’re on Linux, that you’re in a different time zone, that something works worse in Safari, and it stores this as a log: date, time, entry, date, time, entry.
Then they added dreaming. It’s an experimental mode that simulates something like the REM phase of sleep. When activity is low, the agent takes this log and starts repackaging it: what’s important, what isn’t, what should go into structured memory and what can stay in the raw log. In the end, a simple dump of entries turns into more or less decent indexing.
I like this much more than the old memory, because there’s less rubbish. The agent doesn’t drag the whole raw log into the active context. It brings structured memory, and if it needs specifics, it can go deeper for them.
At the same time, exactly how it decides what’s important and what isn’t is not fully transparent. My impression is that repetition plays a role, possibly stress signals, certain features of behaviour. I’ve seen discussions and small studies suggesting that aggressive or emotional wording can also leave a mark on how the system ranks importance. I won’t claim this is literally true, but as a hypothesis it’s quite widely discussed.
Tools: the hidden price of agency
When people start working with agents, they often don’t realise how much tools add to the cost.
Tools are everything the agent has to be able to do: work with files, search code, call bash, do web search and web fetch, run planning, talk to other agents, search messages, pass on commands and so on. For the agent to be able to use all this, it all has to be described.
And that description takes up context. A lot of context. That’s exactly why an agent system costs more than an ordinary chat right from the start. You haven’t really done anything yet, and you’ve already spent tokens on the system prompt and the definitions of all these tools.
This leads to a separate problem: MCP servers. They’re useful in themselves, but each such server also has weight. If you connect lots of MCP servers, especially heavy ones, you simply eat up your own context. I’ve seen estimates where a single GitHub MCP can weigh roughly as much as all of Claude Code’s built-in tools put together. So MCP orchestration is no joke at all. If you use this a lot, it’s worth occasionally just opening the context and having a look: have you bolted on too much?
Skills: a new format for passing knowledge to an agent
Skills have essentially become a new format of prompting. Before, you carried knowledge over into the prompt by hand every time. Now you can wrap it up in a skill.
A skill has a name, a description, a list of available tools and rules for when to call it. And, importantly, what usually gets loaded into the context is not the whole skill but its metadata. So the model knows the skill exists, what it’s responsible for, when to call it and what it can use. Thanks to this you can keep lots of skills and not kill the context with their full volume straight away.
Claude, for example, has Skill Creator and Evaluator. Creator helps you put a skill together. Evaluator can run a comparison in a sandbox and show whether there’s any meaningful effect at all: whether the task works better with the skill than without it, whether the skill can be improved, how much of a gain it really gives.
And yes, I can already see people starting to sell knowledge precisely in the form of skills. A marketer, say, can go beyond giving advice personally: they can wrap their approach into a skill and sell it to a company as a product. In terms of scale this makes sense: the agent gets its consultation not from the person but from that person’s packaged knowledge.
Project instructions: Claude.md, Agent.md and syncing
Every repository of mine has a project Claude.md. It’s not a giant wall of text but more of an index: where the design system is, where the architecture is, where the product questions are, how the pipeline works, where to look for what. I want it to be the one main point of reference for the project.
There’s a root Claude.md, there’s a project one, and you can also put files in subfolders, but I usually don’t. I don’t like spreading control across different levels, because later it’s harder to clean up and keep in sync.
Since I work with different agents from time to time, I have a hook that, whenever Claude.md changes, copies the changes into Agent.md and similar files for other systems. So I deliberately keep these instructions in sync. Not because it’s neat, but because I don’t want to explain to the agent every time: “Please go and read that file over there.” If I can make sure everyone already has the information they need in the same form, that’s what I do.
Could this be solved with symlinks? Possibly. I just didn’t dig into it deeply enough and solved the problem more crudely: with a separate sync skill that copies changes line for line.
Subagents aren’t for show, they’re for isolating context
A very important topic is subagents.
Originally subagents weren’t meant to create a nice org chart of roles, but to isolate context. It was a very pragmatic mechanism. Instead of dragging the whole internet or an entire code search into the main window, you create a separate session, a separate worker that runs off to the right place, reads, searches and brings back only the high-signal result.
Later this grew into roles, characters, teams, skill-like agents, but the basic goal was very simple: don’t clog up the main context. That’s exactly why I have a load of subagents for different tasks: lead designers, testers and so on. But I still see them first and foremost as a mechanism for isolation and filtering.
So a subagent isn’t just “one more clever helper”. It’s a way of not pushing everything through one shared window.
How the agent loop really works
An ordinary chat finishes its work the moment it has given you an answer. An agent doesn’t work like that.
If you’ve given it a task, for example to find something in a repository, the model first gets the whole context: the system prompt, memory, Claude.md, tools, skills, messages, everything it needs. Then it starts generating the tokens of its answer. If along the way it turns out that a tool is needed to solve the task, it goes to the tool definitions, picks a suitable one, say bash, checks permissions, calls the tool, gets the result and then… sends all of it to the model again to be recalculated.
That’s the loop.
An agent works in a cycle: get the task, think, pick a tool, get the result, run it through the model again, check again whether another tool is needed, and only then render the final answer.
That’s exactly why agency is expensive. Each such cycle isn’t a “small action” but a new run of a big context through the system.
Hooks, the status line and compact
Another underrated part of the architecture is hooks.
The status line is a hook too. It’s tied to input and output, updates when the model answers, and lets you display useful telemetry: limits, the context window, time left until peak hours, uncommitted changes and much more.
Memory reload is tied to a hook too. So is dreaming. So is auto-compact.
Compact is a very important thing in general. When the context fills up to a certain threshold, a hook fires and says: time to compact. In essence, the agent takes the session history, collapses it into a shorter summary according to its own rules, and carries on working not with the full history but with its compact version.
You can also call compact by hand. And if you do it not just with the compact command but with an extra instruction, you can influence what exactly it keeps in more detail. For example, you can say: the last part is more important, keep it in more detail. Then the compact you get is no longer the standard one but tailored to your task.
Why agent systems get expensive so fast
When companies move to agents, they very quickly realise that a person using an ordinary chatbot and a person using an agent like Claude Code are on completely different levels of cost.
If the agent hasn’t understood the task, or the task is badly packaged, the loop can spin twenty or thirty times. And each pass sends the whole context to the model again: the system prompt, tools, servers, skills, messages, documents, everything.
Because of this, the agent doesn’t just get more expensive. It also starts getting dumber as the overspend grows, especially if limits and thinking have already been squeezed. So companies have an objective interest in making agents a bit lazier and a bit less generous with depth of thinking. If the quality of answers can be lowered not to the point of disaster, but from 99% to 95%, for a corporation that can already mean savings in the billions.
That’s an unpleasant but important reality of agent systems.
The cache isn’t just a speed-up, it’s the economic foundation of the whole system
Without the cache, working with agents would cost many times more.
Every time you start a new session, a big chunk of context goes into the cache: the system prompt, tools, Claude.md, memory and so on. The first write to the cache costs more, but subsequent requests for the same data are much cheaper. That’s exactly why repeated work within one session is much lighter for the system and the provider than starting everything from scratch.
At the same time, the cache breaks when things change. If you’ve changed some layer higher up, for example a system parameter like web search true/false, the hash of the token set changes, and the parts below it have to be recalculated from scratch.
So it’s important to understand that the cache isn’t an abstraction but something that directly affects both money and limits. If in the morning you open the continuation of a very long session, you can instantly burn a huge chunk of your limit just by reloading all that accumulated context.
A beginner and a context engineer think differently
When people first start working with agents, they usually talk to them like an ordinary chat. They write: “make a function”, “write this thing”, “fix this”. They don’t build a system around the agent.
A good context engineer, on the other hand, does build a system. They think about memory, the cache, skills, subagents, MCP, project docs, hooks, permissions, agent teams, what lies in the root of the repository and what shouldn’t be dragged into the window at all.
In essence, that’s the difference between a person who simply talks to a model and a person who knows how to build a working environment for it.
I really like a formulation someone in the audience suggested: it’s the ability to move from the big picture to the details. But I’d add that it’s also the ability to gather the right context around a task, rather than just hoping for a lucky wording of the request.
The final formula
If you squeeze all of this into one formula, it’s very simple:
a good result = the minimum necessary set of high-signal tokens.
It looks simple, almost like a school formula. But behind it hides enormous complexity: how exactly to pick out those tokens, how not to drown in noise, how not to bloat the context, how not to break the cache, how not to spend reasoning on rubbish, how not to clog up the main loop with things that can be moved into a subagent, tool, memory or skill.
And that, really, is the whole idea. Context engineering isn’t a search for a magic phrase. It’s managing the model’s attention, its working environment, memory, tools, cost and the likelihood of the outcome you need.
If you really want to learn to work with agents, don’t treat them as a rubbish tip where you can dump everything. Look at what’s actually in your project, how memory is set up, whether there’s rubbish in your instructions, whether you need skills, whether subagents make sense, what’s happening with the cache, what your context is made of. Most people never even get to this layer of understanding.
And without it, there won’t be good context engineering.
Conclusion
In the end it all comes down to a fairly simple idea: don’t try to beat the model with one “brilliant” prompt. That’s almost always an illusion.
You need to be able to build the right system for it: what’s in its head from pre-training, what’s in the system prompt, what it pulls from memory, which tools and MCP servers you’ve bolted on to it, which skills it can call, how your files are organised, where you need a subagent, where you need compact, and where it’s better to just start a new session.
That’s what context engineering is.
And the sooner it stops being a set of “magic words” for people and becomes a normal engineering discipline, the sooner truly strong and stable results will appear.





