If your codebase is good for new-joiners, it's also good for agents
A fresh agent session is structurally a new joiner: empty context, no tribal knowledge, dependent on what's discoverable. The difference is that the new joiner pays the onboarding tax once, and your agent pays it several times a day.
Starts with an empty context. Explores the repo to figure out how things work, picks up patterns that are already deprecated, follows docs that don’t match reality anymore… and the output needs a careful review before you can trust it.
You probably are thinking of agents, context windows, fresh sessions… but I was talking about this new guy who joined last week.
He tries to find his way through the giant codebase with 3 different ways of styling, different UI libraries, multiple validation approaches. And some components with “new” in the filename which are actually used nowhere. The wiki pages he reads are outdated for at least half a year, and it takes him a whole day (and asking multiple people) just to get the complete stack running. Only to find out one important service he has no access to is missing.
It maybe sounds familiar. Everybody knows this is something we should clean up, but other things have more priority, and “hey, you just have this pain once, then you know it”.
That’s true for the new joiner. His context window fills up once and stays. But there is one guy going through this exact process multiple times a day, with a context window that gets deleted on every fresh session… your code agent.
TL;DR
- A fresh agent session and a new joiner have the identical problem → no prior knowledge, only what’s findable
- The difference is the frequency. The human pays that once, the agent pays it on every new session, forever
- Agents are really good at self-onboarding, but only up to the quality of what’s findable
- They don’t hallucinate your architecture, they infer it from the stuff you left lying around
- Agent confusion doesn’t reach you as a question. It reaches you as a mediocre diff.
Why it’s the same problem
An agent session starts empty. It knows nothing about your project, your conventions, or that three year old decision behind the weird adapter in the payments module. It builds that up the only way it can: searching, going through the code, following the links you left it… and it does that again on the next session, and the one after that.
The good news is agents are really good at this. It’s the part they are built for: reading a lot of unfamiliar material fast and staying close to what’s actually there instead of inventing something. A fresh session is maybe even the better onboarder: faster, never tired, and no ego about reading the same file for the fifth time.
But that only holds as long as the material supports it. An agent finds its way when the path from “task” to “the right file” is short, when there is one way to do a thing instead of three half-migrated ones, when the documentation matches the code. And when the reasoning behind non-obvious decisions is written down somewhere the code can’t say it itself.
Take that away and the agent doesn’t fail loudly. It does something worse: it infers confidently from bad evidence. Three styling approaches in the repo means it picks one, plausibly and defensibly… and often the deprecated one.
That’s not really a hallucination, the codebase told it wrong.
And that’s also why dead code became an actual liability. A human learns at some point that everything with “new” in the name is the abandoned rewrite. An agent reads it as the newest and most intentional version, because that’s literally what the name says.
The frequency is the whole argument
If this was only about quality, this post would be the usual “keep your codebase clean” advice and you would have stopped reading. The thing that changed is the multiplier.
Onboarding used to be a one-time cost per person. You could rationally decide to leave the mess and let that pain be paid by somebody new, twice a year. The maths worked out. Now the same environment gets re-read by a fresh context multiple times a day, by something that produces code the whole time. A one-time tax became a recurring one and nobody redid the calculation.
And the pain is invisible, which is really the problem. When the new joiner runs into the wall, he walks over and asks you. When the agent runs into it, it just produces something slightly wrong and you think: the model is getting worse.
The feedback that would tell you your environment is broken never reaches you as a question. It reaches you as a mediocre diff.
Your new joiner is a measurement instrument
Which brings me to the practical part. You can’t ask your agent what confused it, but you can ask a human, and the answer transfers nearly perfectly.
You really can test your setup when you have new people joining. If they have no questions at all, that reads in two very different ways: either you did a great job, or they decided to struggle through quietly instead of looking slow in week one. Ask them to walk you through their first day if you want to know which one it was.
If there are a lot of questions, look at what kind:
- “why don’t we have this?”
- “why is this not working?”
- “what do I need to install?”
- “something is not working as I assumed”
- “this readme is pretty old, is this actually up-to-date?”
Every single one of those is a gap between what your project claims and what it is. And each one tells you three things at once: you are answering out of experience that is written down nowhere, that knowledge is not spread around the whole team either. And there is a high chance this is also the answer why your results with agents are not as good as everybody told you they would be.
That last one is the interesting one for me. If your agents underperform, the instinct is to reach for a better model, a longer prompt, more tooling. Sometimes the honest answer is that you handed a competent worker a codebase where the truth is not findable.
Where the answers go
So now you have a list of questions. The tempting move is to dump every answer into one big context file so the agent always has it.
Don’t → a big CLAUDE.md measurably doesn’t help and can even hurt, and it is a tax on every single session, no matter if the information is relevant this time or not.
Put the answer where the question was asked instead. If the confusion was about a function, the answer is a comment above that function. If it was about a setup step, the answer goes into the setup script, or into the error message that fires when the step is missing. If it was about a decision, write the why next to the thing it explains. That’s the one piece of context an agent can never derive from reading the code, because it’s about the alternatives you rejected.
That’s a full reversal for me by the way, and it took a while. I used to treat comments as a smell. But that rule was about humans maintaining prose they don’t want to maintain… and the reader changed. There is more about where exactly that inverts in Maintainable for whom?.
And while you are in there: delete the dead component, finish the half-done migration, fix the readme. Not as a cleanup sprint. As the cheapest AI investment you have available → no budget, no vendor, no procurement.
One effort, two beneficiaries
I like this one because you don’t have to believe anything about agents for it to be worth doing. Making a codebase self-explaining was always the right thing, it just never had a good enough business case against the next feature.
Now it has one. Improving the environment for a new joiner automatically improves the environment for the coding agents and the other way around. One effort, two beneficiaries. This is something we could work on and keep an eye on.
The agents didn’t create this problem. They just made it expensive enough to finally care about it.