Skip to content

Instructions and agents

These two primitives pair naturally. An instruction is a scope-attached rule: a coding standard, naming convention, or review checklist that fires when the agent touches files matching a glob. An agent is a persona scoping module: a named specialist (security reviewer, migration assistant, on-call SRE) the user invokes explicitly. Instructions shape how the model behaves on any given file. Agents shape who the model becomes when summoned.

Reach across harnesses differs and matters when you choose. See Primitives and targets for the full matrix; the gist is below.

A unit of policy that travels with a glob. Authors write one rule; APM compiles it to whatever frontmatter and directory the harness expects.

my-package/
apm.yml
.apm/
instructions/
python-style.instructions.md
pr-review-checklist.instructions.md

File names end in .instructions.md. The basename (minus the double extension) becomes the deployed filename stem.

---
description: Python style rules enforced on src/ and tests/
applyTo: "**/*.py"
---
- Use `pathlib.Path`, never `os.path`.
- Tests live next to the module under `tests/<module>/`.
- ...
KeyRequiredPurpose
descriptionyesOne-line summary; used in compiled context indexes
applyToyes for instructionsGlob (or comma-separated globs) the rule binds to

applyTo is the load-bearing field. Without it the rule is treated as unconditional and gets folded into compiled context files (AGENTS.md, GEMINI.md) instead of a per-file rule directory. With it, each harness wraps the body in its own scoping syntax.

applyTo accepts either a single glob or a comma-separated list of globs. Commas inside brace alternation (**/*.{css,scss}) are part of the glob and are NOT treated as list separators — only top-level commas split the list.

---
description: Frontend style rules
applyTo: "**/*.{css,scss},**/*.tsx"
---

On Copilot the comma-list is preserved verbatim (Copilot splits it natively). On Claude, Cursor, and Windsurf the list is expanded to a YAML array under paths: / globs:.

  • Lead with bullets, not prose. Instructions are read by an agent mid-task.
  • One topic per file. Split python-style and python-testing; do not co-mingle.
  • Cite paths inside the repo with backticks; do not assume any other context is loaded.
  • Skip greetings and meta (“In this file we will…”). State the rule.
TargetOutput pathTransform
copilot.github/instructions/<name>.instructions.mdverbatim; applyTo preserved (comma-lists split natively by Copilot)
claude.claude/rules/<name>.mdapplyTo -> paths: list (comma-lists expanded to YAML array)
cursor.cursor/rules/<name>.mdcapplyTo -> globs: (scalar for single glob, YAML array for comma-lists); description auto-derived if missing
windsurf.windsurf/rules/<name>.mdapplyTo -> trigger: glob + globs: (scalar or YAML array); missing applyTo -> trigger: always_on
codexfolded into AGENTS.mdcompile-only, no per-file deploy
geminifolded into GEMINI.mdcompile-only, no per-file deploy
opencodefolded into AGENTS.mdcompile-only, no per-file deploy

Source: src/apm_cli/integration/instruction_integrator.py, src/apm_cli/integration/targets.py.

A specialist persona invoked by name, with optional model and tool constraints. Think of it as a callable role — the user types @security-review and the harness loads the body as system context.

my-package/
apm.yml
.apm/
agents/
security-review.agent.md
migration-assistant.agent.md

File names end in .agent.md. APM also accepts .chatmode.md and the legacy .apm/chatmodes/ directory for backward compatibility; new work should use .agent.md under .apm/agents/.

---
name: security-review
description: Reviews diffs for OWASP top-10 issues and missing input validation.
model: gpt-5
tools:
Read: true
Grep: true
---
You are a security reviewer. Your job is to inspect the working diff
for...
KeyRequiredPurpose
namerecommendedDisplay name; defaults to filename stem
descriptionyesUsed by Cascade and Copilot to decide when to surface the agent
modeloptionalPinned model the harness should switch to when invoked
toolsoptionalWhitelist of tools the persona may call
coloroptionalDisplay color for harnesses that render it (Copilot, Claude, OpenCode). OpenCode requires a #rgb/#rrggbb hex literal or one of its theme names; see “Common pitfalls” below

model and tools reach Copilot, Claude, Cursor, and OpenCode verbatim. Codex receives a TOML translation. Windsurf and Gemini do not receive .agent.md files at all — Cascade auto-invokes any SKILL.md by its description, and Gemini CLI has no agents primitive.

OpenCode is the strictest of the verbatim targets: it requires tools as a tool-name: boolean mapping (not a list, not a string) and color to be either a #rrggbb hex literal or one of its theme names (primary, secondary, accent, success, warning, error, info). apm install -t opencode warns at install time when an agent ships shapes OpenCode would reject at load time — the file is still deployed, but the warning names the offending package and field so you can fix the source.

  • Open with role and scope in two sentences. The harness uses this as the system prompt.
  • Define what the persona will and will not do. Boundaries make agents useful.
  • List the artifacts it expects (“the open PR diff”, “the failing test name”) and what it returns (“a markdown review with file:line citations”).
  • Keep the body under 300 lines. Long agents drown the harness’s context window before the user’s task even loads.
TargetOutput pathTransform
copilot.github/agents/<name>.agent.mdverbatim
claude.claude/agents/<name>.mdverbatim
cursor.cursor/agents/<name>.mdverbatim
opencode.opencode/agents/<name>.mdverbatim
codex.codex/agents/<name>.tomlYAML frontmatter -> TOML; body becomes developer_instructions
windsurfnot deployedWindsurf has no agents primitive — author personas as skills (Cascade auto-invokes by description)
gemininot deployedGemini CLI has no agents primitive

Source: src/apm_cli/integration/agent_integrator.py, src/apm_cli/integration/targets.py.

Pick instructions when:

  • The rule applies to a file pattern, not a workflow.
  • You want the agent to follow it implicitly, without being summoned.
  • The content is short, declarative, and reviewable as policy.

Pick agents when:

  • A user needs to invoke a specialist on demand.
  • The behaviour involves a sequence of steps, decisions, or model switches, not a static rule.
  • You want to scope tool access (e.g. read-only review persona).

Many packages ship both: instructions for the always-on guardrails, plus one or two agents for the deeper workflows that warrant a dedicated persona.

  • Missing applyTo. An instruction without applyTo stops being scope-attached and gets folded into the compiled context file. If you wanted Cursor or Copilot to scope it to **/*.ts, the rule will not bind.
  • Agent named default or start. These collide with script resolution in apm run. Pick a descriptive name.
  • Targeting an agent at Windsurf or Gemini. Neither harness has an agents primitive. Cascade auto-invokes skills by description and Gemini folds context into GEMINI.md. If a persona must reach those targets, author it as a skill under .apm/skills/<name>/SKILL.md.
  • tools: as a list, or a named color, on an OpenCode-targeted agent. OpenCode’s loader rejects tools: [Read, Grep] and colors like cyan. Use the mapping form (tools: {Read: true}) and either a #rrggbb hex literal or one of OpenCode’s theme names (primary, secondary, accent, success, warning, error, info). apm install -t opencode will warn at install time when it detects either shape; the file still deploys but OpenCode will refuse to load it.
  • Agent body that re-states global instructions. Agents inherit the workspace’s compiled context. Restate only what the persona needs to override or add; do not duplicate python-style inside code-reviewer.agent.md.
  • Co-mingling rules and persona. A 600-line .agent.md that contains style rules, review checklist, and persona prompt is two primitives in a trench coat. Split it.
Terminal window
apm compile --validate # frontmatter + structure check, no writes
apm install --dry-run --target cursor # preview agent deployment
apm preview <script> # if the agent is wired to a script

For the full primitive catalogue and target matrix, see Primitives and targets. For prompts and slash-commands, see Prompts. For packing and publishing, see Pack a bundle.