Guide · DML SDK & CLI
Use the DML SDK and CLI standalone
Everything here works without pi and without sop2harness. If you already have
DML programs — or you want to run and embed DeepClause in your own
service — the deepclause-sdk CLI and the TypeScript SDK are
the whole surface.
Who this is for
Use this guide if you do not author with the pi extension and do not build harnesses with sop2harness. You just have DML files and want to run them headless or call the runtime from TypeScript.
- CLI — run a
.dmlprogram from a shell, a script, or CI. - TypeScript SDK — embed the runtime in a service and supply your own model backend.
Install
DeepClause requires Node.js 18+.
npm install -g deepclause-sdk
deepclause init
deepclause show-model
deepclause init creates .deepclause/config.json,
the local tools directory, and the seeded system assets. Every command except
init expects a .deepclause/ directory in the
workspace. Use npx deepclause-sdk@latest for a one-off run.
Run DML headless
Point the CLI at a DML file and pass the input as an argument.
deepclause run skills/anc-routine-care.dml \
"What antenatal checkups are due at 28 weeks?" \
--stream \
--workspace ./data \
--sandbox \
--trace run.json
--streamprints model text as it arrives.--workspacesets the directory file tools may read or write.--sandboxruns shell tools inside the AgentVM container VM.--tracewrites a run record for review.
To produce a DML file from a Markdown spec, use compile or plan:
deepclause compile spec.md --analyze
deepclause plan spec.md --out skills/my-skill.dml
Compilation and static analysis live in the general SDK. The pi extension does not use them; there, pi authors DML directly.
Embed in TypeScript
Supply a host-provided model backend with createDeepClause; no
provider credentials are required when the host supplies the LLM.
import { createDeepClause, type LLMBackend } from "deepclause-sdk";
const llmBackend: LLMBackend = {
async complete(request) {
const response = await hostModel.complete({
messages: request.messages,
tools: request.tools,
signal: request.signal,
});
return {
text: response.text,
toolCalls: response.toolCalls,
usage: response.usage,
};
},
};
const deepclause = await createDeepClause({
model: "host-active-model",
llmBackend,
});
const result = await deepclause.runDML(dmlSource, {
args: ["What antenatal checkups are due at 28 weeks?"],
onText: (delta) => process.stdout.write(delta),
});
The backend receives messages, DML task tools, cancellation, token limits, and
an optional onText callback. See the
API reference for the full option and
event surface.
Tools and the whitelist
DML-defined tool predicates stay under a runtime tool whitelist. Only tools you register are reachable, so an embedding exposes high-level DML tools without handing over the full runtime registry.
const deepclause = await createDeepClause({
model: "host-active-model",
llmBackend,
tools: {
read_file: { policy: "allow", handler: readFile },
list_files: { policy: "allow", handler: listFiles },
write_file: { policy: "approval", handler: writeFile },
},
});
Use deepclause list-tools to see the resolved built-in and MCP
tools.
Models and providers
Model choice is split into three slots: gateway (orchestration),
run (skill execution), and compile (authoring).
deepclause set-model anthropic:claude-sonnet-4-20250514 --slot compile
deepclause set-model openrouter:google/gemini-2.5-flash --slot gateway
For local or self-hosted models, use an OpenAI-compatible custom: provider:
export LLM_PROVIDER_LOCAL_BASE_URL="http://localhost:11434/v1"
export LLM_PROVIDER_LOCAL_API_KEY="dummy"
deepclause set-model custom:local:qwen3-32b --slot run
Works with Ollama, vLLM, LM Studio, or any endpoint that speaks an OpenAI-style chat/completions API.
Decision models
Besides generation, DML can route a bounded semantic decision to a
decision model. Register backends with
judgeBackends and select one with defaultJudge:
import {
createDeepClause,
createLLMJudgeBackend,
createJevJudgeBackend,
} from "deepclause-sdk";
const sdk = await createDeepClause({
model,
llmBackend,
judgeBackends: {
llm: createLLMJudgeBackend({ llmBackend }),
jev: createJevJudgeBackend({ apiKey: process.env.TYPESAFE_API_KEY }),
},
defaultJudge: "llm",
});
The llm backend is the default, so the choose,
rate, verify, and probability
predicates work with no new credentials. Jev (TypeSafe System
One) is the opt-in calibrated backend. See
Decision models for the DML surface,
capability gating, and configuration.
Sandboxing and static analysis
- WASM logic core. DML executes in a logic engine compiled to WebAssembly; the host is reachable only through explicit hooks.
- Host shell by default. Shell tools run in the active workspace;
shell.wrappercan forceclean-room,bwrap, orsandbox-exec. - AgentVM on demand.
--sandboxruns shell tools inside a dependency-free container VM, with network off by default. - Compile-time security. Static taint analysis flags untrusted data reaching the system prompt, dangerous tools, or task memory; an optional LLM audit reviews the program. Use
--no-auditto skip only the LLM review.
Use it in CI
A minimal headless job: install, run with a trace, and fail the build on a non-zero exit.
npm install -g deepclause-sdk
deepclause init --model openai:gpt-4o-mini
deepclause run skills/anc-routine-care.dml "Checkup schedule at 28 weeks" \
--sandbox --trace artifacts/run.json --no-audit
Credentials come from the environment. DeepClause never asks for or stores an API key in the workspace.
Next steps
DML SDK/CLI command reference → API reference → DML language reference → DML language examples →
Using pi or sop2harness instead? Start with the pi extension or sop2harness guides.