Skip to content

Agent Rules

Rules files give AI coding agents project-specific context that persists across sessions. They live in version control and load on every interaction. This persistence is useful but creates overhead.

Instruction Paradox

More rules do not mean better compliance. Each instruction consumes tokens from the same finite context window that holds your code, conversation history, and tool results. A 2000-token rules file leaves 2000 fewer tokens for actual work.

Overly detailed rules files create a compliance death spiral:

  1. Complex rules consume context, leaving less space for reasoning
  2. The agent's output suffers
  3. Developer adds more rules to fix it, which consumes more context
  4. Repeat

Set an Instruction Budget

Frontier models can follow roughly 150-200 instructions before compliance drops off. Smaller models handle fewer. Every instruction in your rules file competes for this limited attention.

A bloated rules file wastes tokens and degrades the agent's ability to follow rules that matter. Ten focused rules beat fifty thorough ones.

Effective rules files are short. They give the agent what it needs to know without crowding out the actual work.

AGENTS.md Standard

AGENTS.md is an open format under the Agentic AI Foundation (Linux Foundation) for providing project-specific context to AI coding agents. It functions as a "README for agents" - persistent, version-controlled instructions that travel with the codebase.

The format is intentionally simple: markdown files with no required structure. Most runtimes read a variation of this pattern:

Runtime Primary File Notes
AGENTS.md standard AGENTS.md Cross-runtime, recommended
Claude Code CLAUDE.md Can symlink to AGENTS.md
Cursor .cursorrules Legacy; migrating to AGENTS.md
Windsurf .windsurfrules Also reads AGENTS.md
Opencode AGENTS.md Native support
Aider CONVENTIONS.md Configurable via settings

For maximum compatibility, create an AGENTS.md file and symlink runtime-specific names to it.

Nested files are supported for monorepos. A rules file in packages/api/AGENTS.md provides context specific to that package, loaded only when working in that directory.

Choosing the Right Tool

Before adding something to your rules file, ask: is advisory text the right mechanism?

If you want... Use Not rules because...
Agent to know project vocabulary Rules Context only the codebase can provide
Agent to find relevant code Rules Navigation hints can't be automated
Agent to follow a multi-step workflow Skill Workflows need progressive disclosure, not always-loaded text
Agent to always run tests after edits Hook Mechanical enforcement beats advisory text
Agent to never use certain patterns Hook If it must be blocked, block it deterministically
Consistent code style Linter/Formatter Tools like Biome, Ruff enforce without tokens

Rules files are for context the model cannot infer from your codebase or tooling. If you can enforce the behavior with a linter or hook, do that instead.

What to Include

Put things here that have nowhere else to go:

Category Example Why rules
Navigation "Auth logic lives in src/auth/" Can't be automated; saves exploration time
Vocabulary "A 'tenant' is an organization account" Project-specific jargon the model won't know
Temporal context "Migration from REST to GraphQL in progress" Explains inconsistent patterns in the codebase
Command syntax pytest path/to/file.py How to invoke tools (not when - that's hooks)
Non-obvious constraints "Never query prod DB directly - use the replica" Critical context that can't be lint-enforced

Delete any line whose removal would not break anything a linter or hook could catch.

What to Avoid

Rules files become bloated when they duplicate existing information or try to teach the model things it already knows.

Skip these:

  • Obvious conventions (the model knows standard language idioms)
  • Anything in your README or docstrings
  • Generic platitudes like "Write clean code"
  • Persona prompts ("You are a senior engineer...") - these waste tokens
  • Defensive reminders the model already knows
  • Prefer bullets over prose

Warning signs your rules file needs pruning:

  • Over 1500 tokens
  • Sections the model ignores (if it ignores them, they're not helping)
  • "Just in case" rules
  • Prompt engineering essays copied from elsewhere

File Organization

Root-level file for project-wide context:

project/
├── AGENTS.md          # Project-wide rules
├── CLAUDE.md → AGENTS.md  # Symlink for Claude Code
├── src/
└── packages/

Nested files for monorepo packages:

project/
├── AGENTS.md              # Shared context
├── packages/
│   ├── api/
│   │   └── AGENTS.md      # API-specific rules
│   └── web/
│       └── AGENTS.md      # Frontend-specific rules

Lazy loading for large documentation. Instead of embedding a style guide, reference it:

When modifying C# files, read `docs/csharp-conventions.md` for style guidance.

The agent loads the file only when relevant. This saves context for other work.

Effective Patterns

Command syntax reference - document the invocation, let hooks handle timing:

## Commands
- Test single file: `pytest path/to/test_file.py`
- Type-check module: `tsc --noEmit -p packages/api`
- Run migrations: `alembic upgrade head`

Note: If you want tests to run automatically after edits, that's a hook, not a rule.

Navigation pointers - where things live:

## Architecture
- Auth: `src/auth/` - JWT validation, session management
- API handlers: `src/api/routes/` - one file per resource
- Database models: `src/models/` - SQLAlchemy definitions

File paths go stale

Navigation pointers rot quickly. If your rules file says "auth logic in src/auth/handlers.ts" and the file gets renamed, the agent confidently looks in the wrong place. Prefer directory-level pointers over specific files, and describe capabilities rather than structure when possible. Domain concepts like "tenant" and "widget" are more stable than paths.

Vocabulary definitions - project-specific terms:

## Domain Terms
- **Tenant**: An organization account (multi-tenant SaaS)
- **Widget**: Customer-facing configurable component
- **Hydration**: Server-side data loading before render

Temporal context - explain inconsistencies:

## Current State
- Migration from REST to GraphQL in progress - new endpoints use GraphQL
- Legacy auth in `src/auth/legacy/` - do not extend, will be removed Q2

Add rules after failures. When the agent screws up and no linter or hook could have caught it, add a rule. For everything else, add a linter or hook.

Anti-Patterns

Does your rules file include step-by-step workflows? ("When adding a component, first create the directory, then add index.ts...") That belongs in a skill, where it loads only when relevant.

"DON'T mock the database" - if you're writing this, you've already lost. Advisory text gets ignored when inconvenient. Use a hook to grep for mock patterns and block the commit.

Style rules like "use single quotes" waste tokens. Your linter already handles this. Set up Biome or Ruff and delete the rule.

Persona instructions ("You are a world-class architect...") do nothing measurable except burn tokens. Cut them.

Watch for kitchen-sink syndrome: coding standards, architecture decisions, team preferences - all crammed into one file. If a human couldn't memorize it, an agent won't follow it either.

Don't add rules for hypothetical situations. Wait until the agent makes the same mistake twice. Then ask: is this a rule problem, or should I add a hook/skill/lint rule instead?

Never scaffold your rules file with a generator or template. Those tools prioritize breadth over focus. You end up with 50 "best practices" that crowd out the three things that matter for your project. Write it by hand. Keep it short.

  • Agent Skills - For workflows and multi-step processes that need progressive disclosure
  • Hooks - For constraints that must be enforced mechanically

Different problems need different tools. A rules file tells an agent what "tenant" means. To stop the agent from writing to production, use hooks.

External Resources