Skip to content
Part 8 of 1080% through the series
8
Part 8February 10, 202617 min read

Context Is the Bottleneck: Managing AI's Most Precious Resource

Code intelligence and the context problem

AI assistants are only as good as the context they receive. How code intelligence tools, domain mappings, and coupling analysis solve the context bottleneck.

I was two hours into implementing a complex feature when I noticed the AI had stopped following its own rules.

Not dramatically. Not obviously. It was subtle, the kind of thing you only catch if you know what to look for. The code it was writing was still functional, but it had stopped using the database query pattern that's been standard in my codebase for months. It was using include statements for relational queries, something explicitly forbidden in my rules because my database client ignores them silently. The data would look right in development and fail mysteriously in production.

I scrolled back through the session. Sure enough, the AI had been following the correct pattern earlier. Two hundred messages ago, it was doing everything right. But somewhere around message one hundred and fifty, the quality started slipping. By message two hundred, it was writing code as if my rules didn't exist.

They did exist. They were right there, loaded at the start of the session. But the session had grown so large that those early instructions had been effectively pushed out of the AI's working memory. The rules were technically present in the conversation history, but practically invisible.

This is the context window problem, and it's the most insidious bottleneck in AI-assisted development. Not because it's hard to understand (it's conceptually simple) but because its effects are gradual, invisible, and devastating.


The Invisible Degradation

Context windows are the amount of information an AI model can "see" at once. Think of it like a desk. You can spread a certain number of documents across it before things start falling off the edges. Every file the AI reads, every message you exchange, every code snippet it generates: all of it goes on the desk. When the desk is full, the oldest documents start falling off. The AI doesn't announce this. There's no warning that says "I've forgotten your database rules." It just quietly stops following them.

This is different from most software limitations, which tend to be binary. A server either handles the load or it crashes. A function either works or throws an error. Context degradation is analog. It's a slow fade, not a sudden stop. Quality at message ten is excellent. Quality at message fifty is good. Quality at message one hundred is adequate. Quality at message two hundred is quietly catastrophic.

The worst part is that the AI doesn't know it's degrading. It's not being lazy or rebellious. It genuinely doesn't have access to the information anymore, or more precisely, the information has been diluted by so much subsequent content that it no longer meaningfully influences the output. The AI continues to produce confident, well-structured responses. They're just wrong in ways that only someone who knows the rules would notice.

I've had sessions where the AI violated the same rule it had been enforcing an hour earlier. I've had sessions where it re-explored files it had already read, because it couldn't remember the earlier exploration. I've had sessions where it made architectural decisions that directly contradicted decisions we'd made together thirty minutes prior.

Every one of these failures traces back to the same root cause: the context window filled up, and critical information got displaced.


Context as a Finite Resource

Most people treat AI context the way most people treat disk space: as if it's unlimited until something breaks. They open a session, start working, and never think about how much information they're accumulating. This works fine for short tasks. It fails catastrophically for complex ones.

The shift that changed my approach was starting to think about context as a finite, precious resource, more like RAM than disk space. Every operation consumes some of it. Every file read, every exploration, every conversation turn. And unlike RAM, you can't just add more. The model's context window is what it is.

Once I internalized this, my behavior changed fundamentally. I stopped asking the AI to "look at the whole directory structure" when I only needed one file. I stopped having long conversational exchanges about approach when a concise instruction would suffice. I stopped letting the AI explore freely when I could point it directly at what it needed.

Every token matters. Not in a theoretical "best practices" way, but in a practical "this will degrade my output quality in forty-five minutes" way.


The Exploration Paradox

Here's where things get genuinely tricky. Good software development requires understanding context. To write a new feature, the AI needs to understand how existing features work. To modify a component, it needs to understand the components around it. To write a database migration, it needs to understand the current schema.

All of this understanding requires reading files. Lots of files. And every file read consumes context.

This creates a paradox: the more the AI understands your codebase, the less room it has for the rules and instructions that ensure it does good work. Deep exploration produces informed but undisciplined code. Shallow exploration produces disciplined but uninformed code. Neither is acceptable.

I hit this wall repeatedly in the early months. Complex features require reading twenty, thirty, sometimes fifty files to understand the full picture. By the time the AI had a thorough understanding of the relevant code, it had consumed so much context that my rules, the patterns, the conventions, the hard-won lessons from past failures, were barely influencing its output anymore.

It was like sending an employee to spend three days studying the company's products, only to discover they'd forgotten the employee handbook in the process. They knew what to build, but they'd lost the standards for how to build it.

I needed a way to get the understanding without paying the context cost.


Subagent Isolation

The solution came from an idea that's simple in concept but transformative in practice: delegation to isolated processes.

Instead of having my main AI session explore the codebase directly, I delegate exploration to separate AI processes (subagents) that run in their own isolated context. In Massu, this is built into the workflow commands --- when /massu-loop needs to analyze blast radius or explore a domain, it delegates to specialized subagents automatically. The main session stays clean. The subagent reads all the files, does all the analysis, and then returns only the relevant findings. Not the full exploration history. Not the raw file contents. Just the distilled results.

Think of it like a research assistant. If you need to understand a complex legal case, you don't read every document yourself. You send a paralegal to review the files and come back with a summary. Your desk stays clear. Your mental bandwidth stays available for the actual decision-making.

The main AI session maintains the rules, the patterns, the current task state, and the conversation history. All the expensive, irreplaceable context. The subagent handles the exploration, absorbs all the raw file content, does the analysis, and produces a compact result. When it finishes, its context is discarded. The main session receives the summary and continues working with full awareness of its rules and standards.

This one change --- isolating exploration from execution --- probably doubled the effective length of my working sessions. I went from quality degradation around two hours to maintaining consistent quality for four, five, six hours of continuous work.


Specialized Agents for Specialized Tasks

Once I had the basic subagent pattern working, something natural happened: I started specializing them.

Different tasks require different kinds of analysis. Reviewing code for pattern compliance requires reading different files and applying different criteria than analyzing the impact of a schema change. Auditing a plan for completeness requires different reasoning than debugging a runtime error.

So instead of one general-purpose exploration agent, I built specialized ones. One agent is optimized for code review: it knows the patterns, knows what violations look like, and produces structured compliance reports. Another is optimized for plan auditing: it reads a plan document, checks each deliverable against the codebase, and reports which items are actually complete versus merely claimed. Another handles schema verification, querying the database, comparing the actual schema against what the code expects, and flagging mismatches.

Each specialized agent carries only the context relevant to its specific task. The code review agent doesn't need to understand the deployment process. The schema verifier doesn't need to know about UI patterns. By narrowing their scope, each agent can go deeper within its domain without running into context limits.

There's another subtlety here that took me a while to appreciate. Specialized agents don't just use context more efficiently; they produce better results. A general-purpose agent doing code review has to balance code review reasoning against everything else it knows and everything else in the conversation. A specialized code review agent has nothing else competing for its attention. It's the difference between asking a generalist "also, check the code" and hiring a dedicated code reviewer.

I currently run about half a dozen specialized agents, each tuned for a specific type of analysis. They're invoked automatically by my protocol system when the relevant task comes up. The main session orchestrates, delegates, receives results, and executes. It never gets bogged down in raw exploration.

There's a cost dimension here too. Not all agents need the same model. I've implemented model tier optimization: adversarial agents that make judgment calls (security review, architecture review, plan auditing) use the most capable and expensive models, because the cost of a missed vulnerability far exceeds the cost of the model. Meanwhile, agents doing search, comparison, and pattern-matching work use more efficient models. The result is that I get the depth of reasoning where it matters most while keeping costs manageable for routine analysis. It's the AI equivalent of knowing when to hire a specialist versus when an experienced generalist will do.


Context Hygiene

Subagents handle the exploration problem, but there's a broader discipline required: context hygiene. The practice of actively managing what's in your context and cleaning it up before it causes problems.

The most important hygiene practice is clearing context between unrelated tasks. If I finish implementing a feature and need to switch to debugging an unrelated issue, I don't just keep the same session going. I save the current state, start fresh, and load only the context relevant to the new task.

This feels wasteful. Starting a new session means losing all the context from the current one. But that's exactly the point. The context from the feature implementation is irrelevant to the debugging task. Keeping it around doesn't help; it actively hurts, because it fills the window with information that competes with the debugging context for the AI's attention.

Another hygiene practice: compact session summaries. Instead of letting a full conversation history accumulate, I periodically save a structured summary of what's been decided, what's been done, and what's still pending. The summary is a fraction of the size of the full history but captures everything that matters. If the session needs to be restarted, the summary provides a clean, efficient foundation.

I also archive session state proactively. In Massu, this is the session state file (.claude/session-state/CURRENT.md) --- a structured document that gets updated after significant decisions, failed attempts, file modifications, and task pivots. Before a session gets large enough for degradation to set in, I save the current state to this persistent file. This serves two purposes: it creates a checkpoint I can recover from, and it forces me to articulate what's actually important, which is itself a useful exercise that clarifies thinking.

The discipline of context hygiene is unsexy. There's no dramatic moment where it saves the day. It's more like brushing your teeth: invisible when you do it, painful when you don't. But the cumulative effect is enormous. Sessions stay productive longer. Quality remains consistent. And I spend dramatically less time debugging issues that were caused by context degradation rather than actual code problems.


Recovery from Context Loss

Even with good hygiene, context loss happens. Sometimes the system compacts the conversation automatically, summarizing the full history into a compressed form to make room for new content. Sometimes a session crashes. Sometimes you simply have to start fresh.

The question is: what happens next? Without a recovery protocol, the answer is "you lose everything and start over." The AI doesn't remember the decisions you made. It doesn't remember the approaches you tried and abandoned. It doesn't remember the specific configuration of the current task.

This is where persistent state becomes critical. I maintain a structured state file that captures the current task, key decisions and their rationale, recent changes, known issues, and failed approaches. When a session starts or recovers from compaction, the first thing it does is reload this state file. Not as a suggestion, but as a mandatory protocol step.

The recovery protocol is specific about what gets loaded and in what order. First, the core rules: the patterns and conventions that govern all work. Second, the current task state, covering what's being built, what's been completed, what's pending. Third, domain-specific patterns relevant to the current task. Fourth, recent failure history, capturing what's been tried and didn't work, so the AI doesn't repeat failed approaches.

This ordering matters because if the recovery itself consumes too much context, you're back to the original problem. Loading everything from every previous session would be counterproductive. The priority ordering ensures that the most critical information gets loaded first, and less critical information gets loaded only if there's room.

I learned this the hard way. My first recovery protocol tried to reload everything: full conversation histories, complete exploration results, entire plan documents. It worked, technically, but by the time all that context was loaded, there was barely any room left for actual work. The recovery consumed the resource it was trying to protect.

The current protocol is surgical. It loads the minimum necessary context to resume productive work. Everything else stays in persistent storage, available if needed but not consuming precious context window space by default.


Token Budgets and Prioritization

The recovery protocol hints at a broader concept that took me months to fully develop: token budgets.

When you're injecting context into an AI session, whether at startup, after compaction, or during a task, you can't inject everything. There's a finite budget, and you have to decide what's worth spending it on. This is essentially a prioritization problem, and getting the priorities wrong can be worse than loading no context at all.

My system uses a tiered priority scheme. The highest priority is active task context: what's being built right now, what's been completed, what's blocked. This always gets loaded first because it's immediately actionable.

Second priority is failure history. If the AI tried an approach that didn't work in a previous session, that information is more valuable than almost anything else. Without it, the AI will waste time and context re-exploring the same dead end. Failed attempts are expensive to repeat and cheap to remember.

Third priority is relevant patterns and conventions. These are the rules that govern how code should be written in this specific part of the codebase. Not all rules, just the rules relevant to the current task.

Fourth priority is broader codebase knowledge: how related systems work, what the overall architecture looks like, recent changes that might affect the current task.

Everything below that threshold stays in storage unless specifically requested. Historical decisions from weeks ago, completed task archives, exploration results from unrelated features --- all valuable in the right context, but not valuable enough to consume tokens that could be used for current work.

The budget system also applies to runtime context injection. When the AI needs historical information mid-session (say, details about a past implementation decision) the system retrieves the relevant records but applies a token limit to the injection. If ten historical records match the query but only three fit within the budget, it loads the three most relevant ones and notes that additional records exist. The AI can request more if needed, but the default is to be conservative with context consumption.

This sounds like a lot of overhead, and it is, to build. But once built, it runs automatically. I don't manually decide what to load or how much context to allocate. The system handles prioritization based on the current task, and I only intervene when something unusual requires manual context injection.


Warning Systems

The final piece of context management is early warning. If you only discover context degradation after the AI has been producing bad code for thirty minutes, you've already lost. You need to catch it before quality drops.

My system includes automated detection that monitors session size. When the conversation exceeds a threshold, measured in total tokens accumulated, it surfaces a warning. Not a subtle log entry. A visible, impossible-to-ignore alert that says: your context is getting large, consider clearing, delegating, or archiving before quality degrades.

The threshold isn't arbitrary. I calibrated it through painful experience, tracking the point at which I started noticing quality drops across dozens of sessions. The number varies by task complexity, but there's a reliable inflection point where more context starts hurting more than it helps.

The warning gives me options. I can clear the session and start fresh with a summary. I can delegate the remaining work to a subagent. I can archive the current state and continue with a lighter context. Or I can acknowledge the warning and continue, accepting the risk; sometimes you're five minutes from finishing a task and it's worth pushing through.

The key is that the choice is conscious. Without the warning, degradation is invisible. With it, I'm making an informed decision about whether and how to manage the resource.

I also built warnings for a subtler problem: context pollution from tangential exploration. If the AI starts reading files that aren't directly relevant to the current task (maybe it's trying to understand a related system, or it went down a rabbit hole during debugging) the session state tracker notes the drift. This isn't necessarily bad, but it's context being consumed on something that may not contribute to the immediate goal.


Why This Matters More Than Most People Think

Context management is not a topic that generates excitement. It's not as dramatic as building new features or as satisfying as squashing a nasty bug. It's infrastructure work: invisible when it's working, catastrophic when it's not.

But here's what I've learned after months of building with AI: context is the single largest determinant of output quality, and it's the thing that gets the least attention.

People obsess over prompt engineering, the exact words used to instruct the AI. They obsess over model selection, which AI is "best" for coding. They obsess over tool integration, connecting the AI to the right APIs and databases. All of these matter. None of them matter as much as whether the AI can actually see and remember the information it needs to do good work.

A perfectly crafted prompt in an overloaded context produces mediocre results. A simple instruction in a clean, well-managed context produces excellent results. I've seen this play out hundreds of times. The quality of the context trumps the quality of the prompt, every time.

This is why I've invested so heavily in the systems described in this article. Subagent isolation, context hygiene, recovery protocols, token budgets, warning systems --- none of them are glamorous. But collectively, they're the reason I can run multi-hour development sessions that maintain consistent quality from start to finish. They're the reason the AI follows its rules at message three hundred as reliably as it does at message three. They're the reason I can build complex features without the quality degradation that plagues most AI-assisted development.

Managing context is managing quality. They're the same thing.

All of the context management systems described in this article --- subagent isolation, session state persistence, recovery protocols, token budgets, and warning systems --- are built into Massu's open-source core. They run automatically through the lifecycle hooks and workflow commands.

What the local system can't show you is the bigger picture over time: how your context usage trends across sessions, which types of tasks cause the most degradation, and where your quality inflection points are. Massu Cloud Pro's analytics dashboard tracks these patterns, giving you visibility into session history, quality trends, and AI cost intelligence. It's the difference between managing context in the moment (which the free core handles) and understanding your context patterns over time (which the dashboard reveals). But the core context management --- the part that actually prevents degradation in real time --- is free.


What's Next

In the next article, I'll step back and look at the big picture: what it actually means to be a solo operator producing enterprise-grade software, the economics of AI-assisted development, and why the gap between AI-augmented builders and traditional teams is widening in ways that create extraordinary opportunities for anyone willing to invest in the system.


This is Part 8 of a 10-part series on building enterprise software with AI:

  1. How I Stopped Vibe Coding and Built a System That Actually Ships
  2. The Protocol System: How I Turned AI From a Chatbot Into a Development Partner
  3. Memory That Persists: How I Made AI Actually Learn From Its Mistakes
  4. The Verification Mindset: Why "Trust But Verify" Is Wrong When Building With AI
  5. Automated Enforcement: Building Hooks and Gates That Catch Problems Before You Even See Them
  6. The Incident Loop: How Every Bug Makes Your AI Development System Permanently Stronger
  7. Planning Like an Architect: Why AI Needs a Blueprint Before Writing a Single Line of Code
  8. Context Is the Bottleneck: Managing AI's Most Precious and Most Fragile Resource (this article)
  9. Solo Worker, Enterprise Quality: The New Economics of AI-Assisted Development
  10. The Knowledge Graph: Teaching AI to Understand Your Codebase as a Living System

I'm the Co-founder and COO of Limn, where we create luxury furniture and fixtures for large-scale architectural and building projects. Alongside the physical work, we design the systems required to manage a complex, global lifecycle --- from development and production to shipping and final delivery. The governance system I built for Limn's software is now Massu AI, an open-source AI engineering governance platform.

Imagined in California. Designed in Milan. Made for you.

Here, I share what I've learned about making AI development actually work in the real world.

Have questions or want to share your own AI development setup? I'd love to hear from you in the comments.

Context management, handled

Massu manages context automatically --- subagent isolation, session state tracking, and recovery protocols keep quality consistent even in multi-hour sessions.