AGENTS.md at Scale: A Practical Guide to Nested Instructions
How to organize repository instructions so coding agents respect architectural boundaries, run the right tests, and don’t drown in unnecessary context.
TL;DR
Treat your AGENTS.md hierarchy as an operational architecture, not a collection of prompts.
- Keep the root focused. Define repository-wide invariants, architectural boundaries, and where to find more specific guidance.
- Organize by responsibility. Place nested instructions near the code they govern, without duplicating parent rules.
- Be actionable. Write concrete instructions and decision rules, not lengthy explanations or historical commentary.
- Minimize irrelevant context. Keep detailed procedures in documentation and load them only when needed.
- Make discovery explicit. Agents working across subsystems must consult all relevant instructions. Don’t assume every runtime loads nested files identically.
- Enforce critical rules in code. Instructions guide behavior; tests, permissions, and application logic guarantee correctness.
- Maintain the hierarchy. Remove obsolete guidance and review instructions as the architecture evolves.
The goal isn’t to tell agents everything. It’s to give them the right instructions, in the right place, at the right time.
Giving an AI coding agent a repository-level AGENTS.md is easy. Keeping those instructions useful as your codebase grows is considerably harder.
At first, a single file is enough. It describes your technology stack, coding conventions, and testing commands. Your agent reads it and gets to work.
Then your application grows.
Your backend has architectural constraints that don’t apply to the frontend. Database migrations require special handling. Integration tests need different infrastructure from unit tests. Deployment changes carry risks that ordinary code changes don’t.
You add nested AGENTS.md files to keep everything organized.
And gradually, your instructions become their own maintenance problem.
Files duplicate each other. Rules contradict their parents. Historical explanations accumulate. Agents run expensive test suites when a handful of targeted tests would suffice. Architectural decisions that should be enforced by code become increasingly elaborate paragraphs asking an LLM to behave.
The problem isn’t that you need better prompts. It’s that you’ve started maintaining a distributed system of instructions without treating it like one.
We’ve encountered these challenges while developing OpenOrc, a control plane for governed agentic software development. OpenOrc uses coding agents extensively, with separate Producer and Reviewer roles, persistent task sessions, and independent review throughout the development lifecycle.
This article shares what we’ve learned about organizing and maintaining nested AGENTS.md files in a growing codebase.
Treat your AGENTS.md hierarchy as an operational architecture for coding agents, not as a collection of prompts.
1. Organize instructions around architectural boundaries
The AGENTS.md project describes a convention for placing instructions in different parts of a repository, allowing agents to receive guidance specific to the code they’re working on.
That sounds straightforward. But deciding where instructions belong is more important than deciding what to put in them.
A common mistake is to mirror the directory tree indiscriminately, creating an AGENTS.md wherever there is a folder.
A better approach is to reflect the application’s actual architectural boundaries.
Consider a simplified version of OpenOrc’s repository structure:
openorc/
├── AGENTS.md
├── apps/
│ └── app/
│ └── AGENTS.md
├── src/openorc/
│ ├── AGENTS.md
│ ├── domain/
│ │ └── AGENTS.md
│ ├── services/
│ │ └── AGENTS.md
│ ├── adapters/
│ │ └── AGENTS.md
│ └── persistence/
│ └── AGENTS.md
├── tests/
│ └── AGENTS.md
├── supabase/
│ └── AGENTS.md
└── .github/
└── AGENTS.md
Each file corresponds to a different responsibility.
The root file defines repository-wide invariants. The domain file describes business entities and constraints. Services own application behavior. Adapters describe external integrations. Persistence describes database access and representation.
These distinctions matter because a coding agent can implement a feature that works correctly while placing it in the wrong architectural layer.
Suppose an agent needs to implement a workflow-state transition. Without clear boundaries, it might implement the transition directly in an HTTP endpoint. The code passes its tests, the endpoint works, and the task appears complete.
But the application also executes workflow transitions through background workers. Now the business logic is coupled to HTTP, and the next feature has to work around that decision.
A well-structured instruction hierarchy helps prevent this.
The root AGENTS.md establishes the global architectural rule:
## Architecture
- API routers and background jobs are thin transport layers.
- Application services own workflow behavior.
- Domain code owns business invariants.
- Adapters own external-system mechanics.
- Persistence owns durable representation, not workflow policy.
The nested services/AGENTS.md adds specifics:
## Application services
- Validate authorization and current workflow state
before consequential operations.
- Keep external API calls outside database transactions.
- Reconcile durable state after external operations.
- Return typed application errors rather than
transport-specific responses.
The root establishes the boundary. The nested file describes how to work inside it.
The hierarchy should follow architectural ownership, not simply mirror every directory.
If two directories have identical responsibilities and require identical guidance, they probably don’t need separate instruction files.
2. Keep the root AGENTS.md focused and authoritative
The root file is the entry point to your repository’s operational rules. Its job is not to explain everything.
It should answer three questions:
- What is this repository, and what are its global invariants?
- Which architectural boundaries must never be violated?
- Where should an agent find more specific guidance?
That third question is especially important.
In OpenOrc, the root AGENTS.md contains a context map pointing agents toward the relevant nested files. A simplified example:
## Context map
Read the relevant subsystem guidance before modifying code.
- Domain: src/openorc/domain/AGENTS.md
- Services: src/openorc/services/AGENTS.md
- Adapters: src/openorc/adapters/AGENTS.md
- Persistence: src/openorc/persistence/AGENTS.md
- Testing: tests/AGENTS.md
- Database migrations: supabase/AGENTS.md
For cross-boundary changes, read all applicable guides.
This gives agents a navigation mechanism without forcing every subsystem’s rules into the root file.
It also addresses an important limitation: nested instruction discovery is not necessarily identical across coding-agent runtimes.
Codex’s documented behavior, for example, assembles instructions along a directory path, with more specific files taking precedence. But an agent working in src/openorc/services/ does not necessarily load a sibling file such as tests/AGENTS.md automatically.
That’s significant when a task involves both application services and tests.
Rather than assuming the runtime will discover every relevant file, explicitly tell the agent to consult the instructions for every subsystem it modifies or exercises.
Don’t confuse the existence of an instruction file with proof that the agent has read it.
Detailed migration procedures, historical design discussions, lengthy testing matrices, and issue-specific implementation notes don’t belong in the root. They may all be valuable information. They simply aren’t relevant to every coding task.
If an instruction only matters when modifying one part of the repository, it probably belongs near that part of the repository.
3. Nested files should refine their parents, not repeat them
Instruction duplication is easy to introduce and difficult to notice.
Consider this hierarchy.
Root AGENTS.md:
Application services must not depend on FastAPI.
services/AGENTS.md:
Services must remain independent of FastAPI.
Business logic belongs in services, not HTTP routers.
Service methods should never import FastAPI.
The nested rules mostly restate the root invariant. They add length without adding much information.
Worse, duplication creates synchronization problems. If an architectural boundary changes, developers must find and update every copy. Eventually, one file gets missed.
Now the agent has contradictory instructions, and the team gets to discover which interpretation the model prefers today.
A better structure separates universal and local responsibilities.
Root AGENTS.md:
Application services own business behavior and remain
independent of transport frameworks.
services/AGENTS.md:
Service methods accept domain values and return
domain results or typed application errors.
HTTP status codes and request/response DTOs belong
to the API layer.
RQ-specific job state belongs to the worker layer.
The nested instructions now explain how to preserve the global constraint.
This leads to a useful maintenance test:
Would removing this instruction from the nested file cause the agent to lose information that isn’t available in its parent?
If the answer is no, consider removing it.
Some repetition is justified for critical rules, particularly security boundaries or high-risk operational restrictions. But repetition should be deliberate, not the default.
4. Write instructions that change behavior, not commentary
This is perhaps the most important practical lesson we’ve learned.
As a project evolves, AGENTS.md files tend to accumulate explanations. Explanations can help agents understand architectural intent, but an instruction file should primarily contain information that changes what an agent does.
Consider this example.
Weak instruction:
Database persistence testing is important to ensure
the long-term reliability of the application.
Developers should carefully consider the appropriate
testing strategy before submitting changes.
Nothing is necessarily wrong with it.
But what should the agent actually do? Which tests should it run? Before or after opening a pull request? What if they require live infrastructure?
The paragraph provides almost no operational guidance.
Better instruction:
When changing persistence behavior:
1. Identify the integration tests covering the changed
behavior and affected cross-boundary contracts.
2. Select the smallest meaningful test set.
3. Run those tests before PR review when the execution
environment permits it.
4. If execution requires Owner-controlled infrastructure,
provide the exact targeted command and report that
validation remains outstanding.
5. Report which tests ran and their results.
Do not run the complete integration suite by default
when targeted coverage is sufficient.
This tells the agent what to do, how to choose, and what evidence to provide.
Notice that it doesn’t prescribe a fixed list of test modules. The agent is expected to understand the change and select appropriate validation.
Good instructions establish decision rules rather than eliminating judgment.
Case study: Testing economics in OpenOrc
During OpenOrc’s backend development, our test suite grew beyond 1,000 tests. Our real-Postgres integration suite eventually took more than 25 minutes to execute in full.
The tests themselves weren’t necessarily excessive. Many validated important security, isolation, persistence, and workflow invariants.
The problem was how they were being executed.
Running the entire database integration suite after every persistence-related change creates an expensive feedback loop.
A narrow service change may need one integration module and a handful of adjacent contract tests. A schema migration affecting several relationships may require broader coverage.
Those are different situations, and the testing instructions should recognize that.
OpenOrc’s testing documentation separates ordinary deterministic tests from explicit real-infrastructure integration testing. The latter runs against ephemeral Supabase database branches through a development-server command.
For example:
./scripts/devserver.sh --testdb -- \
.venv/bin/python -m pytest \
-o addopts=--strict-markers \
-m integration \
tests/integration/test_task_agent_session_persistence.py
The current repository policy reserves execution of that infrastructure-backed command for the human Owner. That matters: selecting the correct tests and having permission to execute them are different responsibilities.
An agent can identify the relevant tests and prepare the exact command even when it cannot access the required infrastructure.
The goal isn’t to run fewer tests at any cost. It’s to run tests that provide useful evidence for the change, at the appropriate stage.
Full-suite execution remains valuable for CI, release validation, and broad architectural changes. But indiscriminate full-suite execution isn’t inherently more rigorous.
Sometimes it’s just slower.
5. Optimize for relevant context, not minimum file size
It’s tempting to turn instruction length into a numerical rule: keep every AGENTS.md below 100 lines, never exceed 2,000 tokens, limit the root file to one page.
These rules are easy to measure. Unfortunately, they don’t tell us much about whether the instructions are useful.
A complex persistence subsystem may legitimately require detailed guidance on transaction handling, authorization boundaries, database constraints, and migration safety.
A simple frontend component directory may need almost none.
The right question isn’t how short can we make this file?
It’s how much of this information is relevant to the tasks that will encounter it?
Lengthy standing instructions consume context, increase the chance of contradictions, and make it harder to distinguish critical rules from incidental detail.
Separate rules from reference material
A useful pattern is to keep operational guidance in AGENTS.md while moving procedures into documentation.
tests/AGENTS.md:
## Test policy
- Prefer deterministic tests without live infrastructure.
- Add regression coverage for bug fixes.
- Test new behavior at the layer that owns it.
- Avoid duplicating coverage already established
by adjacent layers.
See tests/README.md for commands, fixtures,
markers, and environment setup.
tests/README.md:
# Testing Guide
## Unit tests
...
## Integration tests
...
## Database setup
...
## Troubleshooting
...
AGENTS.md provides the standing behavioral contract. The README provides reference material for when it is needed.
For rarely used, multi-step workflows, task-specific skills or dedicated runbooks can provide another layer of detail.
This reduces the amount of material an agent needs to carry throughout a task and makes maintenance more predictable.
Some runtimes impose size budgets on discovered instructions, another reason to avoid putting specialized procedures in the root.
More importantly, each runtime has its own discovery behavior and instruction-loading lifecycle.
Before relying on a hierarchy, verify that your agent actually receives the relevant files. The AGENTS.md project documents the convention; individual runtimes such as Codex and Cline document their own behavior.
Portability of the Markdown format doesn’t guarantee identical loading behavior.
6. Instructions are not enforcement mechanisms
This distinction becomes increasingly important as coding agents gain autonomy.
An AGENTS.md can instruct an agent not to bypass authorization. It cannot actually prevent an authorization bypass.
It can tell an agent not to introduce circular dependencies, but it cannot enforce that architectural rule. It can prescribe testing practices, but it cannot prove tests were executed.
An instruction file influences behavior. It does not establish authority.
In OpenOrc, we distinguish between agent instructions, application contracts, authorization boundaries, and mechanical enforcement.
Consider a critical database constraint.
An AGENTS.md might say:
Every Task belongs to exactly one Workspace.
Cross-Workspace references must never be permitted.
That’s useful guidance.
But if Workspace isolation is a security requirement, the application must also enforce it through authorization checks and appropriate database constraints.
The instruction helps the agent implement the system correctly. Enforcement protects the system when the agent doesn’t.
The same applies to code review.
A repository instruction might require agents to review committed code rather than uncommitted working-tree state. But if exact commit identity matters, the review system itself should record and verify which commit was reviewed.
Otherwise, you’re relying on a language model to preserve an invariant that belongs in deterministic software.
Use AGENTS.md to tell agents how to work within your architecture. Use code, tests, permissions, and CI to enforce the architecture.
This also clarifies the role of the agent: make engineering decisions within well-defined boundaries, not act as the sole guardian of those boundaries.
7. Make cross-boundary tasks explicit
Nested instructions work well when a task stays within one subsystem. Real engineering tasks rarely cooperate with such neat boundaries.
Consider adding a new API operation. The change might involve:
src/openorc/domain/
src/openorc/services/
src/openorc/api/
src/openorc/persistence/
tests/
Each directory has its own responsibilities. The task spans all of them.
An agent starting in the API directory might receive the root instructions and API-specific guidance. That doesn’t guarantee it has consulted the service, domain, persistence, and testing instructions.
The solution isn’t to copy every subsystem’s rules into the root. It’s to make cross-boundary discovery explicit.
## Cross-boundary changes
Before implementation, identify the architectural
subsystems affected by the task.
Read the relevant AGENTS.md files for those subsystems.
When adding tests, consult both the testing guidance
and the instructions for the subsystem under test.
Do not assume instructions from sibling directories
have been loaded automatically.
That’s a small instruction with substantial value.
There’s another subtle point: precedence shouldn’t become permission to weaken architectural invariants.
Suppose the root file says:
Never store raw credentials in ordinary database tables.
A nested persistence file shouldn’t casually redefine that policy merely because it is more specific.
Local rules should operate within global constraints. If an exception is genuinely required, document it deliberately and enforce it at the appropriate application boundary.
8. Maintain AGENTS.md as living code
The most dangerous instruction isn’t necessarily a poorly written one. It may be a perfectly clear instruction that was correct six months ago.
As repositories evolve, conventions change. A testing command is replaced. A service is split into smaller components. An adapter gains a supported API that makes an old workaround unnecessary.
If the instruction hierarchy doesn’t evolve alongside those changes, agents will faithfully follow obsolete guidance.
Case study: Instruction decay
During OpenOrc’s development, we noticed that some nested instruction files were becoming increasingly descriptive.
They had started as concise architectural guidance but gradually accumulated historical implementation details, explanations of past decisions, and references to individual issues.
Much of that information was accurate. That wasn’t the problem.
The problem was that it no longer belonged in standing agent instructions.
A paragraph describing why an integration architecture was selected might be useful in design documentation. But once the decision is implemented, the agent often needs only the resulting constraint:
Use the supported public SDK.
Do not depend on private runtime files or
undocumented wire protocols.
Historical reasoning can remain in design documents or Git history. Standing instructions should describe the current rule.
A cleanup pass over OpenOrc’s instruction hierarchy reinforced that distinction.
An instruction should not remain in AGENTS.md merely because it is true.
It should remain because it is relevant to how an agent should work today.
Review instructions when architectural ownership, development tooling, testing infrastructure, runtime integrations, or CI policy change.
Repeated agent behavior is another signal. If agents misunderstand where a responsibility belongs, guidance may be missing or ambiguous. If they repeatedly perform unnecessary work, instructions may be too prescriptive.
If agents ignore a paragraph, investigate whether it’s discoverable, actionable, and relevant before making it longer.
The objective isn’t to accumulate enough instructions to eliminate every mistake. It’s to improve guidance that demonstrably affects engineering outcomes.
9. A practical maintenance checklist
When reviewing a hierarchy, ask:
| Question | What to look for |
|---|---|
| Is this instruction in the right file? | Global invariants at the root; local rules near their subsystem. |
| Does it change agent behavior? | Concrete actions, constraints, or decision criteria rather than commentary. |
| Is it duplicated elsewhere? | Multiple copies of the same rule that may diverge. |
| Is it still current? | Obsolete commands, superseded architecture, historical workarounds. |
| Is it discoverable? | Whether the runtime loads it and cross-boundary tasks consult it. |
| Does it belong in documentation? | Long explanations, troubleshooting, historical context. |
| Should something enforce it? | Security and correctness guarantees needing deterministic mechanisms. |
| Does it require unnecessary work? | Blanket test execution, repeated validation, overly broad discovery. |
For a new repository, don’t create a large hierarchy preemptively.
Start with a focused root AGENTS.md. Add nested files when a subsystem has meaningful rules that differ from global conventions.
For an established repository, the process is almost the reverse: identify duplicated guidance, move instructions toward their proper owners, and remove historical material.
There is no ideal number of files. A five-directory application might need only one. A large monorepo may legitimately require dozens.
The right hierarchy is the smallest one that expresses the actual operational boundaries of the codebase.
10. How to tell whether your instructions are working
Instruction quality is difficult to evaluate by inspection alone.
A beautifully organized hierarchy can still fail if the agent never reads the relevant files.
Rather than measuring success by file count or token count, evaluate engineering behavior.
Does the agent put new functionality in the correct architectural layer? Recognize security boundaries? Select relevant tests without routinely running unnecessary suites? Know when to consult sibling instructions? Report what it actually validated?
These are better indicators than lines of Markdown.
A practical technique is to use representative tasks as informal instruction checks.
Take a small service change, a database migration, and a cross-boundary feature. Ask the agent to explain which instructions apply and how it intends to validate the work.
If it can’t identify the boundaries before implementation, adding more prose to an unrelated file probably won’t help. Fix discovery or clarify responsibility.
If it understands the constraints but violates them during implementation, determine whether the issue is ambiguous guidance, inadequate validation, or missing mechanical enforcement.
Those are different problems requiring different solutions.
The goal isn’t to prove that the agent has read every instruction. It’s to make correct engineering behavior more likely and incorrect behavior easier to detect.
Conclusion: Good instructions define boundaries, not everything
AGENTS.md is a deceptively simple idea: a Markdown file tells coding agents how to work in your repository.
For small projects, that may be all you need.
For larger projects, nested instruction files become part of the engineering environment. They influence how agents discover context, navigate architectural boundaries, select validation, and interact with the repository.
That makes their design and maintenance worth taking seriously.
Keep repository-wide invariants at the root. Put subsystem-specific guidance near the code it governs. Avoid duplication. Prefer operational instructions over commentary. Optimize for relevant context. Separate guidance from enforcement. Maintain the hierarchy as the repository evolves.
Most importantly, remember what these files are for.
An effective AGENTS.md hierarchy doesn’t tell agents everything about your codebase. It tells them what matters, where it matters, and how to work safely within those boundaries.
That’s a more scalable approach than trying to write the perfect prompt.
And as coding agents become capable of handling increasingly substantial engineering tasks, the quality of those boundaries will matter far more than the length of the instructions describing them.
OpenOrc is a control plane for governed agentic software development. Explore the project and its repository instructions at github.com/openorc/core.