Mastering Context: Configuring AGENTS.md for Web Projects

Jul 23, 2026 min read

You tell your agent to use tabs instead of spaces. It fixes the file. Ten minutes and four prompts later, you glance at a new component and there they are again — two spaces, indenting quietly like you never said a word. You didn’t imagine the first fix. The model just forgot it happened, because as far as its attention is concerned, that instruction is now buried under everything you’ve asked for since.

That’s not a bug in Qwen3.5 9B, it’s arithmetic. The model’s context window tops out at a theoretical 262,144 tokens, but coding tasks start showing real degradation once a session crosses roughly 25,000-30,000 tokens. Instructions from early in the conversation stop getting the attention weight they need to actually govern new output. Cloud models with a trillion parameters and a business model built on burning GPU-hours can paper over this with sheer scale. A 9B model running locally can’t, especially when a 30,000 token context window easily spills past the VRAM of a standard 8GB graphics card. Pretending otherwise means re-explaining your tabs preference every fifteen minutes for the rest of the afternoon.

AGENTS.md is the fix, and it works for a reason that’s easy to miss if you think of it as “a longer system prompt.” It isn’t reprocessed and reweighted the way conversation history is. OpenCode treats it as a standing project reference the agent consults fresh, which means your rules don’t degrade the way a message from twenty turns ago does. Get this file right once, and every session starts from the same architectural baseline instead of drifting back toward whatever the model saw most in training.

The Anatomy of AGENTS.md

Why Standard Prompts Fail

A system prompt sets the model’s baseline persona for a conversation. AGENTS.md does something different: it’s a persistent, project-specific reference that survives session restarts and context flushes entirely, because OpenCode loads it fresh from disk rather than carrying it as aging conversation history. Type “always use Prisma, never raw SQL” into chat and that instruction is subject to the same context sliding as everything else you type. Put it in AGENTS.md and it’s there on turn one and turn two hundred, unchanged.

The practical difference shows up exactly where you’d expect — long sessions. Ask for five components in a row without AGENTS.md, and by the fourth or fifth the model has quietly stopped following a rule you gave it at the start, not out of defiance but because that instruction has slid out of its effective attention window. AGENTS.md doesn’t get pushed out that way.

Agent Context Window Diagram

Visualizes how AGENTS.md provides persistent, undegraded context to the agent, bypassing the naturally decaying attention weight of long conversation histories.

Agent Context Window Diagram

(AP[[[GeTTTErCuuuNsorrrTinnnnSsv.te211mer00]dns]]tCaA)ot(((gdiLMDeeooernnwdotGpeHWWpCnieeeoesiidnrtgg)taohhetrttxiy))ton(WDiC(EenuHngdrigrorgiawehndneitWnegPi)rgohmtp)t

Visual Notes:

  • The persistent nature of AGENTS.md means it maintains high attention weight alongside the current prompt.
  • Conversation history degrades over time, illustrating why rules defined early in the chat are eventually ignored by the Code Generation Engine.

Core Components of the File

A working AGENTS.md has three parts, in this order, because order determines what actually gets followed:

# AGENTS.md

## Project Overview
Full-stack web app: Next.js 15 (App Router) frontend, Express.js REST backend.

## CRITICAL RULES
- Never use `var`. Use `const` or `let` only.
- Never use the Pages Router or `getServerSideProps`.
- Never hardcode secrets, API keys, or connection strings. Use `process.env`.
- Never write raw SQL. Use Prisma for all database access.

## Architecture Boundaries
- `/frontend`: Next.js App Router, Server Components by default, Tailwind CSS only.
- `/backend`: Express.js REST API, controllers separated from routes, Zod for input validation.

## Build & Test Commands
- `npm run dev` — start dev server
- `npm run lint` — run ESLint

The CRITICAL RULES section sits second, immediately after the one-line project overview, not buried at the bottom where a model running low on effective attention is least likely to weigh it. That placement is the single highest-leverage decision in the whole file.

Writing Rules for Web Development

Enforcing the Tech Stack

State versions. Not “use Next.js” — “use Next.js 15 with the App Router.” A 9B model’s training data spans years of tutorials, and the majority of that content predates the App Router entirely. Leave the version unstated and the model defaults to whatever pattern it saw most often, which is very often getServerSideProps and a pages/ directory that doesn’t exist in your project. The fix costs you four words: “NOT the Pages Router.”

The same logic applies to React itself. “Use React 19 with Server Components” heads off class-component syntax before it starts, instead of catching it in review after the fact.

Architectural and Style Guidelines

Naming conventions and export patterns belong here too, and they’re worth being just as blunt about:

## Style Guidelines
- Files: kebab-case (`user-profile.tsx`, not `UserProfile.tsx`)
- Components: PascalCase exports (`export default function UserProfile()`)
- Prefer named exports for utility functions; default exports for React components only

One rule, one line. A model parsing this file for the fourth time today processes a bulleted list far more reliably than a paragraph saying the same thing — there’s less to disambiguate, and less for a 9B model to trim or misread under context pressure.

Practical Example: Building a Full-Stack AGENTS.md Template

Here’s the scenario: a new monorepo, Next.js frontend, Express backend, one agent working across both. Without explicit boundaries, nothing stops the model from importing a Prisma client directly into a React component, or dropping a "use client" directive into an Express controller where it means nothing.

Step 1 — define the persona and stack in one line. Don’t write a paragraph of scene-setting. One sentence: “You are a senior full-stack engineer working in a Next.js 15 + Express.js monorepo.”

Step 2 — separate concerns by directory. This is the part teams skip, and it’s the part that actually prevents spaghetti: tell the model explicitly which rules apply where, rather than one flat list it has to guess the scope of.

Step 3 — add the boundary rules that keep the two halves from bleeding into each other.

The complete, copy-pasteable template:

# AGENTS.md

## Persona
You are a senior full-stack engineer working in a Next.js 15 + Express.js monorepo.

## CRITICAL RULES
- Never use `var`. Use `const` or `let`.
- Never hardcode secrets. Use `process.env` for all credentials.
- Never write raw SQL or NoSQL queries. Use Prisma exclusively.
- Never mix frontend and backend concerns in a single file.

## Frontend (`/frontend`)
- Next.js 15, App Router only. NOT the Pages Router.
- Server Components by default; add `"use client"` only when state, effects, or browser APIs are required.
- Tailwind CSS utility classes only. No inline styles, no separate `.css` files.
- State management: React state and context for local/shared UI state. No Redux unless explicitly requested.

## Backend (`/backend`)
- Express.js REST API. Controllers in `/controllers`, routes in `/routes`, kept separate.
- All async controller functions wrapped in try-catch, returning a 500 on internal errors.
- All input validated with Zod before it reaches business logic.

## Build & Test Commands
- Frontend: `npm run dev` (from `/frontend`)
- Backend: `npm run dev` (from `/backend`, via nodemon)
- Lint: `npm run lint`

Commit this file to Git. That’s not a suggestion — it’s how the rules stay consistent across every developer’s machine and every session, instead of living only in the config of whoever set it up first. Point OpenCode at a project with this file in place and the components, controllers, and routes it generates start looking like they came from one senior developer’s keyboard, not four different tutorials stitched together.

Best Practices and Tips

Do:

  • Keep rules as bullets, not paragraphs. A local model parses “Never use var” faster and more reliably than a sentence explaining why var is a bad idea.
  • Update the file as the architecture actually changes. A stale AGENTS.md that still says “Pages Router” three months after you migrated is worse than no file at all.

Don’t:

  • Write a 2,000-word file. Every token in AGENTS.md is a token not available for the actual code generation, and past a few hundred words you’re cutting into the same effective attention budget you’re trying to protect.
  • Put API keys, database passwords, or any secret in this file. It’s committed to Git — anything in it is exactly as exposed as your source code.

Troubleshooting Common Issues

The agent ignores one specific rule. Check two things: is the rule buried past the halfway point of the file, and does it conflict with something else in there — or with your .eslintrc or tsconfig.json? A model asked to reconcile two contradictory instructions usually just picks one, and it’s rarely the one you meant. Move anything non-negotiable to the top under CRITICAL RULES, and audit for conflicts with your actual lint config before you assume the model is at fault.

The agent follows the rules for the first few prompts, then stops. This is context sliding in action — you’ve likely crossed the 25,000-30,000 effective token threshold for the session, and AGENTS.md’s instructions are getting less attention weight relative to everything generated since. Commit your current progress, clear the conversation, and start a new session. The file reloads fresh; the drift doesn’t carry over.

Out-of-memory errors during generation. This usually isn’t AGENTS.md’s fault directly — it’s the inference engine’s configured context window fighting your graphics card for VRAM. Fitting a 30,000 token context window alongside a 9B model requires more than an 8GB card can handle due to the expanding KV cache. In Ollama or LM Studio, dial the context window setting down to 8192 tokens for an 8GB GPU, and lean on a tight, well-structured AGENTS.md instead of a sprawling conversation history to carry your rules.

Conclusion

AGENTS.md isn’t a nice-to-have for local AI coding — it’s the difference between an agent that drifts back to generic patterns every few prompts and one that holds your architecture for an entire session. Keep it concise, bullet the rules, put the non-negotiables at the top, and commit it like the code it effectively is.

Next steps: add an AGENTS.md to whatever you’re building right now, using the full-stack template above as a starting point. Next in this series: what to do when the agent inevitably ignores a rule anyway and you need to debug why.

Related Articles in This Series:

Sources