mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:10:42 +00:00
317 lines
12 KiB
Markdown
317 lines
12 KiB
Markdown
---
|
|
summary: "Public OpenClaw App SDK for external apps, scripts, dashboards, CI jobs, and IDE extensions"
|
|
title: "OpenClaw App SDK"
|
|
sidebarTitle: "App SDK"
|
|
read_when:
|
|
- You are building an external app, script, dashboard, CI job, or IDE extension that talks to OpenClaw
|
|
- You are choosing between the App SDK and the Plugin SDK
|
|
- You are integrating with Gateway agent runs, sessions, events, approvals, models, or tools
|
|
---
|
|
|
|
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.
|
|
|
|
<Note>
|
|
The App SDK is different from the [Plugin SDK](/plugins/sdk-overview).
|
|
`@openclaw/sdk` talks to the Gateway from outside OpenClaw.
|
|
`openclaw/plugin-sdk/*` is only for plugins that run inside OpenClaw and
|
|
register providers, channels, tools, hooks, or trusted runtimes.
|
|
</Note>
|
|
|
|
## 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.
|
|
|
|
```typescript
|
|
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`:
|
|
|
|
```typescript
|
|
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()`.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
const approvals = await oc.approvals.list();
|
|
await oc.approvals.respond("approval-id", { decision: "approve" });
|
|
```
|
|
|
|
Environment helpers expose read-only Gateway-local and node discovery:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```typescript
|
|
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.
|
|
|
|
## Related
|
|
|
|
- [OpenClaw App SDK API design](/reference/openclaw-sdk-api-design)
|
|
- [Gateway RPC reference](/reference/rpc)
|
|
- [Agent loop](/concepts/agent-loop)
|
|
- [Agent runtimes](/concepts/agent-runtimes)
|
|
- [Sessions](/concepts/session)
|
|
- [Background tasks](/automation/tasks)
|
|
- [ACP agents](/tools/acp-agents)
|
|
- [Plugin SDK overview](/plugins/sdk-overview)
|