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.

Two ways in
  • CLI — run a .dml program 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
  • --stream prints model text as it arrives.
  • --workspace sets the directory file tools may read or write.
  • --sandbox runs shell tools inside the AgentVM container VM.
  • --trace writes 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.wrapper can force clean-room, bwrap, or sandbox-exec.
  • AgentVM on demand. --sandbox runs 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-audit to 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

Using pi or sop2harness instead? Start with the pi extension or sop2harness guides.