Workflows
Workflows sit one layer above recipes. A workflow is a playbook the calling agent reads to learn how to iterate items in a domain (one control, all pending scope questions, the entire campaign). Recipes describe what to do per item; workflows describe how to walk the items.
Three-layer routing model:
engagement (deterministic Python rules)
→ workflow (markdown playbook the calling agent reads)
→ recipe (calling agent picks per item from the menu)
The engagement layer (start_task) deterministically selects the appropriate
playbook from prompt entities. Agents can also inspect the registry directly.
What Ships in v1
Nine built-in workflows:
| ID | Iterates over | Pick when |
|---|---|---|
single-control | one control | The user names exactly one control id and the work fits in a single focused pass. |
scope-question | scope questionnaire items | The user references the scope questionnaire or scope is the active workflow-state blocker. |
scope-artifacts | system-spec kinds | The user wants the scope artifacts (asset inventory, boundary, network DFD, PPSM, interconnection) produced and connected to the scope page. |
policy-question | policy questionnaire items | The user references an org policy questionnaire or policy is the active blocker. |
campaign | local Campaign items | Bulk control, Issue-triage, or evidence-review work dispatched to isolated child Plan sessions. |
preflight | connected source kinds | The active scope needs source bindings verified and an active recipe menu provisioned. |
stig-scan-remediation | STIG rules | The user asks for a source-verified STIG scan/remediation lifecycle with test-result, Issue, evidence, and leaf-approval reconciliation. |
risk-assessment | system risks | The user asks to review/attest the system risk register and generate or prove its RAR. |
formal-assessment | assessments | The user asks to schedule/start a formal assessment, freeze its immutable snapshot, and prepare the Auditor Portal. |
Browse them:
pretorin recipe list # for recipes (CLI)
There’s no pretorin workflow list CLI yet — workflows are discovered
through MCP only:
list_workflows— summary metadata for every loaded workflow.get_workflow(workflow_id)— full manifest plus the markdown body.
How a Workflow’s Body Looks
Every workflow body has the same shape: a brief intent statement, a description of the iteration shape, a step-by-step block, and a “what to avoid” closing section. Read one of the built-ins as a template:
cat src/pretorin/workflows_lib/_workflows/single-control/workflow.md
The frontmatter declares:
| Field | Notes |
|---|---|
id | kebab-case, globally unique |
version | SemVer-ish |
name | display name |
description | ≥ 50 chars, what the engagement layer matches against |
use_when | ≥ 30 chars, explicit trigger guidance |
produces | evidence / narrative / answers / mixed |
iterates_over | single_control / scope_questions / policy_questions / campaign_items / system_spec_kinds / source_kinds / stig_rules / system_risks / assessments |
recipes_commonly_used | hint list of recipe ids the agent often picks |
Why Workflows Matter
Without workflows, the calling agent would freelance the iteration pattern for every task. That’s drift-prone — different agents hit the same questionnaire and follow different orders, producing inconsistent audit trails. The workflow body fixes the pattern: load pending items, filter, iterate, pick a recipe per item, submit through the audit boundary, optionally trigger review.
recipes_commonly_used is a hint, not a binding. The agent reads
list_recipes(system_id=...) at runtime and picks per-item by matching
use_when strings against recipes whose required sources are connected.
When no recipe fits, the workflow surfaces a structured recipe_gap
instead of writing directly.
Calling-agent iteration
Every workflow is a playbook for a calling agent. For bounded tasks, that agent
iterates in its current context window. A Plan-backed campaign uses
isolated item iteration instead: the shared CLI/MCP coordinator freezes a parent/item roster,
embedded Hatchet assigns deterministic child Plans, and a separate managed
session using the selected Codex or OpenCode harness reads the selected workflow
and recipe surface for each item.
Because these are unattended privileged children, their recipe surface is
restricted to official package built-ins whose exact source/version/content
bytes were activated for the frozen system/framework. Missing pins become
recorded unavailable/skipped decisions and limitations; project or user recipe
shadowing is never adopted by a Campaign worker.
There is no recipe-level LLM, server-side Campaign LLM, or hidden reasoning runtime inside Pretorin. Large Campaigns remain tractable without putting every control into one context window, while existing platform APIs retain authority over compliance artifacts and review.
Authoring a New Workflow
v1 doesn’t ship a workflow scaffolder — workflows are first-party only. If you need a new iteration shape, open an issue describing:
- What domain it iterates (controls? questions? something else?).
- Why the existing workflows don’t fit.
- The recipes the workflow would commonly use.
Community workflows remain a future extension because routing rules must include third-party contributions safely and deterministically.
What’s Already Wired
- Engagement layer (
start_task) — picks the workflow from the user’s prompt entities. See Engagement Layer. - Capture preflight —
start_taskreturnssuggested_capture_planand workflows can refresh it withcheck_sources. Evidence and narrative writes then proceed through recipe contexts.
Roadmap
- Richer recipe execution — add more first-party and community recipes for operational systems such as GitHub, Kubernetes, and eMASS.
- Community workflows — third loader path, scaffolder, validator. v1.5.