There are a lot of "what is AGENTS.md" posts now, including one of my own. They answer why the file exists. This one is different: it's the spec, the actual anatomy of the file, section by section, in the order that matters, learned from regenerating it for every app we host.
There is no official list of AGENTS.md sections. What follows is the working spec we converged on after shipping the file into production on every VibeKit app: the version that survived contact with real users, real agents, and a string of painful truncation bugs. If you're writing an AGENTS.md for Claude Code, Cursor, or your own agent loop, this is the shape I'd start from.
The constraint that shapes everything: it's a budget, not a document
Before any section, understand the one fact that governs all of them: AGENTS.md is not a document you write, it's a budget you spend.
The agent reads this file on every turn, prepended to its working context. That context is finite, and most agent runtimes cap how much of the file they'll actually inject. When this post first went up, ours cut AGENTS.md at 5,000 characters; we've since raised the cap to 10,000 (the runtime's stock default is 12,000). Anything past the cap is silently dropped: not errored, and the only warning is a line in a server log nobody reads. Dropped.
We learned this the hard way, more than once. In May, a non-English user's first deploy burned ~12 seconds on path-confusion errors because the "use relative paths, not absolute" guidance lived past character 5,000. The agent never saw it. The rule was in the file and might as well not have been. In July the file outgrew the cap again and the secrets rule and the Safety section vanished from every session. We raised the cap to 10,000, and within a week the file had grown past that too, silently cutting Style and Safety for weeks. Now a test asserts the worst-case rendered size and the presence of every load-bearing rule after any template edit.
So the real spec rule, the one that makes all the others make sense, is: order by consequence. Only what fits under the cap counts, and you want headroom (a test fails any render over 9,900 of our 10,000). Everything in the file competes for that space. If a section can't justify its bytes against "what breaks if the agent doesn't know this," it goes in a different file (more on that below).
Every section ordering decision in this spec follows from that single constraint.
The spec, section by section
Here's the order, highest-consequence first. The full template is renderAgentsMd in agent-templates.ts; this is the annotated skeleton.
1. Identity & environment (first: the agent can't act without it)
# Agent guide
App: **my-dashboard** at https://my-dashboard.vibekit.bot
Repo: user/my-dashboard
A couple of lines, top of file. The agent needs to know what it's working on before anything else: the product name, the live URL, the repo. This is cheap (under 200 chars) and load-bearing. The port is a rule rather than a fact in ours ("listen on process.env.PORT, host 0.0.0.0"), because a server bound to a guessed port is unreachable after deploy.
Keep it factual. No prose. The product name matters more than you'd think: agents default to calling the project by its repo name, which drifts after renames. State the canonical name once, here.
2. NEVER rules (the negative constraints that break the product)
This is the highest-priority behavioral section, and it goes second, right after the agent knows what it's touching. Counterintuitively, the things you forbid matter more than the things you request.
## NEVER (breaks the product)
- NEVER point the user at localhost or "npm start". They have no
terminal, often not even a laptop. The test URL is always the live one.
- NEVER claim "deployed" or "shipped" without a successful deploy result.
- NEVER tell the user to run shell commands or curl. They can't.
Why negatives first: a good behavior the agent misses is a worse turn. A forbidden behavior the agent commits is a broken product. In our case, the single most damaging failure was agents telling phone-only users to "open http://localhost:8000": instructions the user physically cannot follow. One sentence of prohibition prevents an entire class of dead-end conversations.
Be specific about why each NEVER exists in half a clause ("they have no terminal"). Models follow rules they understand better than rules they're just handed.
3. Setup and memory pointers (the every-session bootstrap)
## Workspace
- CWD is the workspace root: relative paths, never /mnt/efs/...
- STATUS.md + MEMORY.md are your memory. Read them for real work;
skip for greetings.
The deterministic first move. When we wrote the first version, this section opened with source .vibekit-env to load the API URL and key; the runtime now injects those as environment variables, so that step is gone and what's left is where to look. This is where AGENTS.md hands off to the other two files in the persistent-memory pattern: STATUS.md (what's happening now) and MEMORY.md (durable decisions). AGENTS.md is the contract; those are the state. Keeping them separate is what lets AGENTS.md stay inside its budget: it doesn't carry project history, it points at the file that does.
Note the explicit "skip for greetings." Without it, agents dutifully cat both files to answer "hi," adding latency to a turn that needed none.
4. Behavioral rules (modes, defaults, tone)
The largest section, and the first one you trim when you're over budget. Group it:
- Mode-switching: trivial messages get text-only replies; build requests get tools. Give an explicit tool-call ceiling ("≤3 per turn, builds excepted").
- Defaults that prevent crash loops: for us, "Express + vanilla HTML/CSS/JS; React/Vite/Next break unless asked." Encode the stack decision so the agent doesn't reinvent it (and reintroduce the same break) every session.
- Tone: concise, outcome-only, no "Let me try…" reasoning dumps in user-facing text.
This section is where teams over-spend. Every "always be helpful" platitude is bytes stolen from a NEVER rule that actually prevents a failure. Cut anything the base model already does well. Better still, replace a rule with a mechanism: in ours, one per-turn [Live-state:] line telling the agent whether its edit is live replaced a 900-character paragraph about deploys.
5. Concrete good/bad examples (models pattern-match better than they parse)
### Bad (NEVER say)
- "Open http://localhost:8000 in your browser"
- "Fixed!" (after a 200 response, without checking the live page)
### Good (say instead)
- "Added the contact form. That's live now."
This is the most compliance per byte you'll get anywhere in the file. A paragraph explaining your tone gets paraphrased; two bad/good pairs get imitated. When a rule keeps getting violated, don't rewrite the rule: add an example of the failure and its fix. The model closes the gap from a demonstration far faster than from a description.
6. Overflow: what does not go in AGENTS.md
Everything that's reference rather than contract moves to an on-demand tier. We keep the full API documentation and the debug runbook in a separate TOOLS.md. Only a short index at its top reaches the agent's context; everything below an "INJECTED CONTEXT ENDS" marker stays on disk until the agent needs it. Product, pricing and setup facts live in a third file, PLATFORM.md:
## More docs
- Full API reference: cat TOOLS.md
- Product, pricing and setup: cat PLATFORM.md
This is the release valve for the budget problem. AGENTS.md answers "how do I behave, every turn." TOOLS.md answers "how do I do this specific thing, when it comes up." Conflating them is how files blow past the cap and start silently dropping their own rules. If a piece of knowledge is only relevant in 1-in-20 turns, it's a TOOLS.md entry, not an AGENTS.md line.
7. Safety & recovery (last: important, but rarely the bottleneck)
## Safety
- Before rm -rf / DROP TABLE / git reset --hard: ask first.
- Recovery: git log --oneline -10, then git checkout <hash> -- <file>.
Genuinely important, deliberately last, because destructive-op guardrails fire rarely. That placement has a price, and we paid it: when our file outgrew the cap in July, Safety was exactly the section that disappeared. Last is only safe if something checks that the whole file fits.
Format conventions
The spec is as much about how you write each line as what sections exist:
- Markdown, flat headings.
##for sections,###for sub-rules. Agents navigate by heading; deep nesting buries rules. - Imperative voice. "Bind to 0.0.0.0," not "the app should probably bind to 0.0.0.0." Hedged instructions get hedged compliance.
- Specifics over principles. "≤3 tool calls per turn" beats "be efficient." A number is a rule; an adjective is a suggestion.
- No meta-prose. No "this section covers…" preamble. Every sentence is either a fact the agent needs or a rule it follows. Preamble is pure budget waste.
- State the why in a half-clause, not a paragraph. "Use relative paths: the sandbox rejects
/mnt/efs/..." earns more compliance than the rule alone, at almost no byte cost.
Anti-patterns (what quietly wastes the budget)
After auditing a lot of these files, ours and others', the recurring failure modes:
- The system prompt in disguise. "You are a helpful, harmless assistant…" The base model already is that. AGENTS.md is for this app's deltas from default behavior, not a re-statement of the model's training.
- Stale project history. "We migrated from Postgres to SQLite in March." That's
MEMORY.md's job. AGENTS.md is the contract, not the changelog; mixing them means the contract gets truncated to make room for trivia. - Aspirational rules nobody enforces. If the runtime can't or won't act on a line, it's decoration. "Always write tests" in a file the agent reads but no CI checks is a wish, not a spec.
- Walls of prose. Three paragraphs explaining the deploy flow lose to one bad/good pair. If you're writing sentences, you're probably over budget and under-compliance.
- Ignoring the limit entirely. The most common one. People write a beautiful 15KB AGENTS.md and never learn that their agent only reads the first part. Check your runtime's injection cap. Then write to it, and test it.
How it's actually read
One more thing the spec implies but doesn't say outright: this file is regenerated, not hand-edited. Ours is re-rendered by renderAgentsMd before every agent interaction, stamped with the current app's name, URL, repo and state (the first-build rules drop out once the first build ships). It's also locked: read-only and owned by a different user than the agent, so neither the agent nor someone chatting with it can rewrite the rules. Per-app facts are interpolated; the structure is fixed. If your AGENTS.md is static and hand-maintained, that's fine for a single repo, but the moment you're running agents across many apps, templating it is what keeps every one of them inside the budget and in sync.
A reference skeleton
Strip it to the load-bearing minimum and you get this. Copy it, fill it in, and keep it comfortably under your runtime's cap:
# <app> agent guide
App: <app> at <live-url> | Repo: <repo>
## NEVER (these break the product)
- NEVER <the failure mode that hurts most>
- NEVER <the second one>
## Setup
<the one-line bootstrap>
For real work also read STATUS.md, MEMORY.md. Skip for greetings.
## Rules
- <mode-switching rule with a number>
- <stack default that prevents the recurring crash>
- <tone: concise, outcome-only>
### Bad, then good
- Bad: <a real failure>. Good: <its fix>.
## More docs
- Reference: cat TOOLS.md
## Safety
- Before destructive ops: ask first.
That's the whole spec. Identity, then what-not-to-do, then how-to-start, then how-to-behave, then examples, then a pointer to everything else, then guardrails, ordered so that if the file gets cut off, what survives is what matters most.
AGENTS.md isn't hard to write. It's hard to write short, and short is the entire game, because the agent only ever reads the part that fits. Spend the budget on what breaks if it's missing, and offload the rest. If you want the longer argument for why a file like this beats a longer context window, that's in the companion post.