How SOPs run
Runtime contract
- SOP definitions are loaded from
<shared>/sops/<sop_name>/SOP.tomlplus optionalSOP.md. - CLI
zeroclaw sopcurrently manages definitions only:list,validate,show. - SOP runs are started by a live event fan-in (authenticated webhook, MQTT, filesystem, or AMQP), by the daemon’s periodic SOP maintenance tick for
crontriggers, or by the in-agent toolsop_execute. The remaining trigger types (peripheral and calendar) are defined and matched but not yet wired to a live event source (see SOP Fan-In). - Run progression uses tools:
sop_status,sop_approve,sop_advance. - Run state is process-local by default. With
sop.persist_runs = true, successful initialization of the default SQLite backend stores it under<data_dir>/sop/runs.dband restores active runs after restart. Initialization failure logs a warning and falls back to process-local memory. - SOP audit records are persisted in the configured Memory backend under category
sop.
Run state and audit history are separate surfaces. See Background work lifecycle for lifecycle ownership, cancellation, and restart semantics.
Event flow
graph LR
MQTT[MQTT listener] -->|topic match| Dispatch
TOOL[sop_execute tool] -->|manual| Dispatch
WH[Webhook request] -->|authenticated HTTP fan-in| Dispatch
CRON[Cron trigger] -->|daemon maintenance tick| Dispatch
GPIO[Peripheral trigger] -.->|defined, unwired| Dispatch
Dispatch --> Engine[SOP Engine]
Engine --> Run[SOP Run]
Run --> Action{Action}
Action -->|ExecuteStep| Agent[Agent Loop]
Action -->|WaitApproval| Human[Operator]
Human -->|sop_approve| Run
Getting started
-
sops_diris unset by default, so runtime SOP loading is off out of the box. Opt in by settingsops_dirthrough the gateway, zerocode, orzeroclaw config set. A relative value resolves against the install root (the directory holdingconfig.toml), so the documentedshared/sopsyields<install>/shared/sops, the same directory the SOP author writes to. An absolute or~-prefixed value is used as-is. Setting it back to""(or removing it) disables runtime SOP loading again; the CLI still falls back to<install>/shared/sopsfor offline inspection.Migrating from an earlier build? Relative
sops_dirvalues now resolve against the install root, matching howskill-bundlesdirectories resolve. Earlier builds had two different roots for the same setting, so check both before upgrading:Surface on earlier builds Root it used Where sops_dir = "shared/sops"landedRuntime loading and local zeroclaw sopCLIdata_dir<data_dir>/shared/sopsWeb and RPC SOP authoring <install>/shared<install>/shared/shared/sops(doubled segment)Both now resolve to the single canonical
<install>/shared/sops. Inspect both old locations and move any definitions you find there into<install>/shared/sops; definitions left behind in either tree become invisible after upgrade. Definitions authored through the old web or RPC surface are the easiest to miss, because they sit in the doubled writer path rather than the location the docs described.Any other relative value shifts the same way:
sops_dir = "my-sops"moves from<data_dir>/my-sops(runtime and CLI) or<install>/shared/my-sops(web and RPC authoring) to<install>/my-sops. Absolute and~-prefixed values are unaffected.The unset case moves too: the offline CLI fallback used to scan
<data_dir>/sopsand now scans<install>/shared/sops.zeroclaw sop listreads the new location, so an empty listing after upgrade means definitions are still sitting in one of the old trees. -
Create a SOP directory, for example:
~/.zeroclaw/shared/sops/deploy-prod/SOP.toml ~/.zeroclaw/shared/sops/deploy-prod/SOP.md -
Validate and inspect definitions:
sh
zeroclaw sop list zeroclaw sop validate zeroclaw sop show deploy-prod -
Trigger runs via configured event sources, or manually from an agent turn with
sop_execute.
For trigger routing and auth details, see SOP Fan-In.