RPC and API
OpenClaw アプリ SDK API の設計
このページは、公開 OpenClaw App SDK の詳細な API リファレンス設計です。これは意図的に Plugin SDK とは分けられています。
公開 app SDK は 2 つの層で構築する必要があります。
- 低レベルの生成された Gateway クライアント。
OpenClaw、Agent、Session、Run、Task、Artifact、Approval、Environmentオブジェクトを備えた、高レベルで使いやすいラッパー。
名前空間設計
低レベルの名前空間は Gateway リソースに密接に従う必要があります。
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(); // future API: current SDK throws unsupported
oc.tasks.get(taskId); // future API: current SDK throws unsupported
oc.tasks.cancel(taskId); // future API: current SDK throws unsupported
oc.tasks.events(taskId, { after }); // future 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(...); // future API: current SDK throws unsupported
oc.environments.status(environmentId);
oc.environments.delete(environmentId); // future API: current SDK throws unsupported
高レベルのラッパーは、一般的なフローを快適にするオブジェクトを返す必要があります。
const run = await agent.run(inputOrParams);
await run.cancel();
await run.wait();
for await (const event of run.events()) {
// normalized event stream
}
const artifacts = await run.artifacts.list();
const session = await run.session();
イベント契約
公開 SDK は、バージョン管理され、再生可能で、正規化されたイベントを公開する必要があります。
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 が受け付けられた。 |
run.queued |
Run がセッションレーン、ランタイム、または環境を待っている。 |
run.started |
ランタイムが実行を開始した。 |
run.completed |
Run が正常に終了した。 |
run.failed |
Run がエラーで終了した。 |
run.cancelled |
Run がキャンセルされた。 |
run.timed_out |
Run がタイムアウトを超過した。 |
assistant.delta |
アシスタントテキストの差分。 |
assistant.message |
完全なアシスタントメッセージまたは置換。 |
thinking.delta |
ポリシーで公開が許可されている場合の推論または計画の差分。 |
tool.call.started |
ツール呼び出しが開始された。 |
tool.call.delta |
ツール呼び出しが進捗または部分出力をストリーミングした。 |
tool.call.completed |
ツール呼び出しが正常に返された。 |
tool.call.failed |
ツール呼び出しが失敗した。 |
approval.requested |
Run またはツールが承認を必要としている。 |
approval.resolved |
承認が許可、拒否、期限切れ、またはキャンセルされた。 |
question.requested |
ランタイムがユーザーまたはホストアプリに入力を求めた。 |
question.answered |
ホストアプリが回答を提供した。 |
artifact.created |
新しいアーティファクトが利用可能になった。 |
artifact.updated |
既存のアーティファクトが変更された。 |
session.created |
セッションが作成された。 |
session.updated |
セッションメタデータが変更された。 |
session.compacted |
セッション Compaction が発生した。 |
task.updated |
バックグラウンドタスクの状態が変更された。 |
git.branch |
ランタイムがブランチ状態を観測または変更した。 |
git.diff |
ランタイムが diff を生成または変更した。 |
git.pr |
ランタイムがプルリクエストを開く、更新、またはリンクした。 |
ランタイムネイティブのペイロードは raw から利用できる必要がありますが、通常の UI ではアプリが raw を解析しなくてもよいようにする必要があります。
結果契約
Run.wait() は安定した結果エンベロープを返す必要があります。
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 の形を保持するため、現在のライフサイクルに裏付けられた Run は通常エポックミリ秒の数値を報告しますが、アダプターは引き続き ISO 文字列を公開する場合があります。リッチな UI、ツールトレース、ランタイムネイティブの詳細は、イベントとアーティファクトに属します。
accepted は非終端の wait 結果です。これは、Run がライフサイクルの終了/エラーを生成する前に Gateway の wait 期限が切れたことを意味します。timed_out として扱ってはいけません。timed_out は、Run が自身のランタイムタイムアウトを超過した場合のために予約されています。
承認と質問
コーディングエージェントは常に安全境界を越えるため、承認は第一級である必要があります。
run.onApproval(async (request) => {
if (request.kind === "tool" && request.toolName === "exec") {
return request.approveOnce({ reason: "CI command allowed by policy" });
}
return request.askUser();
});
承認イベントには以下を含める必要があります。
- 承認 ID
- Run ID とセッション ID
- リクエスト種別
- 要求されたアクションの概要
- ツール名または環境アクション
- リスクレベル
- 利用可能な判断
- 有効期限
- 判断を再利用できるかどうか
質問は承認とは別です。質問は、ユーザーまたはホストアプリに情報を求めます。承認は、アクションを実行する許可を求めます。
ToolSpace モデル
アプリは Plugin 内部をインポートせずにツールサーフェスを理解する必要があります。
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
- スキーマ概要
- 承認ポリシー
- ランタイム互換性
- ツールが hidden、readonly、write capable、または host capable かどうか
SDK 経由のツール呼び出しは、明示的でスコープ付きである必要があります。ほとんどのアプリは任意のツールを直接呼び出すのではなく、エージェントを実行するべきです。
アーティファクトモデル
アーティファクトはファイル以上のものを扱う必要があります。
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 diff
- スクリーンショットとメディア出力
- ログとトレースバンドル
- プルリクエストリンク
- ランタイム軌跡
- 管理対象環境のワークスペーススナップショット
アーティファクトアクセスは、すべてのアーティファクトが通常のローカルファイルであると仮定せずに、リダクション、保持、ダウンロード URL をサポートする必要があります。
セキュリティモデル
app SDK は権限について明示的でなければなりません。
推奨されるトークンスコープ:
| スコープ | 許可すること |
|---|---|
agent.read |
エージェントの一覧表示と検査。 |
agent.run |
Run の開始。 |
session.read |
セッションメタデータとメッセージの読み取り。 |
session.write |
セッションの作成、送信、fork、compact、中止。 |
task.read |
バックグラウンドタスク状態の読み取り。 |
task.write |
タスク通知ポリシーのキャンセルまたは変更。 |
approval.respond |
リクエストの承認または拒否。 |
tools.invoke |
公開されたツールの直接呼び出し。 |
artifacts.read |
アーティファクトの一覧表示とダウンロード。 |
environment.write |
管理対象環境の作成または破棄。 |
admin |
管理操作。 |
デフォルト:
- デフォルトではシークレットを転送しない
- 無制限の環境変数パススルーを行わない
- シークレット値の代わりにシークレット参照を使う
- 明示的なサンドボックスとネットワークポリシー
- 明示的なリモート環境保持
- ポリシーで別途証明されない限り、ホスト実行には承認を要求する
- 呼び出し元がより強い診断スコープを持たない限り、Gateway を離れる前に raw ランタイムイベントをリダクションする
管理対象環境プロバイダー
管理対象エージェントは環境プロバイダーとして実装する必要があります。
type EnvironmentProvider = {
id: string;
capabilities: {
checkout?: boolean;
sandbox?: boolean;
networkPolicy?: boolean;
secrets?: boolean;
artifacts?: boolean;
logs?: boolean;
pullRequests?: boolean;
longRunning?: boolean;
};
};
最初の実装は hosted SaaS である必要はありません。既存の Node ホスト、一時的なワークスペース、CI スタイルの runner、または Testbox スタイルの環境を対象にできます。重要な契約は次のとおりです。
- ワークスペースを準備する
- 安全な環境とシークレットをバインドする
- Run を開始する
- イベントをストリーミングする
- アーティファクトを収集する
- ポリシーに従ってクリーンアップまたは保持する
これが安定すれば、hosted cloud service は同じプロバイダー契約を実装できます。
パッケージ構造
推奨パッケージ:
| パッケージ | 目的 |
|---|---|
@openclaw/sdk |
公開高レベル SDK と生成された低レベル Gateway クライアント。 |
@openclaw/sdk-react |
ダッシュボードと app builder 向けの任意の React hooks。 |
@openclaw/sdk-testing |
app integration 向けのテストヘルパーと fake Gateway server。 |
このリポジトリにはすでに Plugin 用の openclaw/plugin-sdk/* があります。Plugin 作成者とアプリ開発者を混同させないように、その名前空間は分けておいてください。
生成クライアント戦略
低レベルクライアントは、バージョン管理された Gateway プロトコルスキーマから生成し、その後、手書きの使いやすいクラスでラップする必要があります。
レイヤリング:
- Gateway スキーマの信頼できる唯一の情報源。
- 生成された低レベル TypeScript クライアント。
- 外部入力とイベントペイロード用のランタイムバリデーター。
- 高レベルの
OpenClaw、Agent、Session、Run、Task、Artifactラッパー。 - クックブックの例と統合テスト。
利点:
- プロトコルのずれが可視化される
- テストで生成されたメソッドと Gateway のエクスポートを比較できる
- App SDK は Plugin SDK の内部実装から独立したままになる
- 低レベルの利用者も完全なプロトコルアクセスを維持できる
- 高レベルの利用者は小さなプロダクト API を利用できる