# Context Engineering for AI Agents

An agent does not have a brain outside its context window. Everything it knows about the task, the world, and what it has done so far exists in that one rectangle of tokens. When the window is clean and purposeful, the agent reasons clearly. When it is bloated or stale, it halts, loops, or drifts.

This is not about reducing cost, though good context engineering does that. It is about giving the agent a working memory that matches the task.

## The window as working memory

A language model has no persistent state between calls. Every time the agent loop runs, the model reads the entire context from scratch and decides what to do next. That is the fundamental fact everything else builds on.

Think of the window as a whiteboard. The agent reads the whole board before every move. A cluttered whiteboard slows you down. A whiteboard with only the current task on it helps you think.

The practical ceiling for most agent runs is not the model's token limit. It is the point where the signal-to-noise ratio drops enough that the model starts making avoidable mistakes. That threshold arrives long before the limit.

## What should you load into the context window and what should you leave out?

The question for every piece of content is: does the model need this to complete the current step?

| Load it | Leave it out |
|---|---|
| The task description, precise and complete | Background the agent will never act on |
| Constraints: rules, schemas, output format | Unrelated files, even if "related" to the project |
| Files the current step will read or edit | Files from earlier steps the agent has already finished |
| The last few tool results | Full tool output when a summary suffices |
| Examples when the format is ambiguous | Examples that duplicate the task description |
| Error messages, verbatim | Log dumps: paste the relevant excerpt, not the file |

The trap is inclusion by relevance rather than necessity. A file can be relevant to the project and completely unnecessary for this step. Load only what this step needs.The mistake that bites hardest here is padding the window with a whole directory or schema "so the model has the full picture," because a long context feels safer than a short one. It is not: the extra tokens dilute attention so the model underweights the three files the step touches, and the run gets slower, pricier, and less accurate at once. Ask "does this step need it to act?" for each piece and drop everything that fails the test.

## Retrieval over stuffing

Stuffing is loading everything that might help and hoping the model finds what it needs. Retrieval is fetching only what the current step requires, at the moment it is required. For when to retrieve and when to paste, see [context injection vs. stuffing the window](/guides/context-injection-vs-stuffing).

Stuffing feels safe, but a 400k-token context with twenty files crammed in costs more, responds slower, and produces worse results than a 15k-token context with the three files the step touches. The model attends to the beginning and end of a long context more strongly than to the middle. Content buried in a swollen context is underweighted precisely when you need it most.

Retrieval-based agents load context incrementally. At each step, the agent asks: what do I need to see to take this action? It reads those things, acts, and moves on. The window stays tight because it reflects the current step, not the entire project.

## What does a well-shaped agent context look like?

Every agent context has the same logical layers. The shape matters as much as the content.

Stable content (A and B) goes at the top. It changes rarely, which makes it a good candidate for prompt caching. Dynamic content (D and E) goes at the bottom and changes every turn. Task-specific content (C) sits in the middle: stable within a step, replaced when the step changes.

This ordering is not arbitrary. Caches break the moment content changes. If your system prompt is at the top and never changes, it hits the cache from the second call onward. If your dynamic content is mixed into the top, nothing caches reliably.

## How do you give an agent memory across long runs?

A single-step agent is simple. An agent running for twenty steps faces a new problem: the history of earlier steps accumulates in the window and eventually crowds out the information the current step needs.

Three patterns address this.

**Summarise and continue.** At a natural checkpoint, have the agent write a compact summary of what it has done, what it decided, and what remains. Replace the raw history with that summary. The agent keeps the essential working context at a fraction of the token cost.

**Episode boundaries.** When a long task has distinct phases (gather, plan, implement, verify), treat each phase as a separate context. Load the summary of the previous phase as the opening context for the next. The window is always fresh at the start of a phase.

**External memory.** For very long runs, write completed decisions and findings to an external store (a file, a database, a notes file in the repo). The agent reads from it selectively, the same way it reads any other document: only the part it needs now. See [giving your agent memory across steps](/guides/agent-memory-and-state) for the pattern in full.

The pattern that does not scale is letting history grow unbounded and hoping the model tracks it. Beyond a few thousand tokens of accumulated tool results, quality degrades noticeably.

## How should you order context for prompt caching?

Prompt caching can cut the cost of a long-running agent significantly, but only if your context is ordered to take advantage of it.

The rule: stable content first, dynamic content last.

```
[System prompt + rules]     ← never changes, cache on first call
[Static reference docs]     ← changes rarely, cache per session
[Task-specific files]       ← changes per step, cache within a step
[Tool results + history]    ← changes every turn
[Current message]           ← always new
```

If you mix a dynamic timestamp or a per-request ID into your system prompt, nothing above it caches. If you put frequently-changing files before rarely-changing docs, the rarely-changing docs lose their cache benefit. The order you choose is a caching decision as much as a readability decision.A broken prompt cache throws no error, just a quiet cost and latency regression you only spot on the bill. One per-request value (a timestamp, a session ID, a "current time" line) high in the prompt invalidates everything after it, so keep those values down in the dynamic tail with the history.

## What are the failure modes of a bloated context?

Recognising these helps you step in before the agent goes off the rails.

**Attention dilution.** The relevant instructions are in the window, but they are buried in the middle of a large context. The model follows the wrong instructions because the right ones are underweighted. Fix: move critical constraints to the top and bottom. Prune everything else.

**Stale context drift.** The agent decided something in step 3. It is now step 15, that decision is outdated, and the raw history is still in the window. The model acts on the old decision. Fix: summarise and compact at phase boundaries.

**Tool result flooding.** A tool call returned a 50k-token file. The agent read it, used one function from it, and moved on. The file is still in the context, inflating every subsequent call. Fix: after using large tool output, summarise the relevant part and let the raw output drop from history.

**Contradictory instructions.** The system prompt says one thing, a later message says the opposite. The model makes an arbitrary choice. Fix: when you update a constraint, remove the old one. Never leave both in the window.

**Context poisoning.** In multi-agent systems, a subagent's context can include adversarial content from external sources (a document, a web page, a database row) that attempts to override the agent's instructions. The model may follow those instructions because they are in the window. Fix: keep tool results clearly delimited from instructions. Never let external content appear in the instruction region of the window.

## Heuristics for agent context

These apply regardless of which agent framework or model you use.

**Brief per step, not brief per task.** Write the agent's current instruction as if it is starting fresh on this step alone. Include what the step needs. Exclude everything it does not.

**Measure the window before a long run.** Estimate how many tokens your system prompt, reference docs, and typical tool results consume. If a 40-step run will fill the window by step 20, you need a compaction strategy before you start, not after.

**Tool definitions are tokens.** Every tool the agent can call adds its schema to the window. Register only the tools needed for the current phase. A retrieval-heavy phase needs different tools than a code-editing phase.

**One source of truth per constraint.** If a rule appears in the system prompt, it should not also appear in the task message. Repetition wastes tokens and creates contradiction risk. Put each rule in one place.

**External memory beats in-context memory for facts that do not change.** A decision made in step 2 that will still be true in step 30 is better stored in a notes file than in a growing context. The agent reads it when it is relevant, not on every turn.

**Prefer precise to comprehensive.** A system prompt that says "output valid JSON matching this schema: `{...}`" is more useful than three paragraphs explaining the importance of consistent formatting. The model executes precision better than it internalises elaboration.

## Connecting to subagents

When an orchestrator fans out to subagents, each subagent starts with a fresh context. That is intentional. The subagent does not inherit the orchestrator's window. It gets a brief, builds its own context by reading what it needs, and returns only a result. The [orchestrator-worker pattern](/guides/orchestrator-worker-agents) covers how this division of labour is structured.

This means the orchestrator's context stays clean: it sees outputs, not the twenty files each subagent read to produce them. The subagent's context stays focused: it thinks about its one job, not the whole task.

The discipline is writing subagent briefs that are complete on their own. A subagent cannot ask the orchestrator for clarification mid-run. The brief must contain the goal, the constraints, the output format, and any context the subagent cannot retrieve itself. See [How agents fan out](/guides/how-agents-fan-out) for the full pattern.

## Checklist before a long agent run

- Does the system prompt contain only rules that apply to every step?
- Is static reference material separated from dynamic task content?
- Is content ordered stable-first, dynamic-last for caching?
- Do you have a compaction strategy for when history grows large?
- Are tool definitions limited to what the current phase needs?
- Does each tool result get summarised after use, or does it accumulate raw?
- Is there a plan for external memory if the run spans many steps?

A context built around these questions gives the agent a working memory that matches its task. That is what reliable agent behaviour runs on.
