Template Authoring Guide

March 5, 2026 ยท View on GitHub

This guide explains how review templates work and how to create custom ones.

Note: Custom user-defined templates are a planned future feature. Currently, templates must be added to the source code. This guide documents the template system for contributors and future extension.

Overview

A review template is a YAML file that defines:

  • What the review agent should look for (system prompt)
  • What tools it can use
  • What inputs it requires
  • How the review prompt is constructed

YAML Schema

# Required fields
name: string              # Unique template identifier
description: string       # Short description shown in `review list`
system_prompt: |          # Multi-line system prompt for the review agent
  Instructions for the reviewer...

allowed_tools: [string]   # SDK tools the agent can use
                          # Common: Read, Glob, Grep, Bash

permission_mode: string   # SDK permission mode
                          # "bypassPermissions" for read-only reviews
                          # "acceptEdits" if the agent needs write access

setting_sources: null | [string]
                          # null: no project settings loaded
                          # [project]: loads CLAUDE.md and project rules

# Input definitions
inputs:
  required:
    - name: string        # Input key name
      description: string # Description shown in help
  optional:
    - name: string
      description: string
      default: string     # Default value if not provided

# Prompt construction (exactly one required)
prompt_template: |        # String template with {input_name} placeholders
  Review {input} against {against}...

# OR
prompt_builder: module.path.function_name
                          # Dotted path to a Python callable
                          # Receives dict[str, str] of inputs, returns str

# Optional
model: string | null      # Default model for this template (e.g. opus, sonnet)
                          # Overridden by CLI --model flag or config default_model
hooks: null | object      # SDK hook configuration (schema ready, not yet wired)

Prompt construction

Templates use exactly one of two prompt construction methods:

prompt_template (inline)

A string with {placeholder} references to input names. Simple and suitable for most templates.

prompt_template: |
  Review the following document:
  **Input:** {input}
  **Reference:** {against}
  Evaluate alignment and report findings.

prompt_builder (Python callable)

A dotted path to a Python function for complex prompt logic. The function receives a dict[str, str] of inputs and returns a string.

prompt_builder: squadron.review.builders.code.code_review_prompt

The corresponding Python function:

def code_review_prompt(inputs: dict[str, str]) -> str:
    """Build a code review prompt with conditional sections."""
    parts = ["Review the code in the project."]

    if diff_ref := inputs.get("diff"):
        parts.append(f"Focus on changes since git ref: {diff_ref}")

    if file_pattern := inputs.get("files"):
        parts.append(f"Scope: files matching {file_pattern}")

    return "\n\n".join(parts)

Use prompt_builder when:

  • The prompt has conditional sections based on which inputs are provided
  • You need to read files or perform logic before constructing the prompt
  • The template string approach would be too complex

Example: annotated template

name: arch
description: "Architectural review - evaluate document against architecture/HLD"

system_prompt: |
  You are an architectural reviewer. Your task is to evaluate whether a design
  document aligns with a parent architecture document.

  Report your findings using this format:

  ## Summary
  [PASS | CONCERNS | FAIL]

  ## Findings

  ### [PASS|CONCERN|FAIL] Finding title
  Description with specific references.

allowed_tools: [Read, Glob, Grep]
permission_mode: bypassPermissions
model: opus
setting_sources: null

inputs:
  required:
    - name: input
      description: "Document to review"
    - name: against
      description: "Architecture document to review against"
  optional:
    - name: cwd
      description: "Working directory for file reads"
      default: "."

prompt_template: |
  Review the following document for architectural alignment:

  **Input document:** {input}
  **Architecture document:** {against}

  Read both documents, then evaluate the input against the architecture.

Built-in templates

arch

Reviews a document against an architecture reference. Uses Read, Glob, Grep tools. Does not load project settings (setting_sources: null). Default model: opus.

tasks

Reviews a task breakdown against its parent slice design. Same tool set and permissions as arch. Default model: opus.

code

Reviews project code. Uses Read, Glob, Grep, and Bash tools. Loads project settings (setting_sources: [project]), which means CLAUDE.md rules are available to the review agent. Uses a prompt_builder for conditional diff/files/survey sections. Default model: sonnet.

Output format

All review agents are instructed to produce output in this format:

## Summary
PASS | CONCERNS | FAIL

## Findings

### [PASS|CONCERN|FAIL] Finding title
Description of the finding.

The parser (squadron.review.parsers) extracts:

  • Verdict from the ## Summary section
  • Findings from ### [SEVERITY] Title blocks

Both bracketed (### [PASS] Title) and unbracketed (### PASS Title) formats are accepted. Bold verdicts (**PASS**) are also recognized.

Registration

Templates are registered in the template registry at runtime:

from squadron.review.templates import register_template, load_template

# Load from YAML file
template = load_template(Path("my-template.yaml"))
register_template(template)

Built-in templates are loaded automatically from src/squadron/review/templates/builtin/ when any review command runs.