docs/playbooks/<role>.md. Playbooks are role and domain instruction docs that the agent reads on demand. They have no frontmatter, no slash command, and no installation step — AGENTS.md routes an incoming request to the right playbook, the agent reads it with the Read tool, then acts. This page documents the playbook shape and the lint that keeps the routing surface honest.
Full example
A working playbook header (excerpted fromhttps://github.com/alecs5am/ralphy/blob/main/docs/playbooks/scenarist.md):
Required sections
| Section | Purpose |
|---|---|
**Read this when:** | One sentence per trigger phrase. Mirrors the AGENTS.md routing-table row. The agent uses this to confirm the match before diving in. |
## Sub-docs | Two-column table (Sub-doc | When to read it). The agent reads sub-docs on demand for specific sub-tasks. Optional only when the playbook has no sub-docs. |
## Output contract or ## Output | What this role produces. For scenarist it’s the Scenario schema; for art-director the Generation log entries; for editor the rendered mp4. |
## Hard invariants | Must-do / must-not lines, one bullet each. Concrete and refusable. These mirror the AGENTS.md invariants but tailored to the role. |
## CLI cookbook | Two-column table of common goals and the exact ralphy <verb> to run. The agent uses this to avoid improvising raw API calls. |
Read this when: block, then reads the rest in order. Skipping any section is a defect.
No frontmatter
Unlike skills (which need YAML frontmatter for the slash-command menu), playbooks are plain Markdown. The router lives inAGENTS.md; the playbook itself only needs to be readable.
This is intentional. Adding frontmatter would create two routing surfaces (AGENTS.md and per-playbook). Decision D-06 (scripts/lint-agents-md.ts) keeps the routing single-sourced.
Sub-docs convention
A playbook routes to sub-docs atdocs/playbooks/<role>/<sub>.md:
When to read it column. The agent only reads sub-docs when the sub-task matches — keeps the context lean.
Sub-docs themselves are plain Markdown with no fixed structure. They are leaves; they do not route further.
Routing into AGENTS.md
Every playbook gets exactly one row in theAGENTS.md routing table:
User intent column is a comma-separated list of trigger phrases (EN; RU is in the body). The Playbook column is a Markdown link to the file. The agents-md lint (scripts/lint-agents-md.ts) walks every row and verifies the target file exists on disk.
Chaining
A request that spans roles is a chain of playbooks in role order. Example: “make a video in the style of<url> for <brand>” chains researcher → scenarist → art-director → editor. The producer playbook is the end-to-end wrapper.
The router does not encode chains explicitly — the agent walks the table row by row and picks every matching row, then orders by role.
Lint
scripts/lint-agents-md.ts enforces four invariants:
- Every routing-table row points at an existing file. Targets matching
docs/playbooks/<name>.mdor.agents/skills/<name>/SKILL.mdare checked against the filesystem. Missing target → error. - Every
user-namespace skill is referenced. Soft check (info-level).maintainerskills are skipped — they are maintainer-only and live outside the routing table. - AGENTS.md contains no Claude-isms. The lint scans for
~/.claude/paths andclaude mcp addinvocations viascanForClaudeIsms()— those are Claude-Code-specific and belong inCLAUDE.md, not the cross-agent routing file. - CLAUDE.md routing rules also appear in AGENTS.md. If
CLAUDE.mdadds a row that AGENTS.md does not have, the lint errors with “move the rule to AGENTS.md (D-06)”. The routing table is single-sourced.
docs/playbooks/ (e.g. into a subfolder) means updating the regex and the link convention — open a separate PR.
CI runs lint:agents-md on every PR. Failures block merge.
Authoring checklist
- Decide what the playbook owns. One role, one domain. If the scope is more than a paragraph, it’s probably two playbooks.
- Write the
**Read this when:**line. This is what the agent matches against. Mirror the routing-table row you’ll add to AGENTS.md. - Draft the body in this order: pre-flight notes → output contract → workflow → hard invariants → CLI cookbook.
- Add a
## Sub-docstable if the playbook is longer than ~400 lines or has cleanly separable sub-tasks. - Add the row to AGENTS.md. Same trigger phrases as the
Read this when:line. - Run
bun run lint:agents-md. Confirm the row resolves to an existing file. - Cross-link. If the playbook depends on another playbook, name it inline — do not duplicate content.
Playbooks vs skills
| Surface | When to use |
|---|---|
Playbook (docs/playbooks/<role>.md) | Role or domain knowledge. Read on demand by the agent. No slash command. |
Skill (.agents/skills/<name>/SKILL.md) | Narrow workflow with a deterministic input → output contract and one CLI command. Slash-invocable. |
evaluator, researcher, templater, install, dev-release, hyperframes, dev-tasks are skills.
Old role-shim skills (ralph-art-director, ralph-core, ralph-editor, ralph-producer, ralph-scenarist) were retired in favor of direct routing via AGENTS.md → playbooks.
Related
- Concepts: playbooks & skills — the routing model, narrated.
- Skill format — when to write a skill instead.
AGENTS.md— the routing table.docs/playbooks/README.md— the catalogue.scripts/lint-agents-md.ts— the lint source.