Saltar al contenido principal

Chapter 2: Context engineering

A model does not see your repository. It sees its context: a window of text, limited in size, assembled by the tool from your prompt, your configuration, the files it decided were relevant and the output of whatever it ran. Everything the model gets right or wrong is downstream of what was in that window. Context engineering is the practice of controlling it on purpose.

Five sources of context you control​

SourceLifetimeWho writes itTypical content
PromptOne requestYouThe task, the spec, the constraints for this change
Rules fileThe repositoryThe teamConventions, forbidden patterns, where things live, how to run tests
Attached files / selectionOne requestYouThe code the change touches, the spec, an example to follow
Tool outputOne sessionThe agentTest results, command output, file contents it read
Memory / MCPAcross sessionsYou, or a serverFacts the tool stores between sessions; data from external systems (issue tracker, docs, database schema)

The rules file is where most of the leverage is, because it is the only source that applies to every request without anyone remembering to include it.

The rules file​

Each tool reads a file at the repository root at the start of every session:

  • Claude Code: CLAUDE.md (also ~/.claude/CLAUDE.md for personal defaults, and CLAUDE.md in subdirectories for local overrides)
  • Cursor: .cursor/rules/*.mdc, each with frontmatter that scopes it to file globs or marks it "always apply"
  • GitHub Copilot: .github/copilot-instructions.md, plus .github/instructions/*.instructions.md with applyTo globs

The content is the same idea in all three: the constraints block from Module 2, written once.

What goes in​

# Project rules

## Stack
- Python 3.12, FastAPI, SQLAlchemy 2.x (async), pytest. Node 20 for the frontend (Vite + React).
- Package management: `uv` for Python, `npm` for the frontend. Do not add dependencies without
asking; prefer what is already in `pyproject.toml`.

## Conventions
- Errors: raise subclasses of `app.errors.AppError`; the global handler converts them to HTTP.
Never `try/except` to return an HTTP error from inside a route.
- Database access only through repositories in `app/repos/`. Routes never import SQLAlchemy.
- All routes go through `app/api/router.py`, which applies auth. Do not register routes elsewhere.
- Logging: `structlog`, `logger.info("event_name", key=value)`. No f-strings in log calls.

## Testing
- Run: `uv run pytest -q`. Tests live in `tests/`, mirroring `app/`.
- Behavioural tests over the HTTP client (`tests/conftest.py::client`) are preferred.
- Never modify a test to make it pass unless the task explicitly says the test is wrong.

## Do not
- Do not touch `migrations/` without an explicit instruction.
- Do not commit, push or change git configuration.
- Do not read or print `.env*` files.

Forty lines. Every one of them prevents a class of "it works but it does not fit" review findings.

What stays out​

  • Anything the model already knows. How Python works, what REST is, how to write a for loop. Every token spent on this is a token not spent on your code.
  • Long prose. Lists and short imperatives. The model treats the rules file like instructions, so write instructions.
  • Things that change weekly. The current sprint goal does not belong here; it belongs in the prompt.
  • Secrets, obviously. The rules file is committed.

Scoped rules​

Both Cursor and Copilot let you attach rules to file patterns, so frontend rules load only when frontend files are in context. Claude Code achieves the same with CLAUDE.md files in subdirectories. Use this: a single file that tries to cover the whole monorepo becomes long, and long rules files get ignored - by the model and by the team.

Keeping the context small​

Larger context windows have made it tempting to "just include everything". Three reasons not to:

  1. Attention is not uniform. Models recall material at the start and end of a long context better than material in the middle. The file you need most may be the one that gets skimmed.
  2. Noise competes with signal. Twenty files that are "sort of relevant" dilute the three that matter.
  3. Cost and latency scale with context size.

Practical rules:

  • Attach the files the change will touch and one example of the pattern to follow. Let the agent read more if it needs to.
  • Point at a spec file rather than pasting the spec into the prompt; it is the same tokens but it keeps the spec as the source of truth.
  • In a long agent session, start a new session when the task changes. Carrying context from the previous task is usually a cost, not a benefit.

Memory and MCP​

Memory lets a tool remember facts between sessions ("this project uses uv, not pip"). Useful for personal preferences. Dangerous as a substitute for the rules file, because memory is per-user and invisible to teammates. If something belongs in memory for everyone, it belongs in the rules file.

Model Context Protocol (MCP) is an open standard for connecting a model to external tools and data: your issue tracker, your documentation, a database schema, a browser. An MCP server exposes functions the agent can call; the tool handles authentication and permissions.

Two guidelines:

  • Read-only first. An MCP server that lets the agent read the issue tracker is low-risk and high-value. One that lets it close issues or run SQL is a governance question (Module 5).
  • Fewer, better servers. Every connected server adds its tool descriptions to the context on every request. Ten servers you rarely use are a tax on every prompt.

A practical sequence for a new repository​

  1. Write the rules file. Thirty to sixty lines, following the template above. Commit it.
  2. Make the first task small and well-specified. Note every correction you make in review.
  3. Each correction that would recur becomes a line in the rules file. Commit it.
  4. After a week, the rules file has stabilised and review findings have dropped. That is the signal that the context is doing its job.
  5. Review the rules file quarterly. Delete lines that no longer prevent anything.

Summary​

  • The model sees its context, not your repository; context is engineered, not accidental.
  • The rules file is the highest-leverage source: constraints written once, applied to every request.
  • Keep context small and specific; start new sessions when the task changes.
  • Memory is personal; rules are shared. MCP servers: read-only first, few and well-chosen.