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

SOP Syntax Reference

SOP definitions are loaded from subdirectories under sops_dir. When sops_dir is omitted from config, CLI commands fall back to <workspace>/sops for offline inspection, but runtime SOP execution is disabled.

1. Directory Layout

<workspace>/sops/
  deploy-prod/
    SOP.toml
    SOP.md

Each SOP must have SOP.toml. SOP.md is optional, but runs with no parsed steps will fail validation.

2. SOP.toml

3. SOP.md Step Format

Steps are parsed from the ## Steps section.

## Steps

1. **Preflight** — Check service health and release window.
   - tools: http_request

2. **Deploy** — Run deployment command.
   - tools: shell
   - requires_confirmation: true
   - input: {"type":"object","required":["version"],"properties":{"version":{"type":"string"}}}
   - output: {"type":"object","required":["digest"],"properties":{"digest":{"type":"string"}}}
   - next: 3

Parser behavior:

  • Numbered items (1., 2., …) define step order.
  • Leading bold text (**Title**) becomes step title.
  • - tools: maps to suggested_tools.
  • - requires_confirmation: true enforces approval for that step.
  • - allow-tools: and - deny-tools: define an explicit per-step tool scope.
  • - input: and - output: attach JSON Schema-like step boundary contracts.
  • - next: and - depends_on: route non-linear runs. Ineligible routed steps are marked skipped and leave the run pending instead of dispatching.
  • - on_failure: accepts fail, retry:<count>, or goto:<step> and is enforced for reported step failures and output schema failures.
  • - mode: overrides the SOP execution mode for that step.

Step Contract Enforcement

Step contracts are optional. When present, input and output accept a compact JSON object with type, required, properties, and items fields. The supported primitive types are object, array, string, number, integer, boolean, and null.

The [sop] config controls enforcement:

FieldDefaultEffect
step_schema_enforcetrueValidate declared step input/output schemas at engine boundaries.
step_scope_enforcefalseTreat per-step tool scopes as enforced filters instead of advisory hints.
step_mandatory_tools["sop_advance", "sop_approve", "sop_status"]Keep lifecycle tools available while scope enforcement is enabled.
max_step_visits256Stop routed runs that revisit one step too many times.
max_step_retries2Limit retries requested by a step failure policy.
untrusted_payload_max_bytes8192Cap untrusted trigger topic/payload text at a UTF-8 character boundary; 0 disables the cap.
untrusted_input_guard"warn"Prompt-guard action for untrusted trigger input: warn, block, or sanitize.
untrusted_guard_sensitivity0.7Sensitivity used by prompt-guard screening and outbound redaction.
untrusted_frame_warningtrueInclude explanatory warning text in the untrusted-content frame. Frame boundaries remain enabled.
untrusted_outbound_redacttrueEnable shared outbound redaction for SOP content-safety consumers.
procedural_memory_enabledfalseRegister the sop_workshop tool for proposal capture, review, and explicit SOP write-back.

Schema enforcement fails closed: invalid step input prevents the step from starting, and invalid step output is routed through the step’s on_failure policy. Routing enforcement replaces linear current_step + 1 advancement in LLM and deterministic runs. Tool-scope enforcement narrows the live step turn’s available tools and blocks scoped-out calls at dispatch.

Untrusted trigger topic and payload text is capped, normalized, screened, and framed before it reaches step context. Framing is always on; the warning text can be hidden, but raw external trigger text is not interpolated into the model context.

Procedural memory is opt-in. When enabled, sop_workshop can create and inspect stored SOP proposals, capture completed run context into a candidate procedure, and apply an approved proposal to SOP.toml/SOP.md. Write-back only happens through the explicit apply action.

4. Trigger Types

TypeFieldsNotes
mqtttopic, optional conditionMQTT message arrival. Live: delivered by the MQTT listener.
webhookpathInbound HTTP request. Defined and matched, but no live route feeds it.
cronexpressionTime-based firing. Defined and matched, but no scheduler feeds it.
peripheralboard, signal, optional conditionHardware signal. Defined and matched, but no peripheral listener feeds it.
filesystempath, optional condition, optional eventsFilesystem change. Live: delivered by the filesystem watcher.
calendarcalendar_source, optional calendar_ids, optional conditionCalendar event state. Defined and matched, but no poller feeds it live.
channelchannel, optional alias, optional conditionInbound message or forge/platform event on a configured channel (telegram, discord, slack, git, …). Live: delivered by the channel orchestrator when the channel’s SOP dispatch is enabled. The Git forge producer sets an event topic of the form <channel>.<alias>:<event_type> and puts event_type in the payload, so an authored condition filters forge events by type without a second trigger shape.
manualnoneAgent-initiated run via the sop_execute tool. Not an external fan-in.
amqprouting_key, optional conditionAMQP delivery. Live: delivered by the AMQP consumer in a SOP dispatch mode.

For the live-versus-unwired status of each source and the transport details, see SOP Fan-In.

5. Condition Syntax

condition is evaluated fail-closed (invalid condition/payload => no match).

  • JSON path comparisons: $.value > 85, $.status == "critical"
  • Direct numeric comparisons: > 0 (useful for simple payloads)
  • Operators: >=, <=, !=, >, <, ==

6. Validation

Use:

sh

zeroclaw sop validate
zeroclaw sop validate <name>

Validation warns on empty names/descriptions, missing triggers, missing steps, and step numbering gaps.