Rules: The Instructions an Agent Always Reads (always / auto / agent / manual)
In short
A rule in the engine isn't a paragraph buried in a shared prompt — it's a separate typed object with a body and an activation mode that answers the question "when exactly should this instruction go into the model's context?" There are exactly four modes: always — permanently in context (the charter, the red lines), auto — attached by file glob patterns (say **/locales/*.json), agent — the model decides for itself based on a trigger description, and manual — silent until you call it explicitly. One set of rules compiles into each target's native mechanism: .claude/rules/ for Claude Code, .mdc with frontmatter for Cursor, a dedicated block inside AGENTS.md. This article covers when to use which mode, plus a worked example of "one rule → three targets."
What it is
A rule is a short instruction for the agent: "always filter SQL queries by organization_id," "don't hardcode strings, add them to both locales," "ask for confirmation before a migration." In the Quest engine a rule isn't a paragraph in a shared prompt — it's a separate typed object with a body and an activation mode. The mode answers one question: when exactly should this instruction be placed in the model's context.
There are exactly four modes (in the schema that's ruleActivationEnum):
always— the rule sits in context permanently, in every request. For the foundations: project charter, red lines, stack.auto— attached automatically when the agent works with files matching glob patterns (for example**/*.tsor**/locales/*.json).agent— the model decides whether the rule is relevant from itsdescription. You write a trigger description like "when adding a payment flow," and the agent pulls the rule in once it recognizes the task.manual— silent until you call it explicitly (in Cursor, via@rule-name).
Why it works this way
Model context is scarce. Put every rule on always and each token is spent on every request, the important parts drown in noise, and a weaker model starts ignoring instructions. The industry consensus is blunt: keep always-rules short, attach everything else conditionally (this is exactly the model Cursor Project Rules use — an honest convergence, not our invention). Granularity buys discipline without bloat: the migrations rule kicks in only when migrations are touched, the a11y rule only on UI.
Which mode when
- An invariant whose violation breaks the product (tenant isolation, a fail-closed billing gate, "no secrets in files") →
always. - A rule tied to a file type (SQL layer, locales, migrations, components) →
autowith precise globs. - A rule for a class of tasks you can't recognize by file extension ("before adding a new dependency, check reuse-first") →
agentwith a clear description. - A rare checklist you need occasionally and on demand →
manual.
Worked example: one rule → three targets
Input. The base Quest engine has a granular tenancy rule (organization isolation) defined like this: activation: 'auto', globs: ['**/*.{ts,py,go,rb,java}'], and a body reading "every query filters by tenant scope, including count/exists; sockets go through auth; SQL is parameterized; found one cross-tenant hole → grep the whole class and fix them all."
What the engine does (the compiler lays it out deterministically per target):
- Cursor → a separate
.cursor/rules/tenancy.mdcfile with the frontmatter thatautomode requires:
---
description: Multi-tenant изоляция
globs: **/*.{ts,py,go,rb,java}
alwaysApply: false
---
Open a server-side .ts and Cursor picks the rule up on its own. (An important research detail baked into the compiler: Cursor silently ignores an .mdc file with no frontmatter, and globs must be a string, not an array — otherwise they won't apply either. The engine guarantees both.)
Claude Code → a
.claude/rules/tenancy.mdfile where the body is wrapped with the path globs.AGENTS.md (the universal target for VS Code/Copilot and the rest) → a rules section in the single file:
alwaysrule bodies go in whole,autorules get the body plus a line "Applies to files:**/*.{ts,py,go,rb,java}", andagent/manualrules are summarized briefly so the always-read file doesn't bloat.
Result. One rule object from the spec turns into each editor's native mechanism. Write the rule once — it works in three environments, with the right activation mode in each.
tenancy.cursor/rules/tenancy.mdc, frontmatter required, globs as a string.claude/rules/tenancy.md, body + path globsAn honest boundary (ENFORCED vs ADVISORY)
A rule is an instruction, not a physical barrier. It advises the model, but on its own it doesn't block a violation with an exit code. Hard blocking (ENFORCED) today exists only in Claude Code, through the PreToolUse hook for dangerous commands (rm -rf, DROP TABLE, git push --force); on Cursor and in plain AGENTS.md, rules act as strict ADVISORY instructions. The portable git/CI safeguard (the Portable Safety Floor) that would make invariants enforced outside Claude too is on the roadmap and not released yet. The engine's whole point is to make these instructions so literal and checkable that even a weak model executes them instead of guessing.
Sources: