Skip to content

Layer Agent Instructions by Specificity Across Scopes

Structure agent instructions in concentric layers — global defaults, project-level files, and directory overrides — so the most specific instruction always wins.

Also known as

Layered Instruction Scopes · Directory-Level Instruction Hierarchy · Hierarchical CLAUDE.md

For the Claude Code–specific implementation of this pattern, see Hierarchical CLAUDE.md.

Why Flat Instruction Files Break at Scale

A single instruction file at the repository root works for small, uniform codebases. As projects grow — multiple services, distinct frontend and backend conventions, mixed toolchains — a single file either becomes an unmanageable list of conditional rules that hits the instruction compliance ceiling or fails to cover the cases that matter.

Layering by scope solves this. The agent receives instructions appropriate to where it is working, without requiring any manual switching.

The Codex Harness Model

OpenAI's Codex harness implements a three-scope hierarchy:

  1. Global config ($CODEX_HOME): defaults and preferences that apply across all repositories
  2. Git root: the project-wide AGENTS.md at the repository root
  3. Working directory: AGENTS.md files in subdirectories, from git root down to the current directory

The harness traverses from global to working directory, concatenating AGENTS.md files in order of increasing specificity. More specific instructions appear later in the prompt and take priority over earlier, more general ones.

graph TD
    A[Global config] --> D[Assembled prompt]
    B[Git root AGENTS.md] --> D
    C[./api/AGENTS.md] --> D
    C2[./api/auth/AGENTS.md] --> D
    D --> E[Agent receives context]

Priority Rules

Later instructions take priority over earlier ones when they conflict. A directory-level file that specifies "use Bun, not npm" overrides a project-root file that specifies "use npm" for that directory and its children.

Priority is implicit in the concatenation order, not declared with explicit keywords: global config provides defaults, project root narrows them, subdirectory files override for their scope.

Why It Works

LLMs exhibit recency bias: instructions appearing later in a prompt carry higher effective weight when they conflict with earlier ones. By concatenating from general to specific, the harness exploits this property to produce scoped behavior without requiring the model to evaluate conditionals.

A flat file saying "if in api/, use uv; otherwise use pip" requires the model to evaluate that condition correctly every time. A concatenated prompt replaces it with a later, unconditional "use uv" — the latter wins without conditional reasoning.

AGENTS.override.md: Per-Directory Alternative to AGENTS.md

Codex's harness supports AGENTS.override.md: when both files exist in the same directory, the harness selects AGENTS.override.md and ignores AGENTS.md for that directory. Parent directory files are still concatenated normally — the override only affects which file is chosen within its own directory.

Use override files when the directory has conventions that diverge enough to warrant a separate file. Override files do not suppress parent directory instructions — those are still included in the assembled prompt.

Context Budget Limits

Codex applies a 32 KiB default cap on assembled instruction content. Without a cap, deeply nested directories can consume the entire context budget before task work begins.

If your harness does not enforce a size limit, apply the same discipline manually:

  • Keep each instruction file to 50–100 lines
  • Prefer pointers to documentation over embedded content
  • Audit the total assembled size for deeply nested directories

Applying This Pattern Without Codex

Any agent harness that reads instruction files from the filesystem can implement this pattern:

  1. Collect all AGENTS.md files from global config through the git root to the current working directory
  2. Concatenate them in order of increasing specificity
  3. Enforce a total size cap
  4. Check for override files and prefer AGENTS.override.md over AGENTS.md within the same directory when both exist — parent directory files are still concatenated regardless

The AGENTS.md standard describes the directory traversal convention. Tools that implement AGENTS.md support — including GitHub Copilot and Cursor — load these files automatically when working within a repository.

When This Backfires

Layering works when scopes are independent. It degrades in several conditions:

  • Conflicting rules without clear resolution: If a global file says "always use TypeScript" and a directory file says "use JavaScript", the directory file wins by position — but only if the agent respects concatenation order. Agents that weight by relevance rather than position may resolve the conflict unpredictably.
  • Instruction bloat in deep hierarchies: A file six directories deep inherits instructions from every ancestor. A few verbose ancestor files saturate the 32 KiB Codex default before task-specific content reaches the model.
  • Inconsistent tool support: Not all tools implement the full traversal spec. Some load only the root AGENTS.md; others support nesting but not AGENTS.override.md. Instructions written assuming full traversal may be silently ignored.

Example

A monorepo with a frontend and an API service uses three AGENTS.md files:

~/.codex/AGENTS.md          # global: preferred languages, editor settings
my-repo/AGENTS.md           # project: test command, commit style, PR conventions
my-repo/api/AGENTS.md       # directory: use uv not pip, never run migrations in tests

When an agent works in my-repo/api/, the harness assembles the prompt in this order:

  1. ~/.codex/AGENTS.md — global defaults
  2. my-repo/AGENTS.md — project conventions
  3. my-repo/api/AGENTS.md — directory overrides

The instruction "use uv not pip" from api/AGENTS.md appears last and takes priority over any package-manager guidance in the project root file. The my-repo/frontend/ directory receives only the first two files — its working directory has no AGENTS.md of its own.

Key Takeaways

  • Concatenate instruction files from general to specific — global config, then git root, then each directory down to the working directory — so the most specific rule appears last and wins.
  • Priority is positional, not keyword-declared: later instructions override earlier ones because LLMs weight recent prompt content more heavily.
  • AGENTS.override.md replaces AGENTS.md within a single directory while parent files still concatenate normally.
  • Cap the assembled size (Codex defaults to 32 KiB) or enforce the discipline manually, since deep hierarchies can exhaust the context budget before task work begins.
Feedback