A single AGENTS.md is enough for a universal contract, but a real project has many rules needed not always: for one language, one directory, one kind of task. Pile them all into the always-on file and the contract turns into noise, where the conditional sits next to the mandatory and gets in the way of reading either. A contract in which the mandatory drowns in the particular stops being a contract: it is either read carelessly or not read at all.
The naive move is to keep adding a line to the permanent file for every special case: "in Python files do this", "for migrations do that". It looks tidy: everything in one place and always at hand. It seems that this way no rule will be forgotten.
It breaks on the double cost of always-on: expense plus irrelevance. A rule about SQL migrations loaded while you edit CSS is pure noise and wasted tokens; the more conditional rules pile into the permanent file, the longer the model wades through inapplicable text to reach what matters now.
Devin sorts this by activation. Additional rules live in .devin/rules/.md, each with its own trigger in the frontmatter; .devin/global_rules.md stays the single always-on file, and ~/.devin/rules/.md are personal global rules. The supported triggers are always_on (in every session), manual (only on user invocation), model_decision and agent (the agent decides applicability) and glob (activated by a file pattern match). Devin also reads external formats - Cursor rules from .cursor/rules, Windsurf from .windsurf, Claude from .claude - when that is enabled in read_config_from, so migrating everything at once is not required.
Why this way rather than one list. Activation binds a rule to the moment it is relevant. glob loads a rule only when matching files are touched; manual keeps a rule out of context until you call it with an @-mention; model_decision lets the agent pull a rule in when it applies. The .devin path is preferred over the legacy .windsurf, and that same location takes precedence on a match. The point is for a rule to appear in the context exactly when it is relevant and disappear when it is not: activation is a way to pay for a rule only when it actually helps.
What to put where follows directly. Keep always-on only for universal constraints and commands that hold everywhere. Move a long procedure into a skill that loads on demand. Add a one-off nudge to the conversation as a manual rule via @-mention. Devin's documentation advises preferring skills to rules where possible for exactly this reason: a skill enters the context only when relevant, while an always-on rule is there every time.
The key distinction that holds the whole topic together: a rule guides, a permission enforces. The phrase "do not run deploy" in Markdown is useful as a pointer, but it is not a security boundary - the agent is free not to honor it. A real boundary is created by a permission deny, a sandbox, or a hook with a blocking outcome. Rules and permissions are different layers: the first advises, the second leaves no choice. Confusing them is costly both ways: a hard prohibition left in prose does not protect, and a harmless style hint wired into a permission deny later gets in the way and has to be remembered and removed.
A rule is justified where you need a conditional hint, not a prohibition: a glob rule for a specific directory, model_decision for a task type, manual for a rare technique you call by hand. Anything that must be impossible rather than merely undesirable moves to the permission layer, not into the text. The split is simple: the rules layer answers "how things are done here", the permissions layer answers "what is possible here at all", and these two questions should not be mixed in one file.
A rule must be verified with two questions. Did its trigger fire: a glob rule helps only if the pattern actually matched the touched files, and a manual rule does nothing until it is mentioned. And is the "hard" rule backed by enforcement, not only by prose. If a rule is "ignored", the first thing to check is not the wording but the activation: was it loaded in this session at all.
The typical failures are predictable. Everything is dumped into always-on - and the model pays with noise and tokens for rules inapplicable to the current task. A Markdown rule is expected to stop a dangerous action - and it does not. A glob pattern is written so it matches nothing - and the rule silently never applies. The legacy .windsurf is shadowed by .devin while someone edits the wrong file. The common sign: a rule "does not work", though the issue is not the text but whether it activated and whether it is on the right layer. Check the trigger and the layer first - most often the answer is there.