Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Authoring Recipes

Recipes are markdown-plus-Python playbooks that the calling AI agent invokes through MCP. Each recipe is a directory with a recipe.md (frontmatter + prose body) and one or more script files. The agent reads the body to understand what the recipe does, picks one when its use_when matches the task, and calls the recipe’s scripts as MCP tools.

If you’ve ever written a Claude Code skill, the shape will feel familiar — recipes are the same idea, scoped to compliance work and stamped with audit metadata automatically.

Why You Might Write One

Three concrete reasons:

  • Your team has a non-obvious procedure for capturing a particular kind of evidence (e.g., “pull the latest IAM policy from the prod account, redact customer ARNs, attach as a configuration record”). Encoding it as a recipe means every teammate’s agent does the same steps the same way.
  • You wrap an internal scanner that produces STIG-style results. A recipe exposes it next to the built-in inspec-baseline / openscap-baseline so the calling agent can pick it for the rules it covers.
  • You’re contributing back upstream. First-party scanner recipes (inspec-baseline, openscap-baseline, etc.) live under src/pretorin/recipes/_recipes/. New contributions follow the same shape.

Write Your First Recipe in 10 Minutes

# 1. Scaffold a fresh recipe in your user folder.
pretorin recipe new my-first-recipe

# 2. The scaffolder drops a directory at ~/.pretorin/recipes/my-first-recipe/
#    with recipe.md, scripts/main.py, README.md, tests/test_recipe.py.

# 3. Edit the description, use_when, and the body of recipe.md.
$EDITOR ~/.pretorin/recipes/my-first-recipe/recipe.md

# 4. Edit scripts/main.py — implement `async def run(ctx, **params)`.
$EDITOR ~/.pretorin/recipes/my-first-recipe/scripts/main.py

# 5. Validate.
pretorin recipe validate my-first-recipe

# 6. Run it locally to test (no agent / MCP boundary involved).
pretorin recipe run my-first-recipe --param key=value

If validate passes and run prints the result you expect, the recipe is in the registry. Restart your MCP client and the agent can use it on the next task.

pretorin recipe run is a local-testing path: writes go through your authenticated PretorianClient directly, so audit-metadata stamping requires explicit audit_metadata on each create_evidence call (see Writer tools). The agent path through MCP stamps automatically.

What Ships in v1

  • Four loader paths with clear precedence: explicit > project > user > built-in. See Loader paths below.
  • pretorin recipe list / show / new / validate / run CLI commands.
  • list_recipes / get_recipe MCP discovery tools, including source-aware filtering with list_recipes(system_id=...).
  • list_connected_sources / check_sources MCP preflight tools for capture planning.
  • Per-script MCP tools auto-registered as recipe_<safe_id>__<script_name>.
  • Audit-metadata stamping: the calling agent opens a recipe execution context with start_recipe(...); every platform write inside the context is stamped with producer_kind="recipe", the recipe id, and the recipe version. The platform records the full chain.
  • Workflow playbooks (list_workflows / get_workflow) for the four item-iteration shapes: single-control, scope-question, policy-question, campaign. Workflows describe how to iterate; recipes describe what to do per item.
  • Recipe-only MCP writes for evidence and narratives: agents pass recipe_context_id on write tools, and narrative recipes also pass cited evidence_ids.

Loader Paths

SourcePathUse it when
Built-insrc/pretorin/recipes/_recipes/<id>/First-party recipes shipped with pretorin-cli.
User folder~/.pretorin/recipes/<id>/Your local recipes — survives across projects.
Project folder<repo>/.pretorin/recipes/<id>/Team-shared recipes checked into the compliance repo.
Explicit pathpretorin recipe show --path /abs/...Testing a recipe while authoring.

If the same id appears in two paths, the higher-precedence one wins. pretorin recipe show <id> --sources lists every location and marks which is active.

Tier

Each loaded recipe gets a tier set by the loader from its source path:

  • official — built-in, shipped with pretorin-cli (forced regardless of what the manifest says).
  • community — anything from the user/project folders or explicit paths.
  • partner — reserved for installed packages (v1.5).

The calling agent sees the tier in list_recipes output and can factor it in when picking. Community recipes are first-class — the tier is signal, not a permission gate.

  • Manifest reference — every frontmatter field with examples.
  • Script contract — the async def run(ctx, **params) -> dict signature.
  • Writer tools — the platform-API tools your scripts call, and how audit metadata gets stamped.
  • Testing — pytest fixtures and patterns.
  • Publishing — how to share a community recipe or PR an official one.
  • Workflows — the layer above recipes: how the calling agent picks a workflow, then picks recipes per item.
  • Worked example — a community recipe walked through end-to-end.