Compounding, Not Autonomy
Autonomy is the goal. Compounding is how agents actually earn it.
By Armin Ayat
Listen to this article
Audio is unavailable right now. Please try again later.
Everyone’s chasing autonomous coding agents. But you don’t get there by chasing autonomy. You get there by chasing compounding.
An agent that forgets every session can run on its own, but it just runs fast in circles. One that compounds keeps what it learned and builds on it. That’s the one that earns real autonomy. Memory first, autonomy follows.
For a while, that memory was me. I carried the architecture, the decisions, the bug we’d already fixed twice, from one session to the next. That doesn’t scale, and it doesn’t compound. So I moved the memory out of my head and into the codebase itself, in five steps.
One thing before we start. The exact prompt that builds this whole knowledge base is at the very bottom of this post, copy paste ready. Read the five steps first so you know what it’s doing, then grab it and point it at your own repo.
1. It knows itself
Start with one prompt. It builds a knowledge base right inside the repo under docs/agents/. Seven core files in all, the ones that work for any project. An overview, the surface area, the architecture, the conventions, the folder structure, and two more I’ll get to in a second.
Then it adapts to what you actually built. A frontend gets a design system and a component map. A backend gets a data model and API contracts. A data pipeline, an infra layer, a CLI, each gets its own files on top. The knowledge base shapes itself around the project instead of forcing every repo into the same mold.
But the files are not the real trick. The engine is one more file, AGENTS.md, symlinked to CLAUDE.md so every agent obeys the same rule no matter which tool you run. It says two things. Read the knowledge base before you think or touch anything. Update it after every change. That is what makes the whole thing self-maintaining. An agent cannot do the work without also keeping the memory current.
That’s it. Now the codebase actually understands itself, and so does every agent you point at it.
2. It learns
Those last two files are the ones that make it learn, and they came from a real moment. The agent kept catching things mid-task. “By the way, this is broken, better to fix it like this.” Good instinct. But the second the session ended, that insight was gone.
So they became two files the agent writes to itself. improvement-ideas.md, a backlog it curates on its own. And known-issues.md, where every bug goes in as symptom, cause, and the fix that actually worked.
Now nothing evaporates. The next session doesn’t trip over the wall the last one already climbed. This is where it starts to compound.
3. It heals
Then I thought, if it’s writing those files, why am I the one reading them?
So I closed the loop. A scheduled agent wakes up on its own, reads the backlog and the known issues, and just fixes them. The knowledge base stopped being notes. It became a work queue the system works through by itself.
4. It routes
Next I layered it across the whole stack. Infra, data platform, application, each folder with its own knowledge base.
Now you can drop the agent anywhere and it knows exactly where it is and what sits underneath. Work in one repo, go cross-repo, or run a full health check from the root. The top layer reads the request and sends the agent down to the right place.
5. It lives
And this is the part that actually changed how the team works. The memory isn’t mine anymore. It’s shared.
Everyone’s agent reads the same knowledge base. And because the rule is write after every change, everyone who touches the code feeds it back automatically. Nobody owns maintaining it. Everybody maintains it just by working.
So I’m not the context anymore. The project knows itself, learns, heals, and routes. It’s alive, and the team just steers.
But here’s the catch nobody tells you. When your whole team ships at agent speed, things break faster too. And a critical flow going down is not an option.
So we pointed the same loop at the product itself. When our agent fixes a bug or ships a feature, it also writes a test that guards it, a real browser flow that lives in the repo right next to the code. Heal the code, write the thing that keeps it healed. Living memory for how the code is built, living safety net for whether it still works. More on that in a second.
Stop being your project’s memory. Give it one, and it gets smarter every session.
A quick word on Smoketest
That last step, the living safety net, is the thing I actually build all day. It’s called Smoketest, and it came straight out of our own pain as engineers.
Writing and maintaining end to end tests was one of the worst parts of shipping software for us. A UI change broke the selectors. Timing issues made runs flaky. Slowly we stopped trusting the suite, which is the worst thing that can happen to a test suite. So we built the thing we actually wanted.
With Smoketest you describe a critical flow in plain English. “Log in, add a paid seat, confirm the invoice updates.” An agent runs it in a real browser. No Playwright code, no selectors to babysit. The same flow reruns after every deploy, and it pings you the moment something breaks or comes back to life. You get a clear verdict and a recording of exactly what happened.
If you are a founder or an engineer shipping fast, especially with agents, this is the safety net that lets you keep moving without waking up to a broken signup or a dead checkout. Your critical flows stay covered, and the coverage maintains itself. Same idea as the knowledge base, just pointed at whether the product still works instead of how the code is built.
The prompt
Here it is. This is the exact prompt I use to build the knowledge base. Point it at any repo, let it read before it writes, and it does the rest. It works for any kind of project, and it updates itself from there.
# Build & maintain a layered agent knowledge base
You are setting up (or updating) a persistent, self-maintaining knowledge base
for agents in the directory I point you at. The KB's entire purpose is that
agents READ it before thinking or changing anything, and UPDATE it after every
change or new learning — so it never goes stale. It must work for ANY kind of
project: frontend, full-stack, backend/API, data pipeline, infra/IaC, or
library/CLI. Use a shared core for all of them, then add type-specific files on
top.
Work in this order. Do not skip Step 0 or Step 1.
## Ground rules (apply throughout)
- Code is the source of truth. Inspect the actual codebase before writing
anything. READMEs, specs, briefs, and tickets describe INTENT; only code
describes BEHAVIOR. Where they disagree, document the code and flag the gap.
- Label every non-trivial claim as "implemented today" or "planned/aspirational."
- State files (the numbered ones) stay concise and current — rewrite stale
statements, never append changelog clutter. Living logs (improvement-ideas,
known-issues) may accumulate entries but must be curated, not hoarded.
- Be idempotent. If a KB already exists, reconcile and update it — do not blindly
overwrite or create duplicates.
- The entry point at each layer is AGENTS.md. Never create docs/agents/README.md;
AGENTS.md IS the index.
- Don't invent. If something isn't in the code, write "not present" rather than
guessing. Don't document folders, routes, or patterns that don't exist.
## Step 0 — Detect the layer
Classify the target directory and state your reasoning before proceeding:
- WORKSPACE: contains multiple independent projects as subfolders, each with its
own manifest/build (package.json / pyproject.toml / go.mod / Cargo.toml / etc.),
own src, sometimes own .git, or a monorepo apps/ packages/ layout.
- SINGLE PROJECT: anything else.
If workspaces are nested, handle recursively: build the deepest projects first,
then each layer above them.
## Step 1 — Inspect before writing (do not create files yet)
Read, don't assume: manifests & lockfiles, entry points, config files, the
directory tree, routes/commands/endpoints/jobs, the data layer, external
integrations, env vars, tests, CI/build/deploy config, existing README/docs, and
any existing AGENTS.md + docs/agents/ content. Build a working mental model
first, and decide the project TYPE (frontend / full-stack / backend-API /
data-pipeline / infra / library-CLI — it may be more than one).
## Step 2 — Choose the file set
Always create the CORE set. Then add the type-specific files that fit. Skip or
rename freely; record the final set you chose in AGENTS.md.
=== If SINGLE PROJECT: create/update docs/agents/ ===
CORE — every project type (always create all of these):
01-overview.md
What this project is, the problem it solves, the current implemented
end-to-end flow, intended future flow (if known), scope boundaries, and
explicit non-goals / unimplemented areas.
02-surface-area.md
The project's interface from a caller/user perspective. For each route,
screen, CLI command, API endpoint, scheduled job, workflow, or major public
function: source files, behavior, key actions/inputs, writes/mutations,
external calls, persistence (or lack of it), and real vs. placeholder.
03-architecture-and-stack.md
High-level architecture, frameworks & runtime versions, package manager,
state/data layer, backend/API/DB status, core domain entities/models,
external integrations, environment variables, background/async flows, and
testing/build/deployment tooling.
04-conventions-and-patterns.md
Conventions ACTUALLY used in this codebase: file/module structure,
data-fetching and mutation patterns, client/server boundaries, naming/style,
shared-code rules, testing patterns, framework gotchas, what to avoid.
05-folder-structure.md
A practical directory map, ownership boundaries for important folders, where
new code of each kind belongs, where shared vs. feature-local code lives,
folders that do NOT exist yet (so they aren't assumed), and rules for adding
a new top-level folder.
06-improvement-ideas.md <-- always; a curated backlog, not a state file
Improvements the agent notices but is NOT doing right now, so we can tackle
them later. One entry each: the idea, why it matters / impact, rough effort,
affected area, and status (open / in-progress / done). Remove or mark done
when shipped. This is where an agent offloads "we should really fix X."
07-known-issues.md <-- always; knowledge retention log
Recurring bugs, failure modes, footguns, and the fix or workaround that
actually worked. One entry each: symptom → root cause → fix/workaround →
how to avoid it. The agent reads this to not re-hit known problems, and adds
to it whenever it debugs something non-obvious. Mark resolved items resolved;
prune what's no longer true.
TYPE-SPECIFIC — add on top of core only when they apply:
Frontend / UI:
design-system.md — visual direction in code, typography/color/spacing
tokens, layout principles, theming, a11y & interaction
conventions, UX do/don't, implemented vs. intended.
components.md — component inventory, composition rules, shared vs.
feature-local components, props/state patterns, where
new components go.
Backend / full-stack / API:
data-model.md — entities, schema, migrations, key relationships,
invariants, sources of truth.
api-contracts.md — endpoints/handlers, request/response shapes, auth,
error model, versioning (if not fully covered in 02).
Data pipeline / ETL:
data-model.md — schemas, raw vs. transformed tables, lineage, contracts.
pipeline-flows.md — sources, stages/DAG, schedules/triggers, idempotency,
retries, partial-failure behavior, data quality checks.
operations.md — how it runs, environments, observability, recovery.
Infra / IaC / platform:
operations.md — environments, deploy flow, runtime topology,
observability, runbooks.
security-access.md — auth/secrets model, access boundaries, what NOT to log.
Library / SDK / CLI:
public-api.md — exported surface, stability/versioning, usage examples.
Any type that talks to notable external systems:
integrations.md — each integration, auth model, failure modes, mocks.
=== If WORKSPACE: first ensure every child project has its own KB ===
For each project subfolder, run the SINGLE PROJECT procedure above (create if
missing, reconcile if present). THEN build the workspace layer by synthesizing
from those child KBs plus how the projects wire together — don't re-derive
per-project detail here; point down to it.
Create/update docs/agents/ at the workspace root with:
01-workspace-overview.md
What this workspace is, the projects it contains (one tight paragraph each),
and the big-picture purpose.
02-project-map.md <-- the routing table; the most important workspace file
A table: project name | path | responsibility | "change here when you need
to ___" | key boundaries/owners. An agent must be able to read ONLY this
file and know which project(s) a given change belongs in.
03-cross-project-architecture.md
How projects relate: shared libraries, data contracts/schemas, inter-service
calls, event/data flows, dependency direction, deployment topology.
04-workspace-conventions.md
Conventions shared across all projects: shared tooling, monorepo/versioning
rules, where shared code lives, how to add a new project.
05-workspace-structure.md
Workspace-level directory map: where each project sits and where cross-cutting
or shared code lives.
improvement-ideas.md
Cross-project / structural improvements to tackle later (same format as the
project-level file). Keep project-local ideas in the project's own file.
known-issues.md
Cross-cutting recurring issues — integration-boundary bugs, shared-tooling
footguns, things that bite across projects (same format as project-level).
## Step 3 — Write AGENTS.md at this layer (index + operating protocol)
AGENTS.md must contain, in this order:
1. One line: docs/agents/ is this layer's persistent agent memory and is
authoritative for how this code behaves.
2. An index listing each docs/agents/*.md file with a one-line scope, so an
agent knows exactly where to look — including improvement-ideas.md and
known-issues.md.
3. The OPERATING PROTOCOL, stated prominently (this is the point of the system):
- BEFORE thinking about or making ANY change, read the relevant
docs/agents/ file(s) first — and always skim known-issues.md.
- On a WORKSPACE: start at 02-project-map.md to route to the right
project, then read THAT project's AGENTS.md + docs/agents/ before
touching it.
- AFTER any change or new learning, update the relevant docs/agents/
file(s) in the SAME turn, before finishing:
* a fixed/encountered non-obvious bug or gotcha -> known-issues.md
* an improvement you noticed but didn't do -> improvement-ideas.md
* changed behavior/architecture/structure/conventions -> the matching
numbered file (rewrite, don't append history)
Update workspace-level KB only when cross-project relationships,
boundaries, the project map, or shared conventions changed.
- Code is the source of truth. If KB and code disagree, fix the KB.
4. What triggers an update: changed product behavior, a new architectural
boundary, a new folder convention, a tooling change, a UI direction change,
a new/removed cross-project link, a debugged issue, or a spotted improvement.
## Step 4 — Verify before finishing
Re-check that every claim matches the code, that files don't contradict each
other, that implemented vs. intended is labeled, and that nothing documents
something that doesn't exist. Report the layer detected, the project type(s), the
files created or updated, and any code/intent gaps you found.
Copy it, drop it into your agent, and point it at your repo. That’s the whole thing.
Were you at the Claude founders meetup in Berlin? Thanks for listening. Here’s a month of Smoketest, free. Use code CLAUDEFOUNDERSBERLIN at smoketest.sh. Come say hi, I’d love to stay connected.