---
title: Context engineering
description: "Anthropic defines context engineering as the set of strategies for curating and maintaining the optimal set of tokens during inference. In practice: decide what is in the window at each step, when it arrives, and what leaves. Prompt engineering, choosing the words, is now one part of it."
author: Asem Abdo
course: Agentic Engineering
lesson: Context engineering
url: https://openplanr.dev/learn/agentic-engineering/context-engineering
updated: 2026-10-17
related:
  - https://openplanr.dev/learn/agentic-engineering/agent-loop.md
  - https://openplanr.dev/learn/agentic-engineering/harness-engineering.md
---

# Context engineering

By [Asem Abdo](https://www.linkedin.com/in/asemabdo/) · Updated 2026-10-17

*What the model sees*

Anthropic defines context engineering as the set of strategies for curating and maintaining the optimal set of tokens during inference. In practice: decide what is in the window at each step, when it arrives, and what leaves. Prompt engineering, choosing the words, is now one part of it.

## Everything that competes for the window

Level 1 · The rules

The model sees one stream of tokens. Instructions, tool definitions, examples, history and tool results all share it.

- **Instructions:** System prompt plus project files such as AGENTS.md or CLAUDE.md. Rule: short, specific, at the right altitude: neither brittle if-else logic nor vague slogans.
- **Tool definitions:** Every tool's name, description and schema, sent on every call. Rule: fewer, clearer tools beat many overlapping ones.
- **Examples:** A few canonical cases that show the expected behavior. Rule: diverse and representative, not an exhaustive edge-case list.
- **History and tool results:** Everything said and returned so far. Grows every turn. Rule: the biggest consumer; prune, summarize or isolate it.

## The context window is a budget

Level 1 · The rules

Every token competes for the model's attention and costs money. Prompt engineering is choosing the words; context engineering is choosing what is present at all.

```python check=run title="Where the budget goes in a real session"
window = 200_000
loaded = {
    "system prompt": 3_000,
    "tool definitions": 12_000,
    "AGENTS.md": 2_500,
    "conversation so far": 95_000,
    "tool results": 38_000,
}
used = sum(loaded.values())
print(f"used {used:,} of {window:,} = {used / window:.0%}")
biggest = max(loaded, key=loaded.get)
print("biggest consumer:", biggest)
```

```text title="Output (Python 3.14.8)"
used 150,500 of 200,000 = 75%
biggest consumer: conversation so far
```

```python check=err:ContextOverflowError title="Loading everything up front fails"
class ContextOverflowError(Exception):
    pass

def load(context, doc_tokens, window=200_000):
    if sum(context) + doc_tokens > window:
        raise ContextOverflowError(f"{sum(context) + doc_tokens:,} tokens > {window:,}")
    context.append(doc_tokens)

context = [3_000, 12_000, 150_000]
load(context, 60_000)
```

```text title="Traceback (Python 3.14.8)"
Traceback (most recent call last):
  File "main.py", line 10, in <module>
    load(context, 60_000)
    ~~~~^^^^^^^^^^^^^^^^^
  File "main.py", line 6, in load
    raise ContextOverflowError(f"{sum(context) + doc_tokens:,} tokens > {window:,}")
ContextOverflowError: 225,000 tokens > 200,000
```

> **Watch out:** **Context rot:** as the number of tokens grows, the model's ability to recall and use what is in the window declines. Quality degrades well before the window is full, because stale tool output and old turns dilute attention. Compact or start a fresh session before you get close to the limit, with key decisions saved in files.

## Just-in-time context and progressive disclosure

Level 2 · Why it works

Load the summary always, the detail only when the task needs it. This is how skills work: a one-line description sits in context; the full playbook loads when the task matches.

```python check=run title="Progressive disclosure: what a skill costs before and after it is needed"
skills = {
    "release": {"description": 40, "body": 2_400},
    "pdf-forms": {"description": 35, "body": 3_100},
    "db-migrations": {"description": 45, "body": 1_800},
}

def context_cost(active):
    always = sum(s["description"] for s in skills.values())
    on_demand = sum(skills[name]["body"] for name in active)
    return always + on_demand

print("idle session:", context_cost([]), "tokens")
print("migration task:", context_cost(["db-migrations"]), "tokens")
print("everything up front:", context_cost(list(skills)), "tokens")
```

```text title="Output (Python 3.14.8)"
idle session: 120 tokens
migration task: 1920 tokens
everything up front: 7420 tokens
```

**Front-loaded** (one long rules file read at start)

- Simple to write
- Costs tokens every session
- Rules fade as context grows
- Compaction may drop them

**Just-in-time** (skills, hooks that inject, retrieval)

- Small base context
- Rule arrives at the moment it matters
- Needs good descriptions to trigger
- Critical rules still belong in hooks

## AGENTS.md and Agent Skills: the open standards

Level 2 · Why it works

Two file conventions now carry context across tools. Both became open standards in late 2025, so what you write works beyond one vendor.

|  | AGENTS.md | Agent Skills (SKILL.md) |
| --- | --- | --- |
| Answers | How this project works: build, test, conventions | How to do one kind of task |
| Loaded | Every session | Name and description at startup; full body only when a task matches; bundled files only when referenced |
| Shape | One Markdown file in the repo | A folder with SKILL.md (frontmatter plus instructions), optional scripts and references |
| Origin | Released by OpenAI in 2025, now stewarded by the Agentic AI Foundation under the Linux Foundation | Developed by Anthropic, published as an open specification at agentskills.io |
| Cost | Paid on every turn: keep it short | Near zero until used: libraries can grow |

> **Note:** **Rule of thumb:** if every task in the repo needs it, it belongs in AGENTS.md. If only some tasks need it, it is a skill. If it must never be violated, it is neither: it is a hook or a permission ([page 5](https://openplanr.dev/learn/agentic-engineering/harness-engineering)).

## Compaction, memory and caching

Level 2 · Why it works

- **Compaction:** Summarizing older turns to free space. Lossy by design. Rule: anything critical lives in a file, not only in chat.
- **Memory:** Facts saved to files and reloaded in later sessions. Rule: durable decisions go into versioned files the agent reads.
- **Prompt caching:** The provider reuses an unchanged prompt prefix, so repeated calls are cheaper and faster. Rule: stable content first, changing content last.

```python check=run title="Why prompt order decides what can be cached"
def cacheable_prefix(parts):
    stable = 0
    for kind, tokens in parts:
        if kind != "stable":
            break
        stable += tokens
    return stable

good = [("stable", 3_000), ("stable", 12_000), ("changing", 900)]
bad = [("changing", 900), ("stable", 3_000), ("stable", 12_000)]
print("stable first:", cacheable_prefix(good), "tokens cacheable")
print("changing first:", cacheable_prefix(bad), "tokens cacheable")
```

```text title="Output (Python 3.14.8)"
stable first: 15000 tokens cacheable
changing first: 0 tokens cacheable
```

## Four moves when the window fills

Level 3 · Mastery

Long tasks outgrow any window. Seniors reach for these in roughly this order:

- "Old tool output is drowning the current step." → **Clear or prune**: Drop raw results the agent has already used; keep its conclusions.

- "The session is long but the thread still matters." → **Compact**: Summarize older turns; lossy, so write key decisions to files first.

- "Progress must survive across sessions." → **Structured notes**: The agent keeps a progress file or task list outside the window and rereads it.

- "Exploration will read thousands of lines." → **Subagent**: Do the noisy work in a separate clean window; return only a condensed summary.

## Predict the output

### How full is the window?

Level 1.

```python
window = 200_000
used = 3_000 + 12_000 + 2_500 + 80_000 + 26_500
print(f"{used / window:.0%}")
```

1. 62%
2. 50%
3. 124%
4. 6%

**Answer:** option 1.

```text title="Output (Python 3.14.8)"
62%
```

**Why:** 124,000 of 200,000 tokens is 62 percent. Watch quality from here on and plan a compaction or a fresh session before the window gets close to full.

## Check your understanding

Levels 1 to 3.

**Q:** What is the difference between prompt engineering and context engineering?

**A:** Prompt engineering is the wording of instructions. Context engineering decides which tokens are in the window at each step, and when they arrive. Prompt engineering is one part of it.

**Q:** What is context rot, and what does it imply?

**A:** As the window fills, the model gets worse at using what is in it. So a bigger window is not a free win: keep the context lean, and compact, prune or isolate before quality drops.

**Q:** A rule is needed by only one task in ten. AGENTS.md or a skill?

**A:** A skill. AGENTS.md is paid on every turn; a skill costs only its short description until the task matches.

**Q:** How should you order a prompt for caching?

**A:** Stable content first (system prompt, tool definitions, long reference docs), changing content last. The cache only covers an unchanged prefix.
