# I argued with AI (Codex) about AGENTS.md. Then I realized what it actually was.

> Source: <https://dev.to/wolfejam/i-argued-with-ai-codex-about-agentsmd-then-i-realized-what-it-actually-was-5ee>
> Published: 2026-10-15 14:35:40+00:00

When I was building FAF, I built it with Claude, starting on Sonnet 3.5 (yes, I thought 3.7 had come down from heaven!). I needed to test other AIs too. The Big 3 were Anthropic, Google's Gemini, and OpenAI, who had just released Codex.

All three got FAF from the get-go. It had a schema and it was YAML, and they love structured data. It's like YAML and noodles to AI 🍜. Claude had `CLAUDE.md`, and Gemini reinforced that (copied it, lol) with `GEMINI.md`. But not OpenAI. There was no `CODEX.md`. They had `AGENTS.md`, and Codex kept telling me it "had context." I was fighting with an AI.

So I stopped using Codex for a while.

Then the industry chose. `AGENTS.md` became the file every coding agent reads: Codex, Cursor, Copilot, Windsurf, Amp, Devin. OpenAI gave it to the Linux Foundation's Agentic AI Foundation in December 2025, and it became an open standard.

Codex said it had context. I said it didn't. Then a developer from the Svelte community asked me, "Isn't this what `AGENTS.md` does?"

I had to sit back and look. And the penny dropped.

`AGENTS.md` is a guide *for agents*: how to build, how to test, the conventions, what not to touch. Instructions.

That's all it was ever meant to be, and it's good at it.

The argument I'd been having was never about which file wins. It was about something markdown doesn't do: say **what the project is**. What it's for, who it's for, what it's built on, what doesn't apply. Instructions need something to be *about*.

`AGENTS.md` is markdown, not YAML: prose, for instructions. `project.faf` sits upstream, next to `package.json`, and gives `AGENTS.md` the falsifiable facts about the project, on demand. `AGENTS.md` instructs the agents.

That's where the line came from:

**FAF defines. MD instructs. AI codes.**

becomes

**FAF defines. AGENTS.md instructs. AI codes.**

`project.faf` is a small YAML file at the root of a repo. It is to context what `package.json` is to dependencies, and it sits right next to it:

```
project/
├── AGENTS.md        ← agents follow this
├── package.json     ← npm reads this
├── project.faf      ← AI reads this
├── README.md        ← humans read this
└── src/
```

It holds the facts: the goal, the stack, the who, what and why. Each one is a **validated fact**, from one of two places only:

`faf auto` reads (runtime, build, CI, hosting);`faf go`.
Nothing is guessed. A placeholder like `tbd` counts as empty, because it has no source.

It feeds the facts to AI, so tokens are best spent on following instructions and coding.

**FAF defines. Context, compiled.**

This matters more than it sounds. A 2026 study, *Evaluating AGENTS.md: Are Repository-Level Context Files Helpful for Coding Agents?* (Gloaguen et al., [arXiv 2602.11988](https://arxiv.org/abs/2602.11988)), found that "providing context files does not generally improve task success rates, while increasing inference cost by over 20% on average", for LLM-generated and developer-committed files alike. Their advice: use them for what's non-standard, and evaluate anything else before you rely on it.

Their latest version adds a finding that matters here: instructions in context files are well followed, but repository overviews, "although popular and recommended by model providers, are not helpful." That's the split this post is about. The paper doesn't say why. My read: an overview is, simply put, more prose. And prose can be stale, non-specific or contradictory, and an agent can't tell which.

So FAF doesn't write one. The definition stays in `project.faf`, where every fact has a source, and what lands in `AGENTS.md` is commands, guardrails and the stack: things an agent can run or check. The study tested markdown context files, so it shows the limits of prose. Structured data, a schema in YAML, wasn't in it. That's the right next test, and their advice says so too.

So: keep the file lean, and give the agent **facts with a source**.

That's how FAF writes it:

```
npx faf-cli export --agents
```

It writes the standard file, plain conformant markdown, never a FAF dialect. Inside it, FAF manages one block of facts: setup and build commands, how to run the tests, where things live, guardrails, the stack. Anything you wrote by hand outside that block is kept. When the facts change, run the same command and the block is rewritten from the source, so it doesn't drift.

Here's where any repo stands. With the ladder and the managed block, FAF and `AGENTS.md` work together, streamlined:

|  | NONE | GOOD | BETTER | BEST | 
|---|---|---|---|---|
| What it is | No `AGENTS.md` ; agents guess | Any `AGENTS.md` | An `AGENTS.md` with the managed block: lean, current, checked | BETTER, plus `project.faf` in the repo: the source behind the block, and far more, with the app type and the human context (goal, who, why) | 
| What happens | Every session starts blank | Goes stale, quietly | The block's facts have no source in the repo | Facts and instructions stay in step | 

Most repos are in the first column. Getting to GOOD is one file. BEST is where the facts stop drifting, because they're defined in one place and every instruction file points back to it.

Here's the part I enjoy most. In September, Claude Code started reading `AGENTS.md` too: in a project with no `CLAUDE.md`, it uses `AGENTS.md` instead. The two camps I was choosing between have met.

Which makes the point for me. The file that instructs will keep changing names, vendors and rules. The facts underneath will not. Define them once, and let every instruction file, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `.cursorrules`, point back to the same source.

Paste either into your terminal or AI 👇

```
npx faf-cli auto
npx faf-cli export --agents
```

★ bookmark repo: github.com/Wolfe-Jam/faf-cli

Then ask your agent what the project is. It won't have to guess.

Help guide what we build —

Comments · suggestions welcome.
