Appearance
OpenClaw App SDK 提供两层 API:从 Gateway 协议 schema 生成的低级客户端,和包含 OpenClaw、Agent、Session、Run 等对象的高级包装器。开发者通过 oc.agents.list() 等命名空间操作资源,用 run.onApproval() 处理审批请求,并利用版本化事件流构建 UI。本文列出所有 API 方法、事件全集、结果格式、审批模型、Token 作用域,以及包结构和生成客户端策略。
OpenClaw App SDK API 设计:命名空间、事件与安全模型
本文是公开 OpenClaw App SDK 的详细 API 参考设计,与 Plugin SDK 分开定义。
::: note @openclaw/sdk 是面向外部应用/客户端的网关通信包。openclaw/plugin-sdk/* 是进程内插件创作契约。仅需运行智能体的应用不要从插件 SDK 的路径导入。 :::
App SDK 分为两层:
- 低级 Gateway 客户端(从版本化协议 schema 生成)。
- 高级易用包装器,包含
OpenClaw、Agent、Session、Run、Task、Artifact、Approval和Environment对象。
命名空间设计
低级命名空间紧密对应 Gateway 资源:
typescript
oc.agents.list();
oc.agents.get("main");
oc.agents.create(...);
oc.agents.update(...);
oc.sessions.list();
oc.sessions.create(...);
oc.sessions.resolve(...);
oc.sessions.send(...);
oc.sessions.messages(...);
oc.sessions.fork(...);
oc.sessions.compact(...);
oc.sessions.abort(...);
oc.runs.create(...);
oc.runs.get(runId);
oc.runs.events(runId, { after });
oc.runs.wait(runId);
oc.runs.cancel(runId);
oc.tasks.list({ status: "running" });
oc.tasks.get(taskId);
oc.tasks.cancel(taskId, { reason });
oc.tasks.events(taskId, { after }); // 未来 API
oc.models.list();
oc.models.status(); // Gateway models.authStatus
oc.tools.list();
oc.tools.invoke("tool-name", { sessionKey, idempotencyKey });
oc.artifacts.list({ runId });
oc.artifacts.get(artifactId, { runId });
oc.artifacts.download(artifactId, { runId });
oc.approvals.list();
oc.approvals.respond(approvalId, ...);
oc.environments.list();
oc.environments.create(...); // 未来 API: 当前 SDK 抛出 unsupported
oc.environments.status(environmentId);
oc.environments.delete(environmentId); // 未来 API: 当前 SDK 抛出 unsupported高级包装器应返回对象,使常见流程更顺畅:
typescript
const run = await agent.run(inputOrParams);
await run.cancel();
await run.wait();
for await (const event of run.events()) {
// 标准化事件流
}
const artifacts = await run.artifacts.list();
const session = await run.session();事件契约
公共 SDK 应公开版本化、可重放、标准化的事件。
typescript
type OpenClawEvent = {
version: 1;
id: string;
ts: number;
type: OpenClawEventType;
runId?: string;
sessionId?: string;
sessionKey?: string;
taskId?: string;
agentId?: string;
data: unknown;
raw?: unknown;
};id 是重放游标。消费者可以通过 events({ after: id }) 重新连接,并在保留期限内接收错过的事件。
推荐的标准事件家族:
| 事件 | 含义 |
|---|---|
run.created | 运行被接受。 |
run.queued | 运行正在等待会话通道、运行时或环境。 |
run.started | 运行时开始执行。 |
run.completed | 运行成功结束。 |
run.failed | 运行因错误结束。 |
run.cancelled | 运行被取消。 |
run.timed_out | 运行超时。 |
assistant.delta | 助手文本增量。 |
assistant.message | 完整的助手消息或替换。 |
thinking.delta | 推理或计划增量(策略允许时暴露)。 |
tool.call.started | 工具调用开始。 |
tool.call.delta | 工具调用流式进度或部分输出。 |
tool.call.completed | 工具调用成功返回。 |
tool.call.failed | 工具调用失败。 |
approval.requested | 运行或工具需要审批。 |
approval.resolved | 审批被批准、拒绝、过期或取消。 |
question.requested | 运行时向用户或宿主应用询问输入。 |
question.answered | 宿主应用提供了答案。 |
artifact.created | 新产物可用。 |
artifact.updated | 已有产物发生变化。 |
session.created | 会话被创建。 |
session.updated | 会话元数据改变。 |
session.compacted | 会话发生压缩。 |
task.updated | 后台任务状态改变。 |
git.branch | 运行时观察或改变了分支状态。 |
git.diff | 运行时产生或改变了差异。 |
git.pr | 运行时打开、更新或关联了拉取请求。 |
运行时的原生载荷通过 raw 可用,但应用不需要解析 raw 来支持普通 UI。
结果契约
Run.wait() 应返回稳定的结果信封:
typescript
type RunResult = {
runId: string;
status: "accepted" | "completed" | "failed" | "cancelled" | "timed_out";
sessionId?: string;
sessionKey?: string;
taskId?: string;
startedAt?: string | number;
endedAt?: string | number;
output?: {
text?: string;
messages?: SDKMessage[];
};
usage?: {
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
costUsd?: number;
};
artifacts?: ArtifactSummary[];
error?: SDKError;
};结果应保持简单稳定。时间戳值保留 Gateway 形状,因此当前生命周期支持的回通常报告毫秒级数字,而适配器可能仍返回 ISO 字符串。丰富的 UI、工具追踪和运行时原生细节应放在事件和产物中。
accepted 是非终态的等待结果:表示 Gateway 等待截止时间已过,而运行还未产生生命周期结束/错误。不能将其视为 timed_out;timed_out 仅用于运行本身超时。
审批和提问
审批必须是第一等公民,因为编码智能体经常跨越安全边界。
typescript
run.onApproval(async (request) => {
if (request.kind === "tool" && request.toolName === "exec") {
return request.approveOnce({ reason: "CI command allowed by policy" });
}
return request.askUser();
});审批事件应携带:
- 审批 ID
- 运行 ID 和会话 ID
- 请求类型
- 请求操作摘要
- 工具名称或环境操作
- 风险等级
- 可用决策
- 过期时间
- 决策是否可重用
提问与审批是分开的。提问要求用户或宿主应用提供信息;审批要求允许执行某个操作。
ToolSpace 模型
应用需要理解工具表面,而无需导入插件内部。
typescript
const tools = await run.toolSpace();
for (const tool of tools.list()) {
console.log(tool.name, tool.source, tool.requiresApproval);
}SDK 应公开:
- 标准化的工具元数据
- 来源:OpenClaw、MCP、plugin、channel、runtime 或 app
- schema 摘要
- 审批策略
- 运行时兼容性
- 工具是否隐藏、只读、可写或宿主可用
通过 SDK 调用工具应显式且有范围。大多数应用应运行智能体,而不是直接调用任意工具。
产物模型
产物应覆盖文件之外的范围。
typescript
type ArtifactSummary = {
id: string;
runId?: string;
sessionId?: string;
type:
| "file"
| "patch"
| "diff"
| "log"
| "media"
| "screenshot"
| "trajectory"
| "pull_request"
| "workspace";
title?: string;
mimeType?: string;
sizeBytes?: number;
createdAt: string;
expiresAt?: string;
};常见示例:
- 文件编辑和生成文件
- 补丁包
- VCS 差异
- 截图和媒体输出
- 日志和追踪包
- 拉取请求链接
- 运行时轨迹
- 托管环境工作区快照
产物访问应支持编辑、保留和下载 URL,不假定每个产物都是普通本地文件。
安全模型
App SDK 必须显式声明权限。
推荐的 Token 作用域:
| 作用域 | 允许的操作 |
|---|---|
agent.read | 列出和检查智能体。 |
agent.run | 启动运行。 |
session.read | 读取会话元数据和消息。 |
session.write | 创建、发送、分支、压缩和中止会话。 |
task.read | 读取后台任务状态。 |
task.write | 取消或修改任务通知策略。 |
approval.respond | 批准或拒绝请求。 |
tools.invoke | 直接调用暴露的工具。 |
artifacts.read | 列出和下载产物。 |
environment.write | 创建或销毁托管环境。 |
admin | 管理操作。 |
默认行为:
- 默认不转发秘密
- 默认不无限制传递环境变量
- 使用秘密引用而非秘密值
- 显式沙箱和网络策略
- 显式远程环境保留
- 除非策略证明相反,否则宿主执行需要审批
- 原始运行时事件在离开 Gateway 前被编辑,除非调用者具有更强的诊断范围
托管环境提供者
托管智能体应实现为环境提供者。
typescript
type EnvironmentProvider = {
id: string;
capabilities: {
checkout?: boolean;
sandbox?: boolean;
networkPolicy?: boolean;
secrets?: boolean;
artifacts?: boolean;
logs?: boolean;
pullRequests?: boolean;
longRunning?: boolean;
};
};第一个实现不需要是托管的 SaaS。它可以针对已有的节点主机、临时工作区、CI 风格的运行器或 Testbox 风格环境。关键是契约:
- 准备工作区
- 绑定安全环境和秘密
- 启动运行
- 流式事件
- 收集产物
- 按策略清理或保留
一旦此契约稳定,托管的云服务可以实现相同提供者契约。
包结构
推荐的包:
| 包 | 用途 |
|---|---|
@openclaw/sdk | 公开的高级 SDK 和生成的低级 Gateway 客户端。 |
@openclaw/sdk-react | 可选的 React hooks,用于仪表盘和应用构建器。 |
@openclaw/sdk-testing | 测试助手和虚假 Gateway 服务器,用于应用集成测试。 |
仓库中已有 openclaw/plugin-sdk/* 用于插件。保持该命名空间独立,避免混淆插件作者和应用开发者。
生成客户端策略
低级客户端应从版本化 Gateway 协议 schema 生成,然后由手写的易用类包装。
分层:
- Gateway schema 真相源。
- 生成的低级 TypeScript 客户端。
- 外部输入和事件载荷的运行时验证器。
- 高级
OpenClaw、Agent、Session、Run、Task和Artifact包装器。 - 示例代码和集成测试。
好处:
- 协议漂移可见
- 测试可以比较生成方法和 Gateway 导出
- App SDK 保持独立于 Plugin SDK 内部
- 低级消费者仍有完整协议访问
- 高级消费者获得精简的产品 API
常见问题
OpenClaw SDK 和 Plugin SDK 有什么区别?
@openclaw/sdk 是面向外部应用的客户端包,用于与 Gateway 通信;openclaw/plugin-sdk/* 是进程内插件创作契约。应用开发者只应使用 App SDK,不要导入 Plugin SDK 的子路径。
审批事件怎么在 SDK 中处理?
通过 run.onApproval() 注册回调,根据 request.kind 和 request.toolName 决定批准、驳回或转交用户。审批事件会携带风险等级、过期时间和可用决策,支持 approveOnce 或 askUser。提问与审批分离,提问用于获取信息,审批用于获取许可。
Token 作用域的核心限制有哪些?
默认不转发秘密、不无限制传递环境变量,使用秘密引用而非值。关键限制:approval.respond 作用域才能响应审批,environment.write 用于创建/销毁环境,admin 用于管理操作。原始运行时事件在离开 Gateway 前会被编辑,除非调用者具有更强的诊断范围。