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.

Install 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
StepWhat happens
initCreates s2h.json, harness/, and seeds .pi/deepclause/ non-destructively.
createIngests SOPs, starts a pi session with the extension loaded, authors DML Skills, and validates them deterministically.
commitRuns the validation gate, bumps the harness version, commits, and tags v<version>.
exportGenerates 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/chat streams 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__run tool 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.

Authoring uses pi

s2h create embeds a normal pi AgentSession with the pi extension loaded, so the authoring intelligence and conventions are shared with in-session authoring. Bash is off by default for authoring, and writes are confined to the project.

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