Context Engineering for AI Coding Agents: 9 Techniques That Actually Work

Nine production-proven context engineering techniques for AI coding agents — system prompt layering, just-in-time retrieval, compaction, subagent isolation, prompt caching, and more. Maps each to the Write/Select/Compress/Isolate framework with real token arithmetic and code examples.

Context windows are growing at a dizzying pace — 100K, 200K, 1M tokens, and beyond — but every engineering team running AI coding agents has hit the same wall: the agent gets dumber as the conversation gets longer. This isn’t a feeling; it’s measured. Chroma’s research on context rot found that performance consistently degrades as context length increases across every major model [4]. Redis replicated the finding: more tokens reliably means worse output [5]. The practical ceiling appears at roughly 1M tokens regardless of window size, and the degradation curve starts long before you reach it.

The response from the leading AI engineering teams hasn’t been to chase bigger windows. It’s been to engineer the context itself. Anthropic and LangChain have converged on a four-operation framework — Write, Select, Compress, Isolate — that turns context from a passive buffer into an active, managed resource [1][2]. Below, nine techniques that actually work, each mapped to its operation, each with real token arithmetic and production data.

The Four Operations at a Glance

Operation Function Token Impact When to Use
Write Craft stable, prefix-friendly system prompts and offload structures Establishes reusable token blocks for caching Session init, memory offload setup
Select Retrieve and surface only what the model needs right now 40–60% reduction vs. full-history dump Every turn — gate what enters context
Compress Distill or summarize existing context when the window fills 70–90% compression ratio Context exceeds 60–70% of window
Isolate Delegate subtasks to ephemeral subagents; return only a summary Subagent context fully discarded after return Complex multi-step operations

Each operation feeds the others. You Write a layered system prompt, Select relevant files, Compress stale history, and Isolate heavy reasoning — then repeat.


Write: Crafting Stable Context

1. System Prompt Layering

The technique: Build your system prompt as a stable prefix containing task constraints, output schemas, and behavioral rules. Separate volatile instructions (file paths, user intent) into the user-turn layer. This turns the entire system prompt into a reusable cache key.

Before: A flat 2,800-token blob with per-request path fragments mixed into static rules. Cache hit rate near zero.

After: A structured 1,200-token system prefix (static) + token-level instructions per turn. With prompt caching, the static prefix hits the cache on every subsequent request in the session — 90% cost reduction, 85% latency reduction [6].

2. Memory Offloading (Write + Select)

The technique: Instead of cramming the entire agent memory into the prompt every turn, offload to an external store (Redis, SQLite, vector DB). Each turn, write a compact index into the system prompt, then Selectively retrieve only the entries needed for the current task. Reversible offload lets you pull back full records on demand; if retrieval fails, fall back to a summarization of the offloaded segment [7].

Before: 8,000 tokens of accumulated conversation history appended to every request — 40% of which is irrelevant to the current task.

After: 400-token index in system prompt, ~600 tokens of retrieved context. Same information surface, 87% fewer tokens per turn.


Select: Gate What Enters

3. Just-in-Time Retrieval

The technique: Treat your codebase as a RAG corpus. Instead of dumping the project tree into context, embed the current task description and retrieve only the files and symbols that match. LangChain’s implementation loads file headers, function signatures, and import maps first, then lazily pulls full bodies on demand [2].

Before: Full project context — 15,000 tokens for a mid-size repo, including files irrelevant to the current edit.

After: 2,500 tokens of targeted context — just the caller chain, the target function, and its direct dependencies. 83% reduction.

4. Tool Result Clearing

The technique: Every tool call returns output — file reads, shell stdout, search results. Most of that output is useless after the model has acted on it. Explicitly clear or truncate tool results after their action is committed. Keep only the last N tool results (typically 3–5) as a rolling buffer.

Before: 12 tool results accumulating across 10 turns — 6,800 tokens of stale ls, grep, and read_file outputs the model already consumed.

After: Rolling window of last 3 results — 1,100 tokens. The model has exactly what it needs to understand the current state, not the history of how it got there.

5. Dynamic Filesystem Context

The technique: This is Cursor’s approach, documented in their token optimization research. Instead of scanning the full workspace, dynamically track which files are open, which symbols are referenced, and which git diffs are pending. Build a live context map and feed only the delta [8].

Before: Full workspace tree + open tabs + last 5 terminal outputs: 9,200 tokens.

After: Active file context + git diff head + symbol references: 4,900 tokens. Cursor reports a 47% token reduction with no measurable quality degradation [8].


Compress: Keep It Lean

6. Context Compaction

The technique: When the conversation approaches the context threshold, compress prior turns into a dense summary. The key insight is to preserve action-outcome pairs rather than natural-language narrative — the model needs to know what happened and what the result was, not how the user phrased the request. Anthropic’s cookbook demonstrates compaction that distills a multi-turn conversation into a high-fidelity, structured summary [3].

import json
from typing import List, Dict, Optional

def summarize_messages(
    messages: List[Dict],
    max_tokens: int = 2048,
    model: str = "claude-sonnet-4-20250514"
) -> List[Dict]:
    """
    Compress conversation history into a structured summary.
    Preserves action-outcome pairs, discards conversational framing.
    """
    # Identify turns that can be compressed (skip system prompt and latest turn)
    compressible = messages[1:-1] if len(messages) > 2 else []
    if not compressible:
        return messages

    # Build a compact representation focused on intent, action, result
    turns = []
    for msg in compressible:
        role = msg["role"]
        content = msg.get("content", "")
        if isinstance(content, list):
            # Extract text from tool result blocks
            texts = [b.get("text", "") for b in content if b.get("type") == "text"]
            content = "\n".join(texts)
        turns.append({"role": role, "preview": content[:200]})

    summary_prompt = {
        "role": "user",
        "content": (
            "Summarize the following conversation turns as a JSON array of "
            "action-outcome pairs. Each entry: {action, result, files_affected}. "
            "Keep the total under 1500 tokens. No filler.\n\n"
            + json.dumps(turns, indent=2)
        )
    }

    # The compressed result replaces all middle turns
    compressed = [messages[0], summary_prompt, messages[-1]]

    # Post-condition: verify compression ratio
    # original_tokens - compressed_tokens / original_tokens >= 0.7
    return compressed

# Usage: call when context exceeds 60% of window
# session.context = summarize_messages(session.context)

Before: 12-turn conversation with tool calls, file edits, and error recovery: ~22,000 tokens.

After: Action-outcome summary (~1,500 tokens) + current turn: ~2,500 tokens. 88% compression while retaining all decision-relevant history.

7. Context Rot Mitigation

The technique: Context rot isn’t a binary failure — it’s a continuous degradation curve [4][5]. The mitigation is structural: if your agent has been operating for more than a few hundred turns, discard everything before the performance inflection point and start a fresh context seeded with the compaction summary. This is distinct from naive truncation (which drops the oldest data) — you proactively compact before the curve steepens.

Before: A 50-turn session at ~95,000 tokens. Performance has visibly decayed: the model misses file paths, repeats tool calls, and hallucinates state.

After: Compacted summary (~3,000 tokens) + last 5 turns (~4,000 tokens). Total: 7,000 tokens. The model acts as if the session just started.


Isolate: Ephemeral Context for Heavy Lifting

8. Subagent Isolation

The technique: When a task requires multiple steps, deep reasoning, or its own tool loop, spawn a subagent with a pristine context. Feed it the relevant context slice, let it work independently, and capture only its final summary (or output artifact). The subagent retains nothing post-return — its entire context is garbage-collected. LangChain’s DeepAgents architecture formalizes this as “context in, summary out, nothing retained” [7].

Before: Monolithic agent handling a 15-step refactor in a single context. Context swells to 40,000 tokens with intermediate reasoning and failed attempts. The agent loses coherence at step 11.

After: Orchestrator delegates two 8-step subagents. Each operates in a <5,000-token context. Orchestrator receives a structured summary from each (300 tokens each) and produces the final merge. Total context load on the orchestrator: ~8,500 tokens.

9. Prompt Prefix Caching (Cache)

The technique: This sits at the infrastructure layer but belongs in every agent engineer’s toolkit. Using Anthropic’s cache_control breakpoints, you can explicitly mark sections of the prompt as cached — the stable system prompt, the tool definitions, frequently retrieved documentation blocks. Subsequent requests that share the same prefix bypass re-encoding entirely.

from anthropic import Anthropic

client = Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=4096,
    system=[
        {
            "type": "text",
            "text": "You are a code engineering agent. Follow these rules:\n"
                    "1. Read before you write\n"
                    "2. Validate syntax after every edit\n"
                    "3. Run tests before declaring completion\n"
                    "4. Never guess imports — check the file first\n"
                    "5. Output all edits as unified diffs",
            "cache_control": {"type": "ephemeral"}
        },
        {
            "type": "text",
            "text": "Today's date: 2026-07-22\n"
                    "Project: codeintel.xyz\n"
                    "Workspace: /home/techgeek/code-intel-blog",
        }
    ],
    messages=[
        {
            "role": "user",
            "content": "Refactor the build pipeline to add a lint step before test."
        }
    ]
)

Before: No caching — every request re-encodes the full 4,200-token system prompt + tools. API cost: $0.032/request at Sonnet rates.

After: System prompt cached at the ephemeral breakpoint. First request pays full cost ($0.032); subsequent requests in the same session pay ~$0.003 for the user-turn tokens only. Over 100 requests, cost drops from $3.20 to $0.61 — a 91% reduction. Latency per request drops from ~4.2s to ~1.1s [6].

(Cache-aware design also synergizes with System Prompt Layering — the two techniques together produce multiplicative savings. The industry estimate is that 20–40% of production prompts are semantically identical or near-identical across requests, making them ideal caching targets.)


The Composite Effect

None of these techniques is silver-bullet sufficient on its own. Their power comes from composition:

  1. Write a layered system prompt that hits the cache.
  2. Select only what’s needed per turn (JIT retrieval + tool clearing + dynamic filesystem).
  3. Compress when the window gets fat (compaction + rot mitigation).
  4. Isolate expensive reasoning into subagents that clean up after themselves.

Teams running all four operations report sustained performance across sessions lasting hundreds of turns — something that was impossible with raw context windows alone. The 1M-token ceiling isn’t a hardware constraint; it’s a signal that context engineering, not context size, is the bottleneck worth solving.


Sources

[1] https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents [2] https://www.langchain.com/blog/context-engineering-for-agents [3] https://platform.claude.com/cookbook/tool-use-context-engineering-context-engineering-tools [4] https://www.trychroma.com/research/context-rot [5] https://redis.io/blog/context-rot/ [6] https://platform.claude.com/docs/en/build-with-claude/prompt-caching [7] https://www.langchain.com/blog/context-management-for-deepagents [8] https://supergok.com/cursor-dynamic-context-ai-token-optimization/

  • ToolBrain — tool reviews, LLM comparisons, and AI workflow guides
  • NoCode Insider — AI workflow automation with no-code tools, agents, and APIs
  • Hermes Tutorials — Hermes Agent setup, configuration, and advanced workflows

Cross-links automatically generated from CodeIntel Log.