A person in a green coat drops a document into a cabinet labeled CONTEXT WINDOW, beside a token-budget gauge, a Python logo, and a checklist on a tripod.

Context Engineering for Python Codebases

by Leodanis Pozo Ramos Updated Reading time estimate 19m intermediate ai best-practices tools

Context engineering is the practice of curating the content that goes into an AI agent’s context window. In Python projects, that may mean pinning your dependency manager in an instruction file, trimming irrelevant history, delegating heavy tasks to subagents, and more.

By the end of this tutorial, you’ll understand that:

  • The context window holds everything the agent sees on a single turn, not just your latest prompt.
  • Most agent failures come from bad context, not a bad model.
  • Bigger context windows don’t fix poor curation—they only delay the symptoms.
  • Instruction files like AGENTS.md keep your Python conventions in front of the agent.
  • Curate, Distill, Delegate, and Externalize are strategies that can help you manage the agent’s context.

Modern AI coding agents, such as Claude Code, Codex CLI, Cursor, Copilot CLI, and Antigravity CLI, work with a fixed-size context window. Once you know what’s in that window and decide what belongs there for the task at hand, you’ll spend less time arguing with your agent and more time shipping quality Python code.

Take the Quiz: Test your knowledge with our interactive “Context Engineering for Python Codebases” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Context Engineering for Python Codebases

Build a working framework to manage your AI coding agent's context window using four practical strategies for Python projects.

Prerequisites

Before you start learning about context engineering, you should already have:

To learn more about these and other related topics, you can check out the resources in this Real Python learning path:

Learning Path

Python Coding With AI

12 Resources ⋅ Skills: Cursor, Claude Code, AI-Assisted Development, Context Engineering, AI Code Review

You don’t need any prior exposure to context engineering itself. The whole point of this tutorial is to give you a working framework to effectively manage your agent’s context window.

With that distinction in mind, the next section opens up the context window so you can see exactly what’s competing for space on every turn.

Defining Context for AI Coding Agents

The context window is everything the agent sees on a single turn. Your most recent prompt is only the last item on the list. On any given turn, whenever you write a prompt and press Enter, the agent’s window typically holds the following layers of content:

  1. System prompt: The agent’s built-in role and rules, typically set by the vendor.
  2. Instruction files: Files like AGENTS.md, CLAUDE.md, Cursor rules, or Copilot instructions, auto-loaded into every turn. Skill descriptions also live in this layer. The agent loads a skill’s full body only when it picks the skill for the task.
  3. Tool definitions: Names, short descriptions, and JSON Schema definitions for every tool the agent can call, including MCP server tools and, in some frameworks, any subagent the main agent can delegate to.
  4. Opened files: Source files, configuration files, or docs the agent has read in this session.
  5. Search results: Results from web searches, internal RAG queries, or file searches.
  6. Conversation history: Earlier prompts, replies, and tool outputs from the same session.
  7. Your new prompt: The prompt you just typed, plus any attachments.

In practice, all of this content lives inside the context window. The layers are listed separately here to clarify what’s consuming your context budget. The diagram below shows how all seven layers come together as the context window the agent reads before producing a reply:

A labeled Context window frame holds seven colored input cards feeding via arrows into a central Agent box, which produces a Generated response box on the right.
The Context Window on a Single Agent Turn

For a more concrete example, below is a snapshot of what a single turn in a Claude Code session might look like:

Language: Text Filename: Context Window
[system prompt]        You are Claude Code, an interactive CLI...
[CLAUDE.md]            Use uv. Python 3.14. Run tests with uv run pytest -q.
[tool catalog]         Read, Edit, Bash, Grep, WebFetch, ...
[opened file]          src/api/users.py  (340 lines)
[history turn 1]       User: Add an email validator to the User class.
[history turn 2]       Assistant: <edits users.py>
[tool result turn 2]   Bash: uv run pytest -q -> 3 failed
[history turn 3]       User: Fix the failing tests.

Here are three properties of the context window that matter for everything that follows:

  • Fixed: The context window can only hold a certain number of tokens. Everything above that number competes for the same budget.
  • Position-sensitive: Items at the top and bottom of the window tend to get more attention from the model than items in the middle. Long conversation histories may push important rules into the dead zone in the middle of the context window.
  • Non-persistent: Most of the context evaporates when you close the session. What survives is whatever you write to disk or a memory store.

Once you can see the context window as a layered payload that you control, you realize that context engineering is mostly about deciding what you put in each layer. Doing a bad job of managing the context window can lead to poor-quality responses or actions from your favorite AI agent.

Diagnosing Common Context-Engineering Failures

When an agent misbehaves, your first instinct might be to blame the model behind it. Most of the time, the model is fine, but the context isn’t. Here are the failures you’ll recognize from your own sessions:

  • The agent forgot your rules. You said “use uv” thirty turns ago, and now the agent ran pip install again. Older context fades as the window fills, and your earliest instructions get crowded out. Apply the Distill strategy to reduce noise so the rules stay clear, or the Externalize strategy to save the rule in a persistent notes or memory file the agent re-reads on every run.

  • The agent quotes its own hallucination. The agent invented pandas.read_parquet_lazy() a few turns back and is now calling it again. A wrong answer becomes fact if it stays in the window. Apply the Distill strategy to rewind past the bad turn.

  • The agent loops. It keeps re-running the same failing pytest command instead of stepping back to plan. Recent failures pull harder than older instructions. Apply the Delegate strategy to hand the retry to a subagent with a clean window.

  • The agent picks the wrong tool. Twelve MCP tools are loaded, and it grabs list_users() when you wanted list_accounts(). Too many similar options crowd out the right one. Apply the Curate strategy to load only the MCP servers this task needs.

  • The agent gets conflicting signals. AGENTS.md says uv, but a Makefile line says pip. Two pieces of context disagree, and the agent picks one randomly. Apply the Curate strategy to keep a single source of truth in your instructions.

A larger context window doesn’t solve these issues and can make some of them worse. It simply fills more slowly without deciding what matters. The real fix involves curating what goes into the window. Putting that fix into practice is what you’ll do for the rest of this tutorial.

Each failure above maps to one of the four context-engineering strategies: Curate, Distill, Delegate, and Externalize. Together, they make up the framework you’ll learn about in the next section.

Exploring Context-Management Strategies

Most context-engineering techniques map to four strategies, each defined by a single question you can ask before any agent task. Instruction files, MCP servers, skills, subagents, and the rest all fit into one of these four:

Strategy Question Possible Actions
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? Use /compact, summarize on demand, drop old tool output, trim stale turns
Delegate What deserves its own separate window? Subagents, sandboxed code execution