AXME Code · 6 min read

The 4 Types of Context Your AI Coding Agent Needs

Most agents treat all context as 'stuff in the context window'. But facts, patterns, project state, and references have different lifecycles and different retrieval rules. Mixing them is why agents feel dumb.

The word “context” is doing too much work. When I say “the agent needs more context,” I could mean four very different things, and until I separated them in my head I kept building systems that got one of them right and broke on the other three.

Here are the four types of context, what they are, how they differ, and why mixing them is the reason your agent feels like it has goldfish memory.

Type 1: facts about the user

What it is: stable preferences, habits, personal conventions of the human working with the agent.

Examples:

  • “User prefers explicit return types on all functions, even when inferred would work.”
  • “User writes commit messages in present tense, not past.”
  • “User is a senior Go engineer, currently learning React.”
  • “User communicates in Russian when the topic is non-technical, English otherwise.”

Lifecycle: very long. These don’t change between sessions. They don’t change much between projects. A fact about the user is one of the most stable things in the system.

Retrieval: loaded into every session, regardless of project. Your preference for explicit return types applies whether you’re writing TypeScript or Python, and it applies to a new repo you just cloned.

Storage: a global user file, not tied to any repo. Something like ~/.config/axme-code/user.md or equivalent. One source of truth across all projects.

Failure mode: treating user facts as project facts. If you put “user prefers explicit return types” in the project-level memory, you lose it every time you switch projects. A month later, you’re re-training the agent on your own habits. Annoying. Fixable by having a separate layer for global user preferences.

Type 2: patterns validated for this project

What it is: things that turned out to be true about how this specific project works, discovered through use, not prescribed in advance.

Examples:

  • httpx.Client cannot be used inside async handlers. Blocks the event loop. Use httpx.AsyncClient.”
  • “The users.py file is legacy. New user-related code goes in user_service.py.”
  • “Tests in tests/e2e/ require DATABASE_URL env var to be set or they skip.”
  • “The Intent Pydantic model must be re-exported from schemas/__init__.py or imports break.”

These are the kinds of things you discover during real work. You don’t know them in advance. They emerge when the agent does something that would have worked in a generic project but doesn’t work in yours.

Lifecycle: medium. A pattern is valid until the codebase changes around it. When the refactor happens (“we migrated users.py to user_service.py”), the old pattern becomes wrong. Patterns need to be supersedable.

Retrieval: loaded when working in the relevant area of the repo. Patterns about the auth module only matter when editing auth. A simple path-based filter can narrow the set injected into context.

Storage: per-project, keyed by some structural identifier (file path glob, module name, or general “applies to whole project”). Something like .axme-code/memory/patterns/.

Failure mode: not capturing them. Every correction you make during a session is a pattern that should become memory. If the only way for a pattern to enter the store is for you to hand-write it, none of them will. You need automatic capture from session transcripts.

Type 3: active project state

What it is: what is happening right now in the project. What was I doing yesterday. What’s in progress. What’s the state of the current work.

Examples:

  • “Mid-refactor of auth module: 3 of 12 files migrated to new token format.”
  • “Known failing test: test_cost_rollup_weekly.py:42, stale fixture, not a bug.”
  • “Open question: should historical records in BigQuery also migrate to Decimal?”
  • “Last session ended with: user approved the Zod migration PR, next step is writing the changelog entry.”

Lifecycle: very short. Active state is valid for a day or a week, then it’s stale. The refactor completes, the question gets answered, the test gets fixed. Yesterday’s handoff is tomorrow’s archaeology.

Retrieval: loaded at the start of the next session only. You don’t need last month’s active state. You need this morning’s. Anything older should expire or at least be weighted down.

Storage: session handoff files, ideally auto-generated at session close. A handoff note + worklog of recent events is enough.

Failure mode: treating it as permanent. If you write “currently refactoring auth” into a long-lived memory store, you’ll still see it three months later after the refactor is long done, and it will confuse the agent. Active state needs an expiry, or at least a clear “last updated” that makes it obviously current.

Type 4: external references

What it is: pointers to things that live outside the code and outside your memory system. Docs, tickets, API references, design docs, Slack threads, pull request discussions.

Examples:

  • “Billing logic follows the contract in docs/specs/billing-v3.md.”
  • “Track bug reports in the INGEST Linear project.”
  • “API rate limits are documented at https://api.openai.com/docs/rate-limits.”
  • “The migration pattern was decided in PR #412, see the discussion there.”

Lifecycle: medium to long. The reference itself might be stable, but its content might move or change. A stale URL is worse than no URL.

Retrieval: loaded when the agent needs to look something up. Not injected preemptively. The agent should know where to look, not what’s there.

Storage: a reference registry with URL/path + one-line description + last-verified date. Something like .axme-code/memory/references/.

Failure mode: confusing this with facts. “The billing logic uses Decimal” is a fact (Type 2 pattern). “The billing logic is documented in docs/billing-v3.md” is a reference. They look similar but behave differently: the fact is loaded into every billing session, the reference is retrieved only when the agent explicitly says “let me check the docs.”

Why confusing them breaks agents

If you treat all four as the same thing (put them all in CLAUDE.md, or in a flat memory table), these are the specific failure modes:

User facts get lost between projects. You put them in project memory, they don’t carry over. You re-explain yourself to every new repo.

Patterns don’t expire. You add “the auth module uses JWT tokens” as a pattern. Six months later you migrated to session cookies. The old pattern is still in memory, still being injected, still confusing the agent. Without a supersede mechanism you can’t clean it up.

Active state goes stale. You write “currently refactoring auth” into memory. Three weeks later, auth is refactored and moved on. But the memory store still says “currently refactoring.” The agent reads this and acts as if the refactor is ongoing.

References bloat the context. Every doc URL you put in memory gets loaded into every session’s context, eating tokens. You don’t need all the URLs, you need the URL when you need it. Preemptive loading of references is waste.

All four of these bugs look like “my memory system doesn’t work.” They are actually four distinct bugs caused by the same root issue: treating different shapes of data as the same shape.

How to actually structure this

The shape I ended up with (in AXME Code, but the same pattern would work anywhere):

~/.config/axme-code/user.md         # Type 1: global user facts

<repo>/.axme-code/
├── memory/
│   ├── patterns/                   # Type 2: project patterns
│   ├── glossary.md                 # Type 2: project vocabulary
│   ├── user_*.md                   # Type 1: user facts in this project context
│   └── references/                 # Type 4: external references registry
├── sessions/
│   └── <session-id>/handoff.md     # Type 3: active state, per session
├── worklog.md                      # Type 3: recent events
└── decisions/                      # Contracts (separate category)

The key split: Type 1 (user facts) lives outside any repo, the rest live inside the repo. Within a repo, patterns and references live longer than session state, so they’re in memory/ while sessions get their own directory that can be pruned.

At session start, the agent loads:

  • All global user facts (Type 1)
  • All project patterns relevant to the area of work (Type 2)
  • The latest session handoff only (Type 3)
  • Reference registry index only, not the contents (Type 4)

Four context types, four retrieval strategies, one coherent store. The distinctions feel like bureaucracy until you actually have the problems they solve, and then they feel like the minimum practical shape.

The single takeaway

If you’re building agent memory and it feels sloppy, check whether you are mixing these four types. If you are, separate them. If you are not, you are probably already feeling the benefit.

“Context” is a word that covers too much. Break it into its four shapes and the system stops drifting.

More on AXME Code