12 KiB
summary, title, sidebarTitle, read_when
| summary | title | sidebarTitle | read_when | |||
|---|---|---|---|---|---|---|
| Public OpenClaw App SDK for external apps, scripts, dashboards, CI jobs, and IDE extensions | OpenClaw App SDK | App SDK |
|
The OpenClaw App SDK is the public client API for apps outside the
OpenClaw process. Use @openclaw/sdk when a script, dashboard, CI job, IDE
extension, or other external app wants to connect to the Gateway, start agent
runs, stream events, wait for results, cancel work, or inspect Gateway
resources.
What ships today
@openclaw/sdk ships with:
| Surface | Status | What it does |
|---|---|---|
OpenClaw |
Ready | Main client entry point. Owns transport, connection, requests, and events. |
GatewayClientTransport |
Ready | WebSocket transport backed by the Gateway client. |
oc.agents |
Ready | Lists, creates, updates, deletes, and gets agent handles. |
Agent.run() |
Ready | Starts a Gateway agent run and returns a Run. |
oc.runs |
Ready | Creates, gets, waits for, cancels, and streams runs. |
Run.events() |
Ready | Streams normalized per-run events with replay for fast runs. |
Run.wait() |
Ready | Calls agent.wait and returns a stable RunResult. |
Run.cancel() |
Ready | Calls sessions.abort by run id, with session key when available. |
oc.sessions |
Ready | Creates, resolves, sends to, patches, compacts, and gets session handles. |
Session.send() |
Ready | Calls sessions.send and returns a Run. |
oc.models |
Ready | Calls models.list and the current models.authStatus status RPC. |
oc.tools |
Ready | Lists, scopes, and invokes Gateway tools through the policy pipeline. |
oc.artifacts |
Ready | Lists, gets, and downloads Gateway transcript artifacts. |
oc.approvals |
Ready | Lists and resolves exec approvals through Gateway approval RPCs. |
oc.environments |
Partial | Lists Gateway-local and node environment candidates; create/delete are not wired. |
oc.rawEvents() |
Ready | Exposes raw Gateway events for advanced consumers. |
normalizeGatewayEvent() |
Ready | Converts raw Gateway events into the stable SDK event shape. |
The SDK also exports the core types used by those surfaces:
AgentRunParams, RunResult, RunStatus, OpenClawEvent,
OpenClawEventType, GatewayEvent, OpenClawTransport,
GatewayRequestOptions, SessionCreateParams, SessionSendParams,
ArtifactSummary, ArtifactQuery, ArtifactsListResult,
ArtifactsGetResult, ArtifactsDownloadResult, RuntimeSelection,
EnvironmentSelection, WorkspaceSelection, ApprovalMode, and related
result types.
Connect to a Gateway
Create a client with an explicit Gateway URL, or inject a custom transport for tests and embedded app runtimes.
import { OpenClaw } from "@openclaw/sdk";
const oc = new OpenClaw({
url: "ws://127.0.0.1:18789",
token: process.env.OPENCLAW_GATEWAY_TOKEN,
requestTimeoutMs: 30_000,
});
await oc.connect();
new OpenClaw({ gateway: "ws://..." }) is equivalent to url. The
gateway: "auto" option is accepted by the constructor, but automatic Gateway
discovery is not a separate SDK feature yet; pass url when the app does not
already know how to discover the Gateway.
For tests, pass an object that implements OpenClawTransport:
const oc = new OpenClaw({
transport: {
async request(method, params) {
return { method, params };
},
async *events() {},
},
});
Run an agent
Use oc.agents.get(id) when the app wants an agent handle, then call
agent.run().
const agent = await oc.agents.get("main");
const run = await agent.run({
input: "Review this pull request and suggest the smallest safe fix.",
model: "openai/gpt-5.5",
sessionKey: "main",
timeoutMs: 30_000,
});
for await (const event of run.events()) {
const data = event.data as { delta?: unknown };
if (event.type === "assistant.delta" && typeof data.delta === "string") {
process.stdout.write(data.delta);
}
}
const result = await run.wait({ timeoutMs: 120_000 });
console.log(result.status);
Provider-qualified model refs such as openai/gpt-5.5 are split into Gateway
provider and model overrides. timeoutMs stays milliseconds in the SDK and
is converted to Gateway timeout seconds for the agent RPC.
run.wait() uses the Gateway agent.wait RPC. A wait deadline that expires
while the run is still active returns status: "accepted" instead of pretending
the run itself timed out. Runtime timeouts, aborted runs, and cancelled runs are
normalized into timed_out or cancelled.
Create and reuse sessions
Use sessions when the app wants durable transcript state.
const session = await oc.sessions.create({
agentId: "main",
label: "release-review",
});
const run = await session.send("Prepare release notes from the current diff.");
await run.wait();
Session.send() calls sessions.send and returns a Run. Session handles also
support:
await session.abort(run.id);
await session.patch({ label: "renamed-session" });
await session.compact({ maxLines: 200 });
Stream events
The SDK normalizes raw Gateway events into a stable OpenClawEvent envelope:
type OpenClawEvent = {
version: 1;
id: string;
ts: number;
type: OpenClawEventType;
runId?: string;
sessionId?: string;
sessionKey?: string;
taskId?: string;
agentId?: string;
data: unknown;
raw?: GatewayEvent;
};
Common event types include:
| Event type | Source Gateway event |
|---|---|
run.started |
agent lifecycle start |
run.completed |
agent lifecycle end |
run.failed |
agent lifecycle error |
run.cancelled |
Aborted/cancelled lifecycle end |
run.timed_out |
Timeout lifecycle end |
assistant.delta |
Assistant streaming delta |
assistant.message |
Assistant message |
thinking.delta |
Thinking or plan stream |
tool.call.started |
Tool/item/command start |
tool.call.delta |
Tool/item/command update |
tool.call.completed |
Tool/item/command completion |
tool.call.failed |
Tool/item/command failure or blocked status |
approval.requested |
Exec or plugin approval request |
approval.resolved |
Exec or plugin approval resolution |
session.created |
sessions.changed create |
session.updated |
sessions.changed update |
session.compacted |
sessions.changed compaction |
task.updated |
Task update events |
artifact.updated |
Patch stream events |
raw |
Any event without a stable SDK mapping yet |
Run.events() filters events to one run id and replays already-seen events for
fast runs. That means the documented flow is safe:
const run = await agent.run("Summarize the latest session.");
for await (const event of run.events()) {
if (event.type === "run.completed") {
break;
}
}
For app-wide streams, use oc.events(). For raw Gateway frames, use
oc.rawEvents().
Models, tools, artifacts, and approvals
Model helpers map to current Gateway methods:
await oc.models.list();
await oc.models.status({ probe: false }); // calls models.authStatus
Tool helpers expose the Gateway catalog, effective tool view, and direct
Gateway tool invocation. oc.tools.invoke() returns a typed envelope instead
of throwing for policy or approval refusals.
await oc.tools.list();
await oc.tools.effective({ sessionKey: "main" });
await oc.tools.invoke("tool-name", {
args: { input: "value" },
sessionKey: "main",
confirm: false,
idempotencyKey: "tool-call-1",
});
Artifact helpers expose the Gateway artifact projection for session, run, or
task context. Each call requires one explicit sessionKey, runId, or
taskId scope:
const { artifacts } = await oc.artifacts.list({ sessionKey: "main" });
const first = artifacts[0];
if (first) {
const { artifact } = await oc.artifacts.get(first.id, { sessionKey: "main" });
const download = await oc.artifacts.download(artifact.id, { sessionKey: "main" });
console.log(download.encoding, download.url);
}
Approval helpers use the exec approval RPCs:
const approvals = await oc.approvals.list();
await oc.approvals.respond("approval-id", { decision: "approve" });
Environment helpers expose read-only Gateway-local and node discovery:
const { environments } = await oc.environments.list();
await oc.environments.status(environments[0].id);
Explicitly unsupported today
The SDK includes names for the product model we want, but it does not silently pretend Gateway RPCs exist. These calls currently throw explicit unsupported errors:
await oc.tasks.list();
await oc.tasks.get("task-id");
await oc.tasks.cancel("task-id");
await oc.environments.create({});
await oc.environments.delete("environment-id");
Per-run workspace, runtime, environment, and approvals fields are typed
as future shape, but the current Gateway does not support those overrides on
the agent RPC. If callers pass them, the SDK throws before submitting the run
so work does not accidentally execute with default workspace, runtime,
environment, or approval behavior.
App SDK vs Plugin SDK
Use the App SDK when code lives outside OpenClaw:
- Node scripts that start or observe agent runs
- CI jobs that call a Gateway
- dashboards and admin panels
- IDE extensions
- external bridges that do not need to become channel plugins
- integration tests with fake or real Gateway transports
Use the Plugin SDK when code runs inside OpenClaw:
- provider plugins
- channel plugins
- tool or lifecycle hooks
- agent harness plugins
- trusted runtime helpers
App SDK code should import from @openclaw/sdk. Plugin code should import from
documented openclaw/plugin-sdk/* subpaths. Do not mix the two contracts.