Context Engineering Guide for Claude Agents
A practical context engineering guide for Claude agents: memory offloading, compaction vs isolation, Head+Tail budgeting, and attention degradation fixes for CCA-F prep.
By Solomon Udoh · AI Architect & Certification Lead

Context engineering is the discipline of deciding what information Claude sees, when it sees it, and in what form, so that every token in the context window earns its place. This context engineering guide covers the full stack: memory offloading, compaction techniques, isolation thresholds, attention degradation, and context interfaces. If you are preparing for the Claude Certified Architect, Foundations exam (CCA-F), Domain 5 (Context Management and Reliability, 15%) and Domain 1 (Agentic Architecture and Orchestration, 27%) both test these ideas directly.
What exactly is context engineering, and why does it matter?
Context engineering is not prompt engineering. Prompt engineering shapes the instruction; context engineering shapes the entire information environment that surrounds it. A well-engineered prompt inside a poorly engineered context will still fail, because Claude's attention is finite and its quality degrades as the window fills with low-value tokens.
The practical stakes are high. The attention dilution problem is real: as context length grows, the model's effective attention per token shrinks. Instructions buried in the middle of a long conversation receive less weight than those at the head or tail. For multi-step agent tasks that run for dozens of turns, this is not a theoretical concern; it is the primary failure mode.
Build for the context window you will have at step 40, not the one you have at step 1.
How does agentic memory work, and when should you offload context?
Agentic memory refers to any mechanism that stores information outside the active context window and retrieves it on demand. The four canonical forms are:
| Memory type | Storage location | Retrieval mechanism | Best for |
|---|---|---|---|
| In-context | Active window | Always present | Short tasks, critical facts |
| External / file-based | File system, database | Tool call (read, search) | Long-running tasks, large corpora |
| Summarised | Injected summary block | Compaction + re-injection | Session continuity across resets |
| Subagent-isolated | Separate agent context | Delegation | Parallel workstreams |
For multi-step tasks, the decision rule is straightforward: if a piece of information will be needed in fewer than three future turns, keep it in-context. If it will be needed sporadically across a long session, write it to an external store and retrieve it via a tool call. This is the principle behind summary injection for fresh sessions: rather than carrying a full conversation history, you compact the session into a structured summary block and inject it at the head of the new context.
A minimal external memory write in Python looks like this:
import json, pathlibdef write_agent_memory(memory_key: str, payload: dict, store_path: str = ".agent_memory") -> None:"""Persist a structured memory block to the file-system store."""pathlib.Path(store_path).mkdir(exist_ok=True)target = pathlib.Path(store_path) / f"{memory_key}.json"target.write_text(json.dumps(payload, indent=2))
The corresponding read tool is registered in the agent's tool list so Claude can call it when it needs to recover a fact without that fact occupying permanent window space.
When should you switch from compaction to isolation?
Compaction (summarisation and truncation) and isolation (subagent architectures) are complementary, not competing. The question is which to reach for first.
Compaction is cheaper. It keeps the task in a single agent context, avoids the overhead of spawning subagents, and preserves conversational continuity. The right compaction techniques include:
- Tool result clearing: strip the raw content of completed tool results, retaining only the message structure and a one-line summary. Claude's message history requires the tool result block to exist, but the content can be replaced with a compact representation.
- Progressive summarisation: periodically inject a
<summary>block that replaces the oldest N turns, then drop those turns from the history. - Head+Tail budgeting: always preserve the system prompt (head) and the most recent K turns (tail). Drop middle messages when the window exceeds a threshold.
Isolation becomes the right answer when compaction can no longer preserve task fidelity. A practical threshold: when the active context exceeds roughly 50,000 tokens and the task still has significant work remaining, the cost of attention dilution outweighs the overhead of delegation. At that point, subagent context isolation is the correct architectural move. Each subagent receives only the context it needs for its specific workstream, keeping every agent's window lean.
The stale context problem is a related failure mode: an agent continues operating on facts that were accurate at turn 5 but have been superseded by turn 30. Isolation solves this by design, because a freshly spawned subagent has no stale history.
What is Head+Tail budgeting and how do you implement it?
Head+Tail budgeting is a token allocation strategy that treats the context window as having three zones: a protected head (system prompt and task definition), a protected tail (recent turns), and a droppable middle.
The logic is grounded in how transformer attention works. The model attends most reliably to tokens at the beginning and end of the context. The middle is where lost-in-the-middle degradation is most severe. By actively managing which turns occupy the middle, you reduce the chance that critical instructions are ignored.
A reference implementation:
def apply_head_tail_budget(messages: list[dict],system_tokens: int,max_tokens: int = 100_000,tail_turns: int = 10,) -> list[dict]:"""Retain the tail_turns most recent turns.Drop middle messages until the estimated token budget fits.Caller is responsible for counting tokens; this function uses message countas a proxy for illustration."""if len(messages) <= tail_turns:return messagestail = messages[-tail_turns:]head_budget = max_tokens - system_tokens# In production, replace len() with a real token counter.while len(tail) < len(messages) and len(messages) > tail_turns:messages = messages[:1] + messages[2:] # drop oldest non-head messagereturn tail
In production you replace the message-count proxy with a real token counter (for example, using anthropic.count_tokens or a tiktoken equivalent). The key invariant is that the system prompt is never dropped and the most recent turns are never dropped; only the middle is eligible for removal.
How do context interfaces work in Claude Code?
A context interface is a contract that tells Claude Code what additional specifications or skills it may load, and under what conditions. In Claude Code, this is implemented through the CLAUDE.md hierarchy and the skills directory. A well-designed context interface means Claude can dynamically load a relevant skill file when it encounters a task type it was not pre-loaded for, without human intervention.
The three-level configuration hierarchy in Claude Code (global, project-root, and sub-directory) is itself a context interface: it defines which rules are always present, which are path-scoped, and which are loaded on demand. Keeping this hierarchy clean is the foundation of unsupervised context loading.
A minimal skill frontmatter that enables dynamic loading looks like this:
---name: sql-query-reviewdescription: "Load when the task involves reviewing or generating SQL queries against a relational schema."triggers:- "*.sql"- "schema.prisma"---
Claude Code reads the description and triggers fields to decide whether to load the skill. This is analogous to tool descriptions as a selection mechanism: the description is the signal Claude uses to route attention.
The absence of unit tests for context engineering quality is a genuine challenge. The practical substitute is iterative validation: run the agent against a representative task, inspect which context blocks it used (via tool call logs), and prune anything that was never referenced. Repeat until the context is minimal and the task still completes correctly.
How do you prevent attention degradation as context grows?
Attention degradation is not a binary failure; it is a gradient. The further a token is from the head or tail, the less reliably Claude attends to it. Four mitigations work in practice:
- Anchor repetition: re-state the core task definition at the start of each major phase, not just at the beginning of the session. A one-sentence restatement costs very few tokens and resets the attention anchor.
- Structured context blocks: use XML tags (
<task>,<constraints>,<progress>) to give Claude explicit structural signals. Structured blocks are more reliably attended to than prose paragraphs of equivalent length. - Aggressive tool result trimming: raw tool results are the fastest way to bloat a context window. Trim them to the minimum needed for the next step. See tool result appending for the mechanics.
- Subagent delegation for investigation: when a task requires deep exploration of a large codebase or document set, delegate to a subagent rather than loading all the material into the coordinator's context. The coordinator receives a structured summary; the raw material never enters its window.
Effective context management is not about fitting more into the window; it is about ensuring that what is in the window is exactly what the model needs to take the next correct action.
How do you monitor context adherence in production?
Context adherence monitoring answers the question: is Claude actually using the context you provided, or is it ignoring it? This is distinct from output quality monitoring; an agent can produce plausible-looking output while ignoring critical constraints.
Practical monitoring approaches:
| Signal | How to collect | What it detects |
|---|---|---|
| Tool call audit | Log every tool call and its arguments | Whether retrieval tools are being called as expected |
| Constraint echo | Ask Claude to restate active constraints before acting | Whether constraints are in working memory |
| Structured output validation | Parse output against a schema | Whether output fields match injected context |
| Stop reason inspection | Check stop_reason on every response | Premature termination, max-token truncation |
Stop reason field inspection is particularly important: a stop_reason of max_tokens means the response was cut off, which is a strong signal that the context window is too full. A stop_reason of end_turn with unexpectedly short output may indicate the agent has lost track of its task, a symptom of the stale context problem.
For the CCA-F exam, Domain 5 (Context Management and Reliability) tests exactly these monitoring and recovery patterns. The exam rewards deterministic, root-cause solutions: if context adherence fails, the correct answer is almost always to fix the context architecture, not to retry with the same context and hope for a different result.
How does context engineering map to the CCA-F exam?
Context engineering touches four of the five exam domains. The table below maps the key concepts from this guide to their domain weights.
| Domain | Weight | Context engineering concepts tested |
|---|---|---|
| Domain 1: Agentic Architecture and Orchestration | 27% | Subagent isolation, session management, summary injection, stale context |
| Domain 2: Tool Design and MCP Integration | 18% | Tool result trimming, tool descriptions as context signals |
| Domain 4: Prompt Engineering and Structured Output | 20% | Structured context blocks, anchor repetition, XML tagging |
| Domain 5: Context Management and Reliability | 15% | Head+Tail budgeting, compaction vs isolation, adherence monitoring |
Domain 5 is the most direct, but Domain 1 carries the highest weight and is saturated with context engineering scenarios. Our concept library at /concepts maps all 174 atomic concepts to these domains and task statements, so you can identify exactly which context management patterns you need to master before exam day.
The exam's consistent preference for deterministic solutions over probabilistic ones applies directly here: when a scenario presents a context failure, the correct answer is a structural fix (isolate the subagent, inject a summary, trim the tool results) rather than a model-level retry or a prompt tweak.
Frequently asked questions
What is the difference between context engineering and prompt engineering?
What token threshold should trigger switching from compaction to subagent isolation?
How do I implement tool result clearing without breaking Claude's message history?
Does context engineering appear on the CCA-F exam?
What is the lost-in-the-middle effect and how do I prevent it?
How do I validate context engineering quality without unit tests?
People also ask
What is context engineering for LLMs?
How do you manage context in long-running Claude agents?
What is Head+Tail budgeting in context management?
How does context engineering relate to the Claude CCA-F exam?
What causes context rot in Claude agents?
About the author
AI Architect & Certification Lead
Solomon Udoh is an AI Architect who designs and ships production agent systems on the Claude API and Claude Code. He built AI Skill Certs' adaptive engine and authored its 174-concept knowledge graph, mapping every Claude Certified Architect - Foundations objective to hands-on, exam-aligned practice.
- Designs production multi-agent systems on the Claude API and Agent SDK
- Author of the AI Skill Certs knowledge graph (174 mapped exam concepts)
- Builds with MCP, Claude Code, structured outputs, and agentic loops daily
- Reviews every concept page against the official Anthropic exam guide
You might also like
Ready to put it into practice?
Study every exam concept with an adaptive tutor.