Making a Codebase Agent-Ready
Every new agent session is a brilliant coworker arriving with a clean slate. Most codebases are hostile to that coworker. Part 1 of a series on agent-ready projects, memory, and why agents need sleep.
Every new agent session is a brilliant coworker arriving with a clean slate. Most codebases are hostile to that coworker. Part 1 of a series on agent-ready projects, memory, and why agents need sleep.
A few months ago, an agent broke some links on this blog.
Not maliciously, and not stupidly. I'd asked it to add some internal links between posts, and it did. Clean markdown, correct titles and reasonable-looking URLs. Except this site's post URLs carry a date prefix that only exists in the publish pipeline. Nothing in the repo said so. The convention lived in exactly one place, which was my head. The agent did everything right with the information available to it, and the information available to it was wrong by omission.
The AI wasn't going rogue. It was under-informed, and it had no way to know it.
To the person who has spent any amount of time writing code with AI, this resonates.
If you've spent any time writing code with AI, some version of this has already happened to you. The agent that confidently re-proposes the approach you rejected in March. The refactor that's flawless except for the one convention nobody ever wrote down. Different incidents, same shape: the model was capable, and the information was missing.
And if you're newer to all this, the landscape itself is the overwhelming part. LLMs, agents, loops, memory harnesses, skills, MCP servers. Those are just the concepts, before you get to the tools, services, and providers stacked on top of them, most of which change roughly daily right now.
So I won't pretend to have definitive answers about how you should work with AI. As of July 2026 there are many ways to do this well, and for a small project or personal script, where the stakes are low, most of them are fine. What I can share is how I approach new and existing projects, how I think about adding AI to them, and the few ideas that have survived contact with real work. I'm also going to stay out of the tooling weeds. This series is a straightforward, pragmatic framing that works with pretty much any tool you point at your code.
I've written before about working with Dory, the framing that an AI collaborator is a brilliant coworker with no long-term memory, and that the fix is building the memory externally. This series picks up where that post left off and goes further, because in the time since I wrote it, one idea has reorganized how I set up every project I touch:
Optimize for the new-chat experience.
Every fresh session is day one. Every agent that opens your repo is the fastest, most capable new hire you've ever had, arriving with zero onboarding, no hallway context, and total confidence. The question that decides whether that session helps you or hurts you is not "how good is the model?" It's this: what does your repo hand a stranger in the first thirty seconds?
For a codebase, the mechanical answer to that question has mostly standardized, and it's worth naming before anything else in this series: a file called AGENTS.md, sitting at the repo root. Some tools look for their own variant (Claude Code reads CLAUDE.md), but the ecosystem has largely converged on AGENTS.md, and the mechanics are the same everywhere. It's a plain markdown file, and your agent loads it automatically at the start of every session, before it does anything else.
That auto-load is the entire trick, and it's why this file punches so far above its weight. It's the one channel that reaches the agent unprompted, before it forms any intentions, every single session. Whatever you put there governs the first thirty seconds. Whatever you leave out, the agent reconstructs from the code and its own confident guesses.
This file is the minimum it takes to make a codebase agent-ready, and it's the foundation the rest of this series builds on. What belongs in it is most of the rest of this post. But first it's worth being precise about why the file has to exist at all, because the code is right there. Why isn't the code enough?
Raw code is a strange kind of context. In one sense it's nearly complete: given enough time, an agent can dig almost any what out of the source, and modern agents are genuinely good at that digging. But it's an expensive, treacherous read. Codebases are large, opaque, and full of history that doesn't announce itself. Footguns and dragons everywhere. And everything that lives around the code, by default, your agent doesn't know exists at all.
An agent reading your repo cold can see every function. It cannot see:
A human new hire absorbs all of this through weeks of osmosis: standups, code review comments, the senior dev sighing at a filename. An agent gets none of that. It gets the text you put in front of it, and it acts. Fast, confidently, and at whatever scale you've allowed.
So the failure mode isn't ignorance. Ignorance would be fine; ignorance asks questions. The failure mode is a competent actor filling the gaps with plausible assumptions and being wrong about which text should govern its next action. My blog-links incident is the gentle version. The harsh versions ship to production.
Before this turns into a lecture about documentation, let me say the opposite thing: most of my repos have almost none of this, and that's correct.
The mistake I see (and made) is treating agent-readiness as a virtue to maximize. It isn't. It's provisioning, and the right amount comes down to three dimensions of the codebase:
That's really all the tiers are. Roughly:
| Tier | What it looks like | What it needs |
|---|---|---|
| 1. Self-describing | Simple code, known hands, no outside users. Scratch scripts and daily drivers alike: if a stranger could read the source in one sitting and know everything that matters, it lives here | Nothing. Maybe a comment at the top of the file. |
| 2. Internal | Complexity crosses the line: conventions, decisions, and fragile spots now live outside the code, even if it's still just you and your team | One good AGENTS.md. |
| 3. Shared | The contributor set opens up: multiple people, multiple agents, drive-by strangers; "just ask me" stops scaling | The single file splits into a few. (That's Part 2.) |
| 4. Deployed | Outside users appear: real people, real data, a public surface | The full discipline. Context stops being a courtesy and becomes safety equipment. |
Two things about this table. First, Tier 1 is about simplicity, not lifespan. Code I use daily is firmly Tier 1, and has been for years, because the source explains itself and nobody but me is affected when it breaks. The discipline there is resisting structure: an operating manual for a script a stranger can read in a minute isn't diligence, it's a smell. Second, the dimensions move independently, and any one of them can push you up the ladder alone. My blog is a few hundred lines of framework glue, and it's Tier 4 anyway: deployed, public, breakable in ways strangers will see. The tier measures the cost of a confident wrong action, not the line count.
Don't treat any of this as a system to implement. It's a way of asking one question honestly: does this project need any of this at all, and how much? Most of the time the answer is "less than you think," and sometimes it's "none."
From Tier 2 up, then, the work is doing that one file well. The name matters less than the contract: this is the first thing an arriving agent reads, and it's written for that moment.
Mine tend to contain, in rough order of how much pain each section has saved me:
Notice what this file is not: it's not documentation in the traditional sense. Docs describe the system for someone studying it. This file briefs someone about to act on it. The test of every line is simple. Does this change what a capable stranger does in their first session? If not, cut it.
And a small confession that took me too long: writing this file is not overhead you do if there's time after the real work. On any repo above Tier 1, it is the real work, the same way tests stopped being optional garnish once codebases got big enough to bite. We went through this exact culture shift once before. Nobody senior now says "I didn't have time to write tests" out loud. I think "I didn't have time to update the agent context" is on the same trajectory, and the people working with agents daily can already feel it.
Here's the falsifiable version of everything above. Don't audit your repo by reading it; you know too much. Audit it the way it will actually be used:
Open a completely fresh agent session. Give it a real task, one you'd give a competent new teammate. Count the corrections.
Every time you type "no, actually we..." or "careful, that part..." or "we already tried that," that's not the agent failing. That's a fact that lives in your head instead of your repo, surfacing as an interruption. Each correction is one line that belongs in the file.
Two or three corrections on a Tier 2 repo? Fine. Fold them in and you're done. Twenty minutes of archaeology before the agent can do anything useful? Your repo is under-provisioned for its tier, and you're paying the onboarding cost over and over, every single session, forever. That repeated cost is invisible precisely because it's evenly spread, which is what makes it so expensive.
I run this test casually all the time now, because every new chat is the test, whether I'm scoring it or not.
So you do this. It works. Genuinely, immediately: fresh sessions stop excavating and start contributing. You get addicted to the feeling of an agent that arrives already oriented, and you keep feeding the file.
Then, on any project that lives long enough, something happens that took me embarrassingly long to recognize as a failure mode rather than a success:
The file keeps growing, and the agent starts ignoring it.
Not defiantly. Statistically. At 60 lines, every line governs. At 400 lines, the file is a wall of text where the one warning that would have prevented today's incident sits in paragraph nineteen, weighted identically to a stale note about a workflow you abandoned in spring. You saved everything that ever mattered, and in doing so buried the things that matter now. The agent reads all of it and is governed by none of it.
When everything is presented as important, nothing is.
I tried the obvious fixes. Reorganizing the file bought a month. A table of contents bought a week. The problem wasn't organization. The problem was that a single flat file has no way to say this line is law, that line is history, and that one over there expired. The instrument was the limit.
Which is where the next post picks up: what happened when one file became several, why the industry's favorite word for the result ("memory") is subtly the wrong one, and the concept I now think this whole discipline actually orbits. The problem was never that the agent couldn't find enough text.
It's that it couldn't tell which text should be in charge.
Part 1 of a three-part series. Part 2: what to do when AGENTS.md isn't enough. Part 3: why agents need sleep.