Skip to main content
Nathan Fennel
Back to Blog

Context Poisoning: The Shakespeare Problem

Why giving your AI coding agent the entire codebase is actually hurting its performance, and why you should treat it like an intern.

Imagine you're trying to recall a specific quote. You know it's from Shakespeare, maybe something about a rose. If I handed you the complete, unabridged works of William Shakespeare (over a million words) and said "find it," you'd be overwhelmed. You'd spend more time flipping pages than thinking about the quote itself.

However, if I handed you just Romeo and Juliet (or even better, Act II, Scene 2), you'd find "A rose by any other name would smell as sweet" in seconds.

This is exactly what happens when we "dump" our entire codebase into an AI coding agent context window. We think we're being helpful by giving it everything, but we're actually confusing it. This is Context Poisoning.

The Intern Mental Model

The best way to think about an AI Coding Agent isn't as a supercomputer that instantly knows everything. It's better to think of it as a bright, eager, but completely new junior intern.

If you hired a new intern to fix a bug in your payment processing logic, would you:

  1. Send them the link to the entire 5GB repository and say "The payment is failing, fix it."
  2. Tell them "Hey, users are seeing error 500 on checkout. It usually happens in CheckoutController.ts, specifically around line 45 where we handle Stripe callbacks. Here are the logs."

If you chose option 1, your intern (and your AI) will spend hours reading unrelated code in the 'About Us' page footer, the CSS for the login modal, and your CI/CD pipeline configuration, none of which helps them fix the payment bug.

By the time they find the relevant file, they are mentally exhausted (or in AI terms, they have filled their "attention" with irrelevant noise).

Specificity is Speed

When dealing with an intern, you provide:

  • The specific file where the problem likely exists (or at least where to start).
  • The exact error message or user report.
  • What you've already tried.
  • Relevant context only (e.g., "We use Stripe, not PayPal").

This is exactly what you should provide to an AI Coding Agent to have a high chance of success.

The Technical Reality: "Lost in the Middle"

This isn't just an analogy; it's a documented technical phenomenon. Research into LLMs has identified a problem known as "Lost in the Middle".

When an LLM is given a massive amount of context (like dumping 100 modules or a massive distributed monolith context), it tends to focus very well on the beginning of the prompt (your initial instructions) and the end of the prompt (your most recent question). But the information buried in the middle? It often gets ignored or hallucinated.

By stuffing your context window with every file in your project:

  1. You dilute the signal. The 50 lines of code that actually matter are drowning in 50,000 lines that don't.
  2. You increase latency. Processing more tokens takes longer.
  3. You increase cost. You're paying for every token of that irrelevant code.
  4. You increase error rates. The AI might hallucinate a connection between your payment logic and that legacy inventory sync job nobody has touched since 2019 just because they were both in the context.

The Context Recipe

Want to stop confusing your AI intern? Here offers a detailed, step-by-step recipe for success that ensures you are getting the most out of your AI-driven development workflow:

1. Curate, Don't Dump Resist the urge to drag-and-drop your entire folder into the chat window. While it feels efficiently lazy, it actively harms the reasoning capabilities of the model. Instead, valid advice from the Claude Code Best Practices guide and on context management suggests you should ruthlessly select only the 2-3 files that are directly relevant to the bug at hand. If you're fixing a button, give it the button component and the page it lives on, not your database schema, your entire API layer, and your grandmother's secret cookie recipe. By narrowing the scope, you force the AI to focus its limited "attention" on the actual problem space, reducing hallucinations and irrelevant suggestions. Think of every token as a weight. When you overload the context with irrelevant libraries or utility functions, you aren't just wasting credits; you are flattening the attention mechanism's ability to distinguish signal from noise. It’s analyzing the syntactic relationship between your bug and the unrelated code, wasting compute cycles on connections that don't exist contextually.

2. Be Specific & Outcome-Oriented Vague goals lead to vague code and frustrating back-and-forth cycles. Use system instructions (or just clear, structured prompting) to define exactly what you want the final state to look like. Try a detailed instruction like "Update the onClick handler in Button.tsx to log an error event to Sentry before throwing the exception." This provides constraints and a clear definition of done, allowing the AI to generate code that fits your specific architectural patterns and your intent. Consider that "correct code" is highly subjective. To an AI, a hacky one-liner and a robust, tested function are both statistically valid completions. By explicitly defining the outcome (mentioning specific libraries, error handling patterns, or performance constraints) you narrow the search space of possible solutions, preventing the model from defaulting to the path of least resistance or generic internet examples.

3. Provide "Evidence" Your intern can't fix a bug they can't see, and neither can an AI. Always include the error logs, stack traces, or screenshots in your initial prompt. This gives the AI a concrete pattern to match against the provided code, acting as a technical "north star" for its reasoning process. Without this evidence, the AI is essentially guessing at the root cause based on file names and variable types. providing the generic "evidence" transforms the task from an open-ended creative writing exercise into a solvable logic puzzle. The stack trace provides a grounding truth that anchors the model's hallucinations. The AI can map the exact line numbers and error types to the abstract syntax tree of the provided code. This transforms the problem from "generative coding" to "analytical debugging," which is a fundamentally more reliable mode of operation for LLMs.

4. Iterate and Expand Start your session small and focused. If the AI gets stuck or asks for more info, that is the perfect moment to iteratively prompt and add more files to the context. This "just-in-time" context strategy keeps the signal-to-noise ratio high and prevents the model from getting lost in the weeds before it even starts. It mirrors how a senior engineer navigates a codebase: starting with the symptom and tracing the path outwards—the same way a senior engineer would. This approach also saves you from the "needle in a haystack" degradation. Modern models are powerful, but their recall accuracy drops as the context size grows. By adding files only when necessary, you ensure that the most critical information (the code you are currently discussing) remains at the forefront of the model's attention window.

5. Reset Often Finally, don't be afraid to clear the context window. If you've gone back and forth 10 times and the AI is checking the same file over and over, its short-term memory is likely polluted with bad attempts and dead ends. Clear the chat, summarize what you've learned, and start fresh. In fact, this is such a critical best practice that Anthropic turned it into a core feature for Claude Code in January 2026. Now, after the "Planning" phase, Claude Code offers to automatically wipe its memory before the "Execution" phase to ensure it builds exactly what was planned without being distracted by the brainstorming process. It’s not giving up; it’s decluttering for success. Remember that these models are autoregressive; they predict the next word based on the entire history of the conversation. If that history contains five failed attempts and three misunderstandings, the model acts like a biased observer, unknowingly steering specifically towards those same failed patterns. Wiping the slate clean forces the model to re-evaluate the problem from first principles, often making the solution immediately obvious.