Guide · sop2harness
sop2harness (s2h)
Turn Standard Operating Procedures into a runnable, versioned harness: a set of validated DML Skills plus the docs and manifest needed to run them — and export them as a self-hosted API, web chat, and MCP server.
npm install -g deepclause-sop2harness installs the
s2h command. Authoring (create), validation
(test, check), versioning (commit),
and export (export) are implemented.
What it is
s2h is a CLI that turns procedures written for humans into
procedures a program can run. The authoring step is agentic — a real pi
session with the pi extension loaded. The
runtime step is deterministic and portable, executed by the
DML SDK. The harness, not a compiler, is the product.
- One command to scaffold a harness project (
s2h init). - One command to author or update a harness from a prompt and/or SOP files (
s2h create). - Deterministic validation of every artifact before it is accepted.
- One command to export a ready-to-run API, web chat, MCP server, and Dockerfile (
s2h export).
The workflow
npm install -g deepclause-sop2harness # installs the s2h command
s2h init # scaffold a harness project
s2h create "Turn this SOP into a harness" # author + validate skills
s2h test # validate, diagrams, smoke-run
s2h commit -m "add triage workflow" # version, commit, tag
s2h export --out ./export # API + web chat + MCP + Dockerfile
| Step | What happens |
|---|---|
init | Creates s2h.json, harness/, and seeds .pi/deepclause/ non-destructively. |
create | Ingests SOPs, starts a pi session with the extension loaded, authors DML Skills, and validates them deterministically. |
commit | Runs the validation gate, bumps the harness version, commits, and tags v<version>. |
export | Generates a standalone server, web chat, MCP server, Docker assets, and a copy of the harness. |
Worked example: antenatal care
This walkthrough turns a three-page antenatal care SOP into a validated harness, versions it, and serves it over HTTP and MCP.
1. Scaffold
$ s2h init
scaffolded harness/ · seeded .pi/deepclause/
2. Author from the SOP
Pass a free-text request and the SOP file. The PDF is ingested and converted to Markdown for provenance.
$ s2h create "Turn our antenatal care SOP into a harness" \
--file ./sops/anc-guidelines.pdf
ingested anc-guidelines.pdf
pi session · authoring skills/anc-routine-care.dml
validated 3 skills · wrote harness.json + AGENTS.md
The generated harness looks like this:
harness/
harness.json
AGENTS.md
sops/anc-guidelines.md
.pi/deepclause/skills/
anc-routine-care.dml
anc-lab-orders.dml
anc-referral.dml
The router in harness.json maps wording to skills:
{
"name": "who-anc",
"version": "0.1.0",
"skills": [
{ "id": "anc-routine-care",
"triggers": ["antenatal", "checkup schedule", "routine visit"] },
{ "id": "anc-lab-orders",
"triggers": ["bloods", "lab orders", "screening"] },
{ "id": "anc-referral",
"triggers": ["refer", "high risk", "complication"] }
]
}
3. Validate, version, export
$ s2h test
harness valid · 3 skills · diagrams ok · 3/3 smoke runs passed
$ s2h check
harness valid · 3 skills · router covers every skill
$ s2h commit -m "add antenatal care workflow"
harness v0.1.0 · tagged
$ s2h export --out ./export
API + web chat + MCP server + Dockerfile
4. Run it
Call the exported API over SSE:
$ curl -N -X POST localhost:8080/api/chat \
-H 'content-type: application/json' \
-d '{"message":"First antenatal visit: 26y, 10 weeks, no prior complications."}'
event: route
data: {"skill":"anc-routine-care","reason":"trigger"}
event: stream
data: {"delta":"Decision: routine care — no referral."}
event: answer
data: {"skill":"anc-routine-care","content":"Risk: routine. Booking bloods, supplements, and a 4-visit schedule by 28 weeks."}
The same harness is exposed over MCP as one s2h__run tool, so
Claude and other agents can call it without any code changes.
The harness
A harness is the deliverable. Its core is a routing table plus one validated DML Skill per procedure.
harness/
harness.json # manifest: name, version, skills[], triggers, effects
AGENTS.md # router / policy table for hosts and humans
sops/ # ingested SOP sources (provenance)
.pi/deepclause/
skills/ # generated DML programs (one agent_main each)
plans/ # optional generated plans
Routing is host-side, from the AGENTS.md policy table and
harness.json.skills[].triggers. A dispatcher DML is optional.
A harness that needs a shell declares it, and shell steps run only inside the
AgentVM sandbox.
Export runtime
One export produces every way to reach the harness:
- HTTP API.
POST /api/chatstreams DML events over SSE, with routing, limits, and cancellation. - Web chat. A single static page with a skills sidebar, streaming answers, and a docs viewer.
- MCP server. One generic
s2h__runtool over Streamable HTTP and stdio, with progress and elicitation. - Docker. A non-root image with the harness copied read-only.
The exported project does not depend on pi. It runs the harness DML with the DML SDK and a bundled model backend.
Security defaults
- Read-only export by default. Write/effect tools require an explicit flag at export time.
- Root-confined file access. Every read is
realpath-checked against the harness root. - No host shell. Shell tools run inside the AgentVM sandbox, network off by default.
- Secrets from the environment only. Never stored in the harness or the export.
- Skill allowlist. The server runs only skills listed in the manifest.
Next steps
CLI reference → DML language reference → DML language examples → DML SDK/CLI →