The three files an Angular monorepo needs before an agent writes a line A developer published a guide for setting up Angular monorepos so coding agents follow architectural boundaries, centered on three files: a single AGENTS.md rules file that tool-specific files like CLAUDE.md and GEMINI.md point to, an ESLint dependency-constraint config using @nx/enforce-module-boundaries or Sheriff that turns those boundaries into a failing command, and the Angular team's published best-practices.md and angular/skills agent skills. The approach keeps AGENTS.md short and mostly negative, covering layout, non-negotiables such as standalone components and signals, and a definition of done that requires lint:arch and tests to pass. This is part 2 of 8 of the free series AI with Angular: agents in your codebase https://tt-tech.io/series/ai-with-angular , first published on tt-tech.io https://tt-tech.io/blog/three-files-before-an-agent-writes-a-line . The first part https://tt-tech.io/blog/same-ai-two-outcomes ended with a team whose agent lands inside the fence on its first try. This part builds the fence. It is three files: one the agent must read, one it must pass, one it must stay inside. An afternoon of work, and the rules that lived in people's heads become something the agent has to obey. Every agent reads a project-level instructions file before it acts, and each tool has its own: CLAUDE.md , GEMINI.md , .github/copilot-instructions.md , .cursor/rules/ . Several of them now also read AGENTS.md . Many teams leave these files empty, paste in the README, or write four copies that drift apart. The agent sees your code, not your reasons. The rules file is where the reasons live. Write one file, AGENTS.md , and make every tool file a single line that points to it. In the demo repo CLAUDE.md is @AGENTS.md plus the block the Nx tooling adds, and GEMINI.md tells the agent to read and follow AGENTS.md before anything else. One source of truth, any agent. A tool's extras, like permissions or hooks, go in that tool's own settings; the rules never move. You do not have to write the Angular part yourself. The Angular team publishes it: a best-practices.md on angular.dev/ai https://angular.dev/ai/develop-with-ai , and agent skills in angular/skills https://github.com/angular/skills . In the demo repo they sit in .agents/skills/ , a folder several agents read, and the Angular and Atlas skills are linked into .claude/skills/ for Claude Code. Your AGENTS.md keeps only what the Angular team cannot know: your boundaries, your legacy, your definition of done. What goes in it is short, concrete and mostly negative . The agent does not need your architecture vision. It needs the fence. Condensed from the demo repo's AGENTS.md : Atlas Bank: rules for coding agents excerpt Layout - libs/domain pure TypeScript, no Angular imports - libs/data-access/ stores and services; may import domain - libs/ui presentational only; never imports data-access - libs/feature/ routed features; may import ui, data-access, domain Non-negotiables - New components are standalone and use signals. No new NgModules. - Never edit libs/legacy/ unless the task file says migrate. Wrap it. - Crossing a library boundary needs an ADR link in the PR. Before you say you are done - npm run lint:arch passes - npm run test passes without changed assertions - The diff is ≤ 300 lines unless the task file raises the limit One word there deserves a line. An ADR is an architecture decision record, a short dated note saying why a boundary exists. Asking the agent to link one is asking it to justify the crossing, and it usually cannot, which is the point. Instructions are suggestions. A failing command is not. The same boundaries become a lint rule, with @nx/enforce-module-boundaries in an Nx workspace or Sheriff in a plain Angular CLI project. From the demo repo's flat config: js // eslint.config.mjs excerpt const depConstraints = { sourceTag: 'type:domain', onlyDependOnLibsWithTags: 'type:domain' }, { sourceTag: 'type:data-access', onlyDependOnLibsWithTags: 'type:data-access', 'type:domain' }, { sourceTag: 'type:ui', onlyDependOnLibsWithTags: 'type:ui', 'type:domain' }, { sourceTag: 'type:feature', onlyDependOnLibsWithTags: 'type:feature', 'type:ui', 'type:data-access', 'type:domain' }, ; // ... '@nx/enforce-module-boundaries': 'error', { depConstraints } , Now the rules file can say "run lint:arch before you finish", and an agent that runs it will usually retry until it passes. "Please respect the architecture" has become a command that fails. A data-access import in a ui component, and the build says no before a reviewer has to. The third file is per task, not per repo: the ask, written down before the agent reads it, with a scope, an out-of-scope and a "done when". It can be a Jira ticket, a GitHub issue with fixed headings, or a Markdown file in docs/tasks/ . The form does not matter. What matters is one sentence: Scope: libs/feature/accounts only. Done when lint:arch and tests pass and the diff is under 300 lines. The size limit is the part that changes the most. Agents are excellent at satisfying explicit constraints and terrible at guessing implicit ones. With 300 in the task, a diff of well over a thousand lines fails the done-when before anyone reads it. Prompt · let the agent find the holes in your rules file Read AGENTS.md . Then open libs/ and list, as a numbered list, every rule you would need to do a feature in libs/feature/accounts that the file does not state: which imports are allowed, which store to use, how tests are written, what "done" means. Do not write code. Do not propose rules; only list what is missing. Run it once per quarter. The list is your rules file's backlog. AGENTS.md , about a page, mostly "never". Point every tool file at it. lint:arch to "done". Exercise: module 1 in the demo repo https://github.com/tt-tech/workshop-ai-with-angular/blob/main/exercises/m1-ai-assisted-workflow.md . Start without the files: git switch track1/m1-start . Then the same task with them: git switch -c m1/you main . Reference: origin/track1/m1-solution . Bring your own agent. Who writes that third file, and how fast, is the next part https://tt-tech.io/blog/from-ticket-to-task-file : the agent drafts it from the ticket, and a person decides. Track 1, part 2 of the free series behind the Fast and safe: AI in your Angular codebase https://tt-tech.io/workshops/ai-with-angular workshop.