Architecture notes for coding agents that actually help
Learn how to write architecture notes for coding agents that cover naming, service boundaries, and risky areas, so generated code fits your codebase.

Why agents drift in a real codebase
Coding agents do not read a repo like a careful teammate. They grab the nearest pattern that seems to work. If the closest example is old, half finished, or just odd, the agent often repeats it with confidence.
That is why a messy folder can pull generated code in the wrong direction. One stale handler, one outdated naming style, or one shortcut around business logic can spread fast. The agent sees a local pattern and treats it like a rule.
Vague prompts make this worse. If you ask for "add user billing support" without naming the service, the file, and the rules, you often get mixed results: camelCase in one place, snake_case in another, validation in the controller, pricing logic in a helper, and database access where it should not live.
Long design docs rarely stop this drift. Agents usually need a few sharp rules close to the work, not a full history of the system. A page or two with naming rules, service boundaries, and known danger zones often helps more than a 40 page architecture deck nobody reads during generation.
Short notes work because most codebases run on local habits. Maybe all write operations go through one service. Maybe background jobs must never call a public API client directly. Maybe anything tied to payments needs an extra review. These rules can look minor, but they decide whether new code fits or feels foreign.
A simple example makes the problem obvious. Say newer modules put business rules in services, but an older endpoint still calculates discounts in the controller. The agent sees that endpoint first and copies the old layout. The code may pass tests and still be wrong for the team.
Architecture notes for coding agents should stop that kind of drift. They are guardrails, not a full system spec. The goal is simple: help the agent choose the right pattern before it writes 300 lines in the wrong place.
What a short note should cover
Agents do not need a handbook. They need a page they can read in a minute and use while they code. If the note runs long, people skip it, and the agent misses the parts that actually shape the output.
A useful note answers a small set of practical questions. Where should this file go? What names do we use for this kind of thing? Which module owns this logic? What areas need human review before anything gets merged?
Keep only the rules that change the output
Write down only the local rules that affect file placement, code shape, and review risk. Those rules stop the most common mistakes: putting logic in the wrong layer, inventing new naming styles, or touching parts of the system the team handles carefully.
In practice, that usually means folder and file placement, naming patterns for handlers, services, jobs, and tests, module boundaries, forbidden shortcuts, sensitive areas such as billing, auth, migrations, and shared schemas, plus the cases where a person must approve the change before merge.
That is enough for the agent to stay on track. It is also enough for a new teammate to get oriented quickly.
Skip broad advice like "write clean code," "add tests," or "keep functions small." Those are fine rules, but they do not explain how this codebase works. Local conventions matter more than general software advice.
Plain language matters too. If a new engineer cannot understand the note on day one, the agent probably will not follow it well either. Use direct sentences and concrete examples, such as "API request types live next to the route" or "only the billing service can write invoice records."
A small startup team can keep this to one or two pages and still get good results. One clear example often does more than five abstract rules. If the note helps someone place a new feature in the right folder and avoid one risky edit, it is doing its job.
Naming rules worth writing down
Most teams think naming is obvious until a coding agent adds UserManager, user-service, users.ts, and customer_data to the same feature. Each name looks reasonable on its own. Together, they make the codebase harder to scan and harder to trust.
Start with file and folder rules. Keep them boring and consistent. If your team uses kebab-case for files and folders, say so and give one example that shows the whole pattern, not just one file.
For example, a payments feature might look like this:
payments/create-invoice-handler.ts
payments/invoice-service.ts
jobs/retry-failed-payment-job.ts
That one sample tells the agent more than a paragraph of abstract advice.
Name code by role, not by vague intent. A handler should sound like an entry point tied to a request, event, or command. A service should sound like business logic. A job should sound like scheduled or queued work. If the team writes database fields in snake_case but keeps application code in camelCase, write that down plainly. Agents often mix those styles unless you spell it out.
A short naming block is usually enough:
- Handlers end with
-handler - Services end with
-service - Jobs end with
-job - Database columns use
snake_case - App variables and object fields use
camelCase
Also name the words your team avoids. This matters more than people expect. If manager means a long lived coordinator in your codebase, do not let the agent use it as a synonym for service. If model means a database entity, do not use it for API payloads. Ban fuzzy names like helper, common, data, and process unless the team already uses them with one clear meaning.
Plural and singular names trip agents up all the time. Many teams use plural names for routes and tables like users and orders, but singular names for files and types like user.ts and Order. Trouble starts when one feature uses invoice, another uses invoices, and nobody remembers which one holds a list and which one holds one record.
If a reviewer has to guess what a name means, the note is not finished.
Service boundaries agents should respect
Agents make the biggest mess when they cross a line humans already know by habit. A short note should name those lines in plain language, because the model will not infer them from folder names alone.
Start with ownership. Write down which service owns each record and each business decision. User profile data may live in accounts, subscription status in billing, and permission checks in auth. That stops a common failure: generated code reads data in one service, makes a decision in another, and saves the result in a third.
Spell out call paths too. Some code can use a local package. Other actions must go through an API, event, or queue, even if a direct database query looks faster. If the order service needs invoice status, say "call billing API." Do not leave that rule implied.
Shared utilities need a clear edge. Agents often move logic into a common package because it looks neat. That spreads domain rules across the whole codebase. Utilities should handle plain cross service work like logging, retries, date parsing, or ID formatting. Service logic should stay with the service that owns the data and the decision.
Copy and paste between services causes a different problem. A model sees similar handlers and clones them, including the wrong validation rules, table names, or event shapes. Common failure points include auth checks copied into product code, billing rules copied into onboarding flows, notification templates copied with service specific placeholders, and request or response structs copied, then changed in one service only.
A small example makes the rule stick. In a SaaS app, an agent may add "suspend account for non-payment" inside the user service because that is where the account screen lives. The boundary note should say billing decides delinquency, auth enforces access, and the user service only displays status.
That level of detail is enough. You do not need a full system map. You need a page that tells the agent where to stop.
Risky areas to flag early
Some parts of a codebase can absorb small mistakes. Others turn one wrong change into an outage, bad invoices, or silent data loss. Your notes should name those areas early so the agent does not treat them like ordinary files.
Start with the modules that break in ways people notice late. Billing code, auth checks, permissions, database migrations, and background jobs belong on that list almost every time. They often look small on the surface, but they carry rules that sit outside the file itself.
Code that needs extra caution
A short note can call out risky spots like these:
- files that calculate prices, taxes, credits, refunds, or invoices
- login, session, token, and role checking code
- permission checks hidden in middleware, helpers, or decorators
- migration scripts, seed data, and anything that changes schema
- workers, queues, schedulers, retries, and email or webhook jobs
Legacy code needs a warning too. A folder may look simple, yet depend on old naming, old database fields, or behavior that nobody would guess from reading one function. If a module has hidden assumptions, say so in one blunt sentence. For example: "Do not rename fields in this package. Old mobile clients still send them."
When the agent should stop
The note should also say when guessing is not allowed. That saves time during generated code review because reviewers see fewer confident but risky edits.
Ask for review before the agent changes money flow or invoice logic, edits auth, roles, or access rules, writes or rewrites a migration, touches retry logic, cron jobs, or idempotency checks, or finds two possible patterns and cannot tell which one the team wants.
Be specific about the stop points. "If you touch anything under billing/, auth/, migrations/, or jobs/, make the smallest safe change and ask for review before expanding scope" is enough. A line like that prevents a lot of expensive mistakes.
How to write the note step by step
Start with the mistakes that waste the most time. Pick the three you see again and again in generated code. Maybe agents keep putting business logic in controllers, naming database fields in two different styles, or calling a service that should stay private. If a mistake rarely happens, leave it out.
Then write the rules in the shortest form that still makes sense. Good notes read more like a shop manual than a design document. One page is often enough.
List the repeat mistakes in plain language. Add naming rules with simple examples, such as "use customer_id, not customerId in SQL." Add boundary rules that say which service can read billing data and which one must call an API. Then add one tiny example change that shows the right pattern in context.
Keep the naming and boundary rules concrete. "Keep modules clean" is too vague. "HTTP handlers validate input, services hold business rules, repositories touch the database" is much better. Agents follow local patterns when you spell them out.
A small example helps more than a long explanation:
Change request: add invoice status to the customer screen.
Expected pattern: handler reads request, customer service asks billing service for status, billing tables stay inside billing service, UI uses existing status enum names.
That one block can prevent a lot of bad code. It shows naming, ownership, and where data can cross a boundary.
After one real task, review the note right away. Check what the agent still got wrong and what nobody used. Cut dead rules. Add the missing one that would have prevented the mess.
This matters even more on fast moving teams. Clear local rules people actually read beat long docs people ignore. If your note keeps getting skipped, it is too long or too vague.
A simple team example
Imagine a small SaaS product with four parts. The web app shows dashboards and exports. The API handles logins, reports, and billing requests. A worker builds heavy reports in the background. The database stores users, invoices, report jobs, and audit events.
A short repo note might say:
- Reporting changes go in
api/reports,worker/report_jobs, and the reports pages in the web app. - Billing code stays in
api/billingandweb/billing. Do not import billing types into reporting work. - Saved report records use the existing
Reportmodel. Do not createSavedReport,ReportModel, orReportEntity. - Never edit old migrations in
db/migrations/legacy. Add a new migration instead.
Now give an agent a task: add a "team activity report" with CSV export. With that note, the agent has a narrow path. It adds a report screen in the web app, a new API endpoint under reports, and a worker job that builds the CSV from audit events. It also adds one new table for report filters.
It does not open the billing package just because invoices already have date ranges and export code. That boundary matters. Agents often grab the first similar code they find, and billing code is full of side effects, tax rules, and payment provider checks. A two line rule saves you from a messy pull request.
The naming rule does more than keep files neat. Without it, an agent may create SavedReport in the API, ReportEntity in the worker, and ReportDto in the web app for the same thing. A reviewer then has to untangle three near copies. If the note says "persisted report data is always Report", the agent reuses the model and adds only the fields it needs.
The migration warning is just as practical. Many teams have an old path that still rebuilds test or staging databases. One quick warning like "do not change anything before 2023_11_billing_split; that chain is fragile" stops the agent from editing history when it only needs a fresh migration for the new report filters table.
That is why these notes work best when they are small and blunt. They do not explain everything. They block the common wrong turns.
Mistakes that lead to bad generated code
Bad generated code usually starts with bad instructions, not a bad model. When notes are vague, bloated, or out of date, the agent fills gaps with guesses.
A common mistake is writing a mini handbook instead of a short guide. Teams try to cover every past decision, every edge case, and every exception. That sounds careful, but it hides the rules the agent needs for day to day work.
Long notes create a second problem: the agent starts mixing patterns from different eras of the codebase. It sees one old rule, one new rule, and one strange exception, then writes code that looks plausible but does not fit anywhere cleanly.
Abstract advice causes just as much trouble. "Keep services separate" or "follow the standard module layout" tells an agent almost nothing. A useful note names real places: which folders hold handlers, where domain logic lives, which module owns billing, and where database access must stop.
Concrete paths matter because agents copy shapes. If the note says orders belong in internal/orders and API handlers stay in api/http, the agent usually follows that pattern. If the note stays high level, it may invent a new folder, add logic to the wrong layer, or wire one service straight into another.
Another mistake is mixing current rules with old exceptions. This happens after migrations, rushed launches, or partial rewrites. The note says one thing, but then slips in a legacy shortcut without warning. Agents often copy the shortcut because it is more specific than the rule.
Stale notes are the last trap. Teams refactor modules, split services, or fix a painful incident, but nobody updates the note. A week later, the agent imports a deleted package or repeats the same risky pattern that caused trouble before.
A short note works best when it stays strict about three things: current folder and module names, live rules only with old exceptions clearly marked as legacy, and recent risk areas that need extra review.
If the note reflects the code that exists today, review gets faster and generated code needs far fewer repairs.
Quick checks before you use the note
A short note only works if someone new can read it fast and act on it. Give it to a developer who does not know the codebase well. If they cannot explain the naming rules, service boundaries, and risky spots in about five minutes, the note is too vague or too long.
That same test works for architecture notes for coding agents. Agents do not fill gaps the way humans do. They guess, and guessing is where code starts to drift.
Use a simple review pass before you rely on the note:
- Check that a new developer can follow it after one quick read.
- Check that every risky area says what not to change, not just where it lives.
- Check that folder names, service names, and examples still match the current repository.
- Check that the note tells the agent when to stop and ask for help.
The risky areas matter more than most teams expect. "Payments" or "auth" is not enough. Write the rule in plain language: do not rename these events, do not change this retry logic, do not edit this migration pattern without review. That gives the agent a hard edge instead of a soft warning.
Examples need the same care. If your note mentions a service folder that no longer exists, the note trains the wrong habit. One stale example can do more damage than no example at all, because the agent will copy the old shape with confidence.
You also want a clear point where guessing stops. Say when the agent should ask for help: unclear ownership, cross service changes, schema edits, billing logic, security rules, or anything that touches production data. This cuts down bad assumptions and makes generated code review much faster.
A plain, current note beats a polished one that drifted away from the repo. Keep it short, keep it specific, and update examples the moment the structure changes.
What to do next
Start small. Pick one repeated task that already causes wasted time, like adding a new API endpoint, building an admin page, or wiring a background job. Write notes for that area first instead of trying to document the whole codebase at once.
A short note works best when it solves a real problem the team saw this week. If agents keep naming files the wrong way, crossing service boundaries, or touching risky modules, write those rules down in plain language. Good notes usually begin with one stubborn pattern, not a grand plan.
Then test the note on a small change. Ask an agent to make a safe update, review the result, and mark the weak spots. If the code still lands in the wrong folder or calls the wrong service, your note is too vague. Fix the note, run the same kind of task again, and compare the output.
The first version can stay simple: name the task the note covers, list the naming rules the agent must follow, define which service or module it can touch, flag files, tables, or flows that need human review, and add one small example from your own codebase.
Where you store the note matters. Put it where developers and agents see it during daily work: next to the code, inside the team docs, or in the same place you keep coding instructions and review rules. If the note is hard to find, people will ignore it.
If you want a second set of eyes on AI coding guidelines or repo rules, Oleg Sotnikov at oleg.is helps startups and small teams as a Fractional CTO and advisor. His work focuses on practical AI coding workflows, product architecture, and lean engineering systems, which is usually exactly where these notes start to pay off.
Frequently Asked Questions
What is an architecture note for a coding agent?
It is a short repo note that tells the agent how your codebase actually works. It should show where code goes, how you name things, which module owns what, and where the agent must slow down.
How long should the note be?
Keep it to one or two pages for one area of the repo. If it takes more than a minute to scan, people skip it and the agent starts guessing.
What should I put in the note first?
Start with the mistakes that keep showing up in generated code. Write the rules that change output right away, like file placement, naming, service ownership, and stop points for risky edits.
Do naming rules really matter that much?
Yes. Agents mix names fast when you leave room for guesswork. A few direct rules like -handler, -service, -job, plus snake_case in SQL and camelCase in app code, remove a lot of noise.
How should I describe service boundaries?
Name the owner of the data and the owner of the decision in plain words. Say things like orders asks billing for invoice status or only billing writes invoice records so the agent does not cross lines just because two folders look similar.
Which parts of the codebase should I flag as risky?
Mark any area where a small edit can cause money errors, access problems, or data issues. Billing, auth, migrations, retries, jobs, and old modules with hidden assumptions usually need a warning.
When should the agent ask for human review?
Tell it to stop when ownership looks unclear or the change touches billing, auth, schema edits, retry logic, or production data. A blunt rule like make the smallest safe change and ask for review works better than a soft warning.
What do I do with legacy code and old exceptions?
Call out legacy paths directly and label them as exceptions. If an old folder still uses odd names or old fields, say that in one sentence so the agent does not copy the pattern into new code.
Should I include an example change in the note?
Yes, one small example does a lot of work. A short task example shows file placement, ownership, and naming in context, which helps more than a long explanation.
Where should I keep the note, and when should I update it?
Put it where developers and agents see it during normal work, usually next to the repo or in the same place as coding rules. Update it right after refactors or after a bad generated change shows you a missing rule.