Half of the agent failures I see in Python projects come from bad context, not a bad model. The other half come from the same thing in a different costume. Context engineering is the practice of putting the right content in front of the agent at the right moment, and most of the time it is what separates a working session from a half-hour of arguing with a tool.
I have been running Claude Code, Codex CLI, and Antigravity CLI against real Python codebases for the better part of a year. The pattern that consistently produces clean output and the pattern that produces loops and hallucinations are not about which model is on the other end. They are about what is in the window when the model starts its turn.
What is actually in the context window
The context window is the fixed-size budget everything the agent sees lives in. On a single turn, the window typically holds seven layers:
- System prompt (the agent’s built-in role and rules, set by the vendor).
- Instruction files such as
AGENTS.md,CLAUDE.md, Cursor rules, or Copilot instructions, auto-loaded into every turn. - Skill descriptions (the agent loads a skill’s full body only when it picks the skill for the task).
- Tool definitions, including Model Context Protocol server tools (a standardized way for agents to call external tools and data sources) and any subagent the main agent can delegate to.
- Files the agent has opened in this session.
- Search results from web searches, RAG (retrieval-augmented generation, the practice of pulling only the relevant chunks of documents into the context), or file searches.
- Conversation history, including your new prompt at the end.
Three properties of the window matter. It is fixed (everything above the budget competes for the same slots). Position-sensitive (items at the top and bottom tend to get more attention than the middle). Non-persistent (most of it evaporates when you close the session, so anything important needs to live on disk or in a memory store).
Once you see the window as a layered payload you control, context engineering becomes the question of what you put in each layer.
The four strategies that cover the lifecycle
Most context-engineering techniques map to four strategies, and each strategy answers a single question you can ask before any agent task.
- Curate. What should I put into the window for this turn? AGENTS.md, file search, RAG, skill descriptions, MCP servers.
- Distill. What can I shrink without losing the point? Compact commands, on-demand summarization, dropping old tool output, trimming stale turns.
- Delegate. What deserves its own separate window? Subagents, sandboxed code execution.
- Externalize. What should I save outside the window so the agent can pull it back later? Notes files, plan files, persistent memory.
The four cover the lifecycle of context from the moment the agent starts its turn to the moment the session ends. Pick the strategy that matches the failure you are seeing and the next four sections walk through each.
Curation is where most of the work happens
This is where I spend most of my time as a Python developer. The Curate strategy is about deciding exactly what the agent should see to do the task in front of me. Your prompt matters, which is why prompt engineering is its own field, but the surrounding context matters just as much.
The most common starting point is an instruction file. Auto-loaded files like AGENTS.md, CLAUDE.md, Cursor rules, or Copilot instructions get pulled into every turn, so they are the right home for project-wide conventions. A short AGENTS.md for a Python service looks like this:
- Python version: 3.14. Don't assume newer syntax than that.
- Dependency manager: `uv`. Never use `pip`.
- Tests: `uv run pytest -q`. Add a test for every new function.
- Lint and format: `ruff check` and `ruff format`.
- Type checking: `mypy --strict`. Type-hint all public functions.
- Use Google-style docstrings.
- Don't add new dependencies without asking.
Short is the operative word. Long instruction files become a context-bloat problem and the agent tends to ignore any single rule when there are thirty of them.
Beyond instruction files, a few more curation tactics are worth applying. Just-in-time file loading lets the agent search and open files as it needs them rather than dumping the whole repo into the prompt up front. Skills (descriptions of workflows the agent loads only when relevant) keep the window light when most tasks do not need them. RAG pulls only the chunks that match the query instead of concatenating entire documents. MCP servers (each server drops its tool catalog into the window) should be deliberately picked per project, because connecting all of them bloats the catalog and makes the agent worse at picking the right tool.
Distill when context gets noisy
Older context fades as the window fills, and the earliest instructions get crowded out. The agent runs pip install again because it cannot see the rule about uv. The agent quotes its own hallucination because a wrong answer became fact by staying in the window. The agent loops on the same failing pytest command because recent failures pull harder than older instructions.
Distill is the strategy that rewinds and compresses. Most agents ship with a compact command. The honest version of compact rewrites the conversation into a shorter form and keeps the rules, the active task, and the recent failures intact while dropping the chatter. Run /compact when the window is half full, not when it is full. The second-best time is when you are about to start a new sub-task.
Some teams distill manually. They write a one-paragraph “state of play” before a long task and pass that to the next session rather than the full history. Other teams write Distill into a hook (a shell command the agent runs automatically at session-end) so every session ends with a five-line summary file on disk. Both work. The choice depends on whether the agent loads the summary or re-reads it.
Delegate when the window needs a clean start
If the agent has been failing on the same problem for three turns, the fastest fix is usually a new window. Delegate is the strategy that hands a task to a subagent with a clean context, which inherits the rules from AGENTS.md and the conversation summary you pass in but does not inherit the failed attempts.
Most modern agents ship with a delegated-task tool. Claude Code has a Task tool, Codex CLI has subagents, Antigravity CLI has its own delegation. The pattern is the same: write a short task description, give the subagent the tools it needs, and let it work in its own window. When it returns, the parent session sees only the result, not the work.
Delegate is most useful for three categories of task. Heavy code search across a large repo benefits from a subagent with a grep-only window. Sandbox running of untrusted code benefits from a subagent with no write access to the project. Long-running refactors benefit from a subagent with its own session log so the parent can stay responsive.
Externalize what should survive the session
Anything you want to survive the session has to live outside the window. Notes files, plan files, persistent memory, scratch directories under a known path. Agents that re-read these every session keep continuity across long-running projects.
The cleanest pattern is a wants.md in the project root for goals and a notes/ directory for daily-session state. The agent writes a one-line summary at session-end (a hook helps). The next session opens the file, sees yesterday’s state, and continues. For multi-week projects, an issues file or a plan file in the project root serves the same purpose at higher altitude.
Externalize is also where memory stores come in. Some agents ship with a vector database (an index that lets the agent search across many notes by similarity, rather than reading every file) for personal notes; some have a per-project memory store. The pattern is the same: write the rule to disk, let the agent re-read it on the next turn, repeat.
Trade-offs
The Curate strategy scales linearly with the number of instruction files and MCP servers you have. A long AGENTS.md plus ten MCP servers plus a skills directory will eat half the window before the agent reads your prompt. Trim aggressively. The Distill strategy loses some context when compaction rewrites history. If you compact too aggressively you can drop the rule the agent needs most. Delegation is not free: each subagent starts cold and pays the cost of re-reading the instruction files. A 5-minute task does not benefit from delegation. Externalize adds a write/read step on every session boundary; if the write is bad the next session reads garbage.
Each strategy trades off against the others, and the right mix depends on the project. For a one-off script, Curate alone is enough. For a long-running service, all four are in play.
Bottom line
Context engineering is mostly about deciding what is in the window. The four strategies cover the lifecycle. Most failures are context failures, and the fix is rarely a bigger window.
If I had to send one message back to the version of me that started using these tools, it would be this: write a short AGENTS.md and add /compact to your muscle memory before you start reaching for a better model.
- A short AGENTS.md is the cheapest fix in context engineering. Most agent failures trace back to missing rules in the instruction file.
- Compact early, not late. A half-full window compact is invisible; a full-window compact loses the rule you cared about.
- Delegate before you loop. Three failed turns on the same task is the cue for a subagent, not a tenth retry.