Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
132
docs/plugins/adding-capabilities.md
Normal file
132
docs/plugins/adding-capabilities.md
Normal file
@@ -0,0 +1,132 @@
|
||||
---
|
||||
summary: "Contributor guide for adding a new shared capability to the OpenClaw plugin system"
|
||||
read_when:
|
||||
- Adding a new core capability and plugin registration surface
|
||||
- Deciding whether code belongs in core, a vendor plugin, or a feature plugin
|
||||
- Wiring a new runtime helper for channels or tools
|
||||
title: "Adding capabilities (contributor guide)"
|
||||
sidebarTitle: "Adding capabilities"
|
||||
---
|
||||
|
||||
<Info>
|
||||
This is a **contributor guide** for OpenClaw core developers. If you are
|
||||
building an external plugin, see [Building plugins](/plugins/building-plugins)
|
||||
instead. For the deep architecture reference (capability model, ownership,
|
||||
load pipeline, runtime helpers), see [Plugin internals](/plugins/architecture).
|
||||
</Info>
|
||||
|
||||
Use this when OpenClaw needs a new shared domain such as embeddings, image
|
||||
generation, video generation, or some future vendor-backed feature area.
|
||||
|
||||
The rule:
|
||||
|
||||
- **plugin** = ownership boundary
|
||||
- **capability** = shared core contract
|
||||
|
||||
Do not wire a vendor directly into a channel or a tool. Define the capability first.
|
||||
|
||||
## When to create a capability
|
||||
|
||||
Create a new capability only when **all** of these are true:
|
||||
|
||||
1. More than one vendor could plausibly implement it.
|
||||
2. Channels, tools, or feature plugins should consume it without caring about the vendor.
|
||||
3. Core needs to own fallback, policy, config, or delivery behavior.
|
||||
|
||||
If the work is vendor-only and no shared contract exists yet, define the contract first.
|
||||
|
||||
## The standard sequence
|
||||
|
||||
1. Define the typed core contract.
|
||||
2. Add plugin registration for that contract.
|
||||
3. Add a shared runtime helper.
|
||||
4. Wire one real vendor plugin as proof.
|
||||
5. Move feature/channel consumers onto the runtime helper.
|
||||
6. Add contract tests.
|
||||
7. Document the operator-facing config and ownership model.
|
||||
|
||||
## What goes where
|
||||
|
||||
| Layer | Owns |
|
||||
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Core** | Request/response types; provider registry and resolution; fallback behavior; config schema with propagated `title`/`description` docs metadata on nested object, wildcard, array-item, and composition nodes; runtime helper surface. |
|
||||
| **Vendor plugin** | Vendor API calls, vendor auth handling, vendor-specific request normalization, and registration of the capability implementation. |
|
||||
| **Feature/channel plugin** | Calls `api.runtime.*` or the matching `plugin-sdk/*-runtime` helper. Never calls a vendor implementation directly. |
|
||||
|
||||
## Provider and harness seams
|
||||
|
||||
Use **provider hooks** when the behavior belongs to the model provider contract rather than the generic agent loop. Examples include provider-specific request params after transport selection, auth-profile preference, prompt overlays, and follow-up fallback routing after model/profile failover.
|
||||
|
||||
Use **agent harness hooks** when the behavior belongs to the runtime that is executing a turn. Harnesses can classify explicit protocol outcomes such as empty output, reasoning without visible output, or a structured plan without a final answer so the outer model fallback policy can make the retry decision.
|
||||
|
||||
Keep both seams narrow:
|
||||
|
||||
- Core owns the retry/fallback policy.
|
||||
- Provider plugins own provider-specific request/auth/routing hints.
|
||||
- Harness plugins own runtime-specific attempt classification.
|
||||
- Third-party plugins return hints, not direct mutations of core state.
|
||||
|
||||
## File checklist
|
||||
|
||||
For a new capability, expect to touch these areas:
|
||||
|
||||
- `src/<capability>/types.ts`
|
||||
- `src/<capability>/...registry/runtime.ts`
|
||||
- `src/plugins/types.ts`
|
||||
- `src/plugins/registry.ts`
|
||||
- `src/plugins/captured-registration.ts`
|
||||
- `src/plugins/contracts/registry.ts`
|
||||
- `src/plugins/runtime/types-core.ts`
|
||||
- `src/plugins/runtime/index.ts`
|
||||
- `src/plugin-sdk/<capability>.ts`
|
||||
- `src/plugin-sdk/<capability>-runtime.ts`
|
||||
- One or more bundled plugin packages.
|
||||
- Config, docs, tests.
|
||||
|
||||
## Worked example: image generation
|
||||
|
||||
Image generation follows the standard shape:
|
||||
|
||||
1. Core defines `ImageGenerationProvider`.
|
||||
2. Core exposes `registerImageGenerationProvider(...)`.
|
||||
3. Core exposes `api.runtime.imageGeneration.generate(...)` and `.listProviders(...)`.
|
||||
4. Vendor plugins (`comfy`, `deepinfra`, `fal`, `google`, `litellm`, `microsoft-foundry`, `minimax`, `openai`, `openrouter`, `vydra`, `xai`) register vendor-backed implementations.
|
||||
5. Future vendors register the same contract without changing channels/tools.
|
||||
|
||||
The config key is intentionally separate from vision-analysis routing:
|
||||
|
||||
- `agents.defaults.imageModel` analyzes images.
|
||||
- `agents.defaults.imageGenerationModel` generates images.
|
||||
|
||||
Keep those separate so fallback and policy remain explicit.
|
||||
|
||||
## Embedding providers
|
||||
|
||||
Use `registerEmbeddingProvider(...)` / contract `embeddingProviders` for
|
||||
reusable vector embedding providers. This contract is intentionally broader
|
||||
than memory: tools, search, retrieval, importers, or future feature plugins
|
||||
can consume embeddings without depending on the memory engine. Memory search
|
||||
also consumes generic `embeddingProviders`.
|
||||
|
||||
The older memory-specific registration API and `memoryEmbeddingProviders`
|
||||
contract are deprecated. Use `registerEmbeddingProvider` and
|
||||
`embeddingProviders` for all new embedding providers.
|
||||
|
||||
## Review checklist
|
||||
|
||||
Before shipping a new capability, verify:
|
||||
|
||||
- No channel/tool imports vendor code directly.
|
||||
- The runtime helper is the shared path.
|
||||
- At least one contract test asserts bundled ownership.
|
||||
- Config docs name the new model/config key.
|
||||
- Plugin docs explain the ownership boundary.
|
||||
|
||||
If a PR skips the capability layer and hardcodes vendor behavior into a channel/tool, send it back and define the contract first.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin internals](/plugins/architecture) — capability model, ownership, load pipeline, runtime helpers.
|
||||
- [Building plugins](/plugins/building-plugins) — first-plugin tutorial.
|
||||
- [SDK overview](/plugins/sdk-overview) — import map and registration API reference.
|
||||
- [Creating skills](/tools/creating-skills) — companion contributor surface.
|
||||
224
docs/plugins/admin-http-rpc.md
Normal file
224
docs/plugins/admin-http-rpc.md
Normal file
@@ -0,0 +1,224 @@
|
||||
---
|
||||
summary: "Expose selected Gateway control-plane methods through the bundled, opt-in admin-http-rpc plugin"
|
||||
read_when:
|
||||
- Building host tooling that cannot use the Gateway WebSocket RPC client
|
||||
- Exposing Gateway admin automation behind a private trusted ingress
|
||||
- Auditing the security model for HTTP access to Gateway methods
|
||||
title: "Admin HTTP RPC plugin"
|
||||
---
|
||||
|
||||
The bundled `admin-http-rpc` plugin exposes an allowlisted set of Gateway control-plane methods over HTTP, for trusted host automation that cannot keep a Gateway WebSocket connection open.
|
||||
|
||||
It ships with OpenClaw but is disabled by default; when disabled, the route is not registered. When enabled, it adds `POST /api/v1/admin/rpc` on the same listener as the Gateway (`http://<gateway-host>:<port>/api/v1/admin/rpc`).
|
||||
|
||||
Enable it only for private host tooling, tailnet automation, or a trusted internal ingress. Never expose this route directly to the public internet.
|
||||
|
||||
## Before you enable it
|
||||
|
||||
Admin HTTP RPC is a full operator control-plane surface: any caller that passes Gateway HTTP auth can invoke the allowlisted methods below. Enable it only when all of these are true:
|
||||
|
||||
- The caller is trusted to operate the Gateway.
|
||||
- The caller cannot use the WebSocket RPC client.
|
||||
- The route is reachable only on loopback, a tailnet, or a private authenticated ingress.
|
||||
- You have reviewed the allowed methods and they match the automation you plan to run.
|
||||
|
||||
For OpenClaw clients and interactive tools that can keep a Gateway WebSocket connection open, use WebSocket RPC instead.
|
||||
|
||||
## Enable
|
||||
|
||||
Enable the bundled plugin:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="CLI">
|
||||
```bash
|
||||
openclaw plugins enable admin-http-rpc
|
||||
openclaw gateway restart
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Config">
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"admin-http-rpc": { enabled: true },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
The route is registered during plugin startup, so restart the Gateway after changing plugin config.
|
||||
|
||||
Disable it when you no longer need the HTTP surface:
|
||||
|
||||
```bash
|
||||
openclaw plugins disable admin-http-rpc
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
## Verify the route
|
||||
|
||||
Use `health` as the smallest safe request:
|
||||
|
||||
```bash
|
||||
curl -sS http://<gateway-host>:<port>/api/v1/admin/rpc \
|
||||
-H 'Authorization: Bearer <gateway-token>' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"method":"health","params":{}}'
|
||||
```
|
||||
|
||||
A successful response has `ok: true`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "generated-request-id",
|
||||
"ok": true,
|
||||
"payload": {
|
||||
"status": "ok"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When the plugin is disabled, the route returns `404` because it is not registered.
|
||||
|
||||
## Authentication
|
||||
|
||||
The plugin route uses Gateway HTTP auth.
|
||||
|
||||
Common authentication paths:
|
||||
|
||||
- shared-secret auth (`gateway.auth.mode="token"` or `"password"`): `Authorization: Bearer <token-or-password>`
|
||||
- trusted identity-bearing HTTP auth (`gateway.auth.mode="trusted-proxy"`): route through the configured identity-aware proxy and let it inject the required identity headers
|
||||
- private-ingress open auth (`gateway.auth.mode="none"`): no auth header required
|
||||
|
||||
## Security model
|
||||
|
||||
Treat this plugin as a full Gateway operator surface.
|
||||
|
||||
- Enabling the plugin intentionally offers access to the allowlisted admin RPC methods at `/api/v1/admin/rpc`.
|
||||
- The plugin declares the reserved `contracts.gatewayMethodDispatch: ["authenticated-request"]` manifest contract, which is what lets its Gateway-authenticated HTTP route dispatch control-plane methods in process. This is not a sandbox: the contract prevents accidental use of reserved SDK helpers, but trusted plugins still run in the Gateway process.
|
||||
- Shared-secret bearer auth (`token`/`password` modes) proves possession of the gateway operator secret; narrower `x-openclaw-scopes` headers are ignored on that path and normal full operator defaults are restored.
|
||||
- Trusted identity-bearing HTTP auth (`trusted-proxy` mode) honors `x-openclaw-scopes` when present.
|
||||
- `gateway.auth.mode="none"` means this route is unauthenticated if the plugin is enabled. Use that only behind a private ingress you fully trust.
|
||||
- Requests dispatch through the same Gateway method handlers and scope checks as WebSocket RPC, after the plugin route auth passes.
|
||||
- Keep this route on loopback, tailnet, or a private trusted ingress. Do not expose it directly to the public internet. Use separate gateways when callers cross trust boundaries.
|
||||
|
||||
## Request
|
||||
|
||||
```http
|
||||
POST /api/v1/admin/rpc
|
||||
Authorization: Bearer <gateway-token>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "optional-request-id",
|
||||
"method": "health",
|
||||
"params": {}
|
||||
}
|
||||
```
|
||||
|
||||
Fields:
|
||||
|
||||
- `id` (string, optional): copied into the response. A UUID is generated when omitted.
|
||||
- `method` (string, required): allowed Gateway method name.
|
||||
- `params` (any, optional): method-specific params.
|
||||
|
||||
The default max request body size is 1 MB.
|
||||
|
||||
## Response
|
||||
|
||||
Success responses use the Gateway RPC shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "optional-request-id",
|
||||
"ok": true,
|
||||
"payload": {}
|
||||
}
|
||||
```
|
||||
|
||||
Gateway method errors use:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "optional-request-id",
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "INVALID_REQUEST",
|
||||
"message": "bad params"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
HTTP status follows the error code:
|
||||
|
||||
| Error code | HTTP status |
|
||||
| -------------------------- | ----------- |
|
||||
| `INVALID_REQUEST` | 400 |
|
||||
| `APPROVAL_NOT_FOUND` | 404 |
|
||||
| `NOT_LINKED`, `NOT_PAIRED` | 409 |
|
||||
| `UNAVAILABLE` | 503 |
|
||||
| `AGENT_TIMEOUT` | 504 |
|
||||
| any other code | 500 |
|
||||
|
||||
## Allowed methods
|
||||
|
||||
- discovery: `commands.list`
|
||||
Returns the HTTP RPC method names allowed by this plugin.
|
||||
- gateway: `health`, `status`, `logs.tail`, `usage.status`, `usage.cost`, `gateway.restart.request`
|
||||
- config: `config.get`, `config.schema`, `config.schema.lookup`, `config.set`, `config.patch`, `config.apply`
|
||||
- channels: `channels.status`, `channels.start`, `channels.stop`, `channels.logout`
|
||||
- web: `web.login.start`, `web.login.wait`
|
||||
- models: `models.list`, `models.authStatus`
|
||||
- agents: `agents.list`, `agents.create`, `agents.update`, `agents.delete`
|
||||
- approvals: `exec.approvals.get`, `exec.approvals.set`, `exec.approvals.node.get`, `exec.approvals.node.set`
|
||||
- cron: `cron.status`, `cron.list`, `cron.get`, `cron.runs`, `cron.add`, `cron.update`, `cron.remove`, `cron.run`
|
||||
- devices: `device.pair.list`, `device.pair.approve`, `device.pair.reject`, `device.pair.remove`
|
||||
- nodes: `node.list`, `node.describe`, `node.pair.list`, `node.pair.approve`, `node.pair.reject`, `node.pair.remove`, `node.rename`
|
||||
- tasks: `tasks.list`, `tasks.get`, `tasks.cancel`
|
||||
- diagnostics: `doctor.memory.status`, `update.status`
|
||||
|
||||
Other Gateway methods are blocked until they are intentionally added.
|
||||
|
||||
## WebSocket comparison
|
||||
|
||||
The normal Gateway WebSocket RPC path remains the preferred control-plane API for OpenClaw clients. Use admin HTTP RPC only for host tooling that needs a request/response HTTP surface.
|
||||
|
||||
Shared-token WebSocket clients without a trusted device identity cannot self-declare admin scopes during connect. Admin HTTP RPC deliberately follows the existing trusted HTTP operator model: when the plugin is enabled, shared-secret bearer auth is treated as full operator access for this admin surface.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
`404 Not Found`
|
||||
|
||||
: The plugin is disabled, the Gateway has not restarted since enabling it, or the request is going to a different Gateway process.
|
||||
|
||||
`401 Unauthorized`
|
||||
|
||||
: The request did not satisfy Gateway HTTP auth. Check the bearer token or the trusted-proxy identity headers.
|
||||
|
||||
`405 Method Not Allowed`
|
||||
|
||||
: The request used something other than `POST`.
|
||||
|
||||
`413 Payload Too Large`
|
||||
|
||||
: The request body exceeded the 1 MB limit.
|
||||
|
||||
`400 INVALID_REQUEST`
|
||||
|
||||
: The request body is not valid JSON, the `method` field is missing, or the method is not in the plugin allowlist.
|
||||
|
||||
`503 UNAVAILABLE`
|
||||
|
||||
: The Gateway method handler is unavailable. Check Gateway logs and retry after the Gateway finishes startup.
|
||||
|
||||
## Related
|
||||
|
||||
- [Operator scopes](/gateway/operator-scopes)
|
||||
- [Gateway security](/gateway/security)
|
||||
- [Remote access](/gateway/remote)
|
||||
- [Plugin manifest](/plugins/manifest#contracts-reference)
|
||||
- [SDK subpaths](/plugins/sdk-subpaths)
|
||||
13
docs/plugins/agent-tools.md
Normal file
13
docs/plugins/agent-tools.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
summary: "Redirects to Building Plugins (registering tools section)"
|
||||
read_when:
|
||||
- Legacy link to agent-tools
|
||||
title: "Registering tools"
|
||||
---
|
||||
|
||||
This page has moved. See [Building Plugins: Registering agent tools](/plugins/building-plugins#registering-agent-tools).
|
||||
|
||||
## Related
|
||||
|
||||
- [Building plugins](/plugins/building-plugins)
|
||||
- [Plugin SDK setup](/plugins/sdk-setup)
|
||||
1224
docs/plugins/architecture-internals.md
Normal file
1224
docs/plugins/architecture-internals.md
Normal file
File diff suppressed because it is too large
Load Diff
483
docs/plugins/architecture.md
Normal file
483
docs/plugins/architecture.md
Normal file
@@ -0,0 +1,483 @@
|
||||
---
|
||||
summary: "Plugin internals: capability model, ownership, contracts, load pipeline, and runtime helpers"
|
||||
read_when:
|
||||
- Building or debugging native OpenClaw plugins
|
||||
- Understanding the plugin capability model or ownership boundaries
|
||||
- Working on the plugin load pipeline or registry
|
||||
- Implementing provider runtime hooks or channel plugins
|
||||
title: "Plugin internals"
|
||||
sidebarTitle: "Internals"
|
||||
---
|
||||
|
||||
This is the **deep architecture reference** for the OpenClaw plugin system. For practical guides, start with one of the focused pages below.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Install and use plugins" icon="plug" href="/tools/plugin">
|
||||
End-user guide for adding, enabling, and troubleshooting plugins.
|
||||
</Card>
|
||||
<Card title="Building plugins" icon="rocket" href="/plugins/building-plugins">
|
||||
First-plugin tutorial with the smallest working manifest.
|
||||
</Card>
|
||||
<Card title="Channel plugins" icon="comments" href="/plugins/sdk-channel-plugins">
|
||||
Build a messaging channel plugin.
|
||||
</Card>
|
||||
<Card title="Provider plugins" icon="microchip" href="/plugins/sdk-provider-plugins">
|
||||
Build a model provider plugin.
|
||||
</Card>
|
||||
<Card title="SDK overview" icon="book" href="/plugins/sdk-overview">
|
||||
Import map and registration API reference.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Public capability model
|
||||
|
||||
Capabilities are the public **native plugin** model inside OpenClaw. Every native OpenClaw plugin registers against one or more capability types:
|
||||
|
||||
| Capability | Registration method | Example plugins |
|
||||
| ---------------------- | ------------------------------------------------ | ------------------------------ |
|
||||
| Text inference | `api.registerProvider(...)` | `anthropic`, `openai` |
|
||||
| CLI inference backend | `api.registerCliBackend(...)` | `anthropic`, `openai` |
|
||||
| Embeddings | `api.registerEmbeddingProvider(...)` | Provider-owned vector plugins |
|
||||
| Speech | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` |
|
||||
| Realtime transcription | `api.registerRealtimeTranscriptionProvider(...)` | `openai` |
|
||||
| Realtime voice | `api.registerRealtimeVoiceProvider(...)` | `google`, `openai` |
|
||||
| Media understanding | `api.registerMediaUnderstandingProvider(...)` | `google`, `openai` |
|
||||
| Transcripts source | `api.registerTranscriptSourceProvider(...)` | `discord` |
|
||||
| Image generation | `api.registerImageGenerationProvider(...)` | `fal`, `google`, `openai` |
|
||||
| Music generation | `api.registerMusicGenerationProvider(...)` | `fal`, `google`, `minimax` |
|
||||
| Video generation | `api.registerVideoGenerationProvider(...)` | `fal`, `google`, `qwen` |
|
||||
| Web fetch | `api.registerWebFetchProvider(...)` | `firecrawl` |
|
||||
| Web search | `api.registerWebSearchProvider(...)` | `brave`, `firecrawl`, `google` |
|
||||
| Channel / messaging | `api.registerChannel(...)` | `matrix`, `msteams` |
|
||||
| Gateway discovery | `api.registerGatewayDiscoveryService(...)` | `bonjour` |
|
||||
|
||||
<Note>
|
||||
A plugin that registers zero capabilities but provides hooks, tools, discovery services, or background services is a **legacy hook-only** plugin. That pattern is still fully supported.
|
||||
</Note>
|
||||
|
||||
### External compatibility stance
|
||||
|
||||
The capability model is landed in core and used by bundled/native plugins today, but external plugin compatibility still needs a tighter bar than "it is exported, therefore it is frozen."
|
||||
|
||||
| Plugin situation | Guidance |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| Existing external plugins | Keep hook-based integrations working; this is the compatibility baseline. |
|
||||
| New bundled/native plugins | Prefer explicit capability registration over vendor-specific reach-ins or new hook-only designs. |
|
||||
| External plugins adopting capability registration | Allowed, but treat capability-specific helper surfaces as evolving unless docs mark them stable. |
|
||||
|
||||
Capability registration is the intended direction. Legacy hooks remain the safest no-breakage path for external plugins during the transition. Exported helper subpaths are not all equal — prefer narrow documented contracts over incidental helper exports.
|
||||
|
||||
### Plugin shapes
|
||||
|
||||
OpenClaw classifies every loaded plugin into a shape based on its actual registration behavior (not just static metadata):
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="plain-capability">
|
||||
Registers exactly one capability type (for example a provider-only plugin like `arcee` or `chutes`).
|
||||
</Accordion>
|
||||
<Accordion title="hybrid-capability">
|
||||
Registers multiple capability types (for example `openai` owns text inference, speech, media understanding, and image generation).
|
||||
</Accordion>
|
||||
<Accordion title="hook-only">
|
||||
Registers only hooks (typed or custom), no capabilities, tools, commands, or services.
|
||||
</Accordion>
|
||||
<Accordion title="non-capability">
|
||||
Registers tools, commands, services, or routes but no capabilities.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Use `openclaw plugins inspect <id>` to see a plugin's shape and capability breakdown. See [CLI reference](/cli/plugins#inspect) for details.
|
||||
|
||||
### Legacy hooks
|
||||
|
||||
The `before_agent_start` hook remains supported as a compatibility path for hook-only plugins. Legacy real-world plugins still depend on it.
|
||||
|
||||
Direction:
|
||||
|
||||
- keep it working
|
||||
- document it as legacy
|
||||
- prefer `before_model_resolve` for model/provider override work
|
||||
- prefer `before_prompt_build` for prompt mutation work
|
||||
- remove only after real usage drops and fixture coverage proves migration safety
|
||||
|
||||
### Compatibility signals
|
||||
|
||||
`openclaw doctor`, `openclaw plugins inspect <id>`, `openclaw status --all`, and `openclaw plugins doctor` surface these compatibility notices:
|
||||
|
||||
| Signal | Meaning |
|
||||
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
|
||||
| **config valid** | Config parses fine and plugins resolve |
|
||||
| **hook-only** (info) | Plugin registers only hooks; a supported path, but not migrated to capability registration yet |
|
||||
| **legacy `before_agent_start`** (warn) | Plugin uses the deprecated `before_agent_start` hook instead of `before_model_resolve`/`before_prompt_build` |
|
||||
| **deprecated memory-embedding API** (warn) | Non-bundled plugin uses the old memory-specific embedding provider API instead of `registerEmbeddingProvider` |
|
||||
| **hard error** | Config is invalid or plugin failed to load |
|
||||
|
||||
None of the advisory/warn signals break your plugin today. These signals also appear in `openclaw status --all` and `openclaw plugins doctor`.
|
||||
|
||||
## Architecture overview
|
||||
|
||||
OpenClaw's plugin system has four layers:
|
||||
|
||||
<Steps>
|
||||
<Step title="Manifest + discovery">
|
||||
OpenClaw finds candidate plugins from configured paths, workspace roots, global plugin roots, and bundled plugins. Discovery reads native `openclaw.plugin.json` manifests plus supported bundle manifests first.
|
||||
</Step>
|
||||
<Step title="Enablement + validation">
|
||||
Core decides whether a discovered plugin is enabled, disabled, blocked, or selected for an exclusive slot such as memory.
|
||||
</Step>
|
||||
<Step title="Runtime loading">
|
||||
Native OpenClaw plugins are loaded in-process and register capabilities into a central registry. Packaged JavaScript loads through native `require`; third-party local source TypeScript is the emergency Jiti fallback. Compatible bundles are normalized into registry records without importing runtime code.
|
||||
</Step>
|
||||
<Step title="Surface consumption">
|
||||
The rest of OpenClaw reads the registry to expose tools, channels, provider setup, hooks, HTTP routes, CLI commands, and services.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
For plugin CLI specifically, root command discovery is split in two phases:
|
||||
|
||||
- parse-time metadata comes from `registerCli(..., { descriptors: [...] })`
|
||||
- the real plugin CLI module can stay lazy and register on first invocation
|
||||
|
||||
That keeps plugin-owned CLI code inside the plugin while still letting OpenClaw reserve root command names before parsing.
|
||||
|
||||
The important design boundary:
|
||||
|
||||
- manifest/config validation should work from **manifest/schema metadata** without executing plugin code
|
||||
- native capability discovery may load trusted plugin entry code to build a non-activating registry snapshot
|
||||
- native runtime behavior comes from the plugin module's `register(api)` path with `api.registrationMode === "full"`
|
||||
|
||||
That split lets OpenClaw validate config, explain missing/disabled plugins, and build UI/schema hints before the full runtime is active.
|
||||
|
||||
### Plugin metadata snapshot and lookup table
|
||||
|
||||
Gateway startup builds one `PluginMetadataSnapshot` for the current config snapshot. The snapshot is metadata-only: it stores the installed plugin index, manifest registry, manifest diagnostics, owner maps, a plugin id normalizer, and manifest records. It does not hold loaded plugin modules, provider SDKs, package contents, or runtime exports.
|
||||
|
||||
Plugin-aware config validation, startup auto-enable, and Gateway plugin bootstrap consume that snapshot instead of rebuilding manifest/index metadata independently. `PluginLookUpTable` is derived from the same snapshot and adds the startup plugin plan for the current runtime config.
|
||||
|
||||
After startup, Gateway keeps the current metadata snapshot as a replaceable runtime product. Repeated runtime provider discovery can borrow that snapshot instead of reconstructing the installed index and manifest registry for each provider-catalog pass. The snapshot is cleared or replaced on Gateway shutdown, config/plugin inventory changes, and installed index writes; callers fall back to the cold manifest/index path when no compatible current snapshot exists. Compatibility checks must include plugin discovery roots such as `plugins.load.paths` and the default agent workspace, because workspace plugins are part of the metadata scope.
|
||||
|
||||
The snapshot and lookup table keep repeated startup decisions on the fast path:
|
||||
|
||||
- channel ownership
|
||||
- deferred channel startup
|
||||
- startup plugin ids
|
||||
- provider and CLI backend ownership
|
||||
- setup provider, command alias, model catalog provider, and manifest contract ownership
|
||||
- plugin config schema and channel config schema validation
|
||||
- startup auto-enable decisions
|
||||
|
||||
The safety boundary is snapshot replacement, not mutation. Rebuild the snapshot when config, plugin inventory, install records, or persisted index policy changes. Do not treat it as a broad mutable global registry, and do not keep unbounded historical snapshots. Runtime plugin loading remains separate from metadata snapshots so stale runtime state cannot be hidden behind a metadata cache.
|
||||
|
||||
The cache rule is documented in [Plugin architecture internals](/plugins/architecture-internals#plugin-cache-boundary): manifest and discovery metadata are fresh unless a caller holds an explicit snapshot, lookup table, or manifest registry for the current flow. Hidden metadata caches and wall-clock TTLs are not part of plugin loading. Only runtime loader, module, and dependency-artifact caches may persist after code or installed artifacts are actually loaded.
|
||||
|
||||
Some cold-path callers still reconstruct manifest registries directly from the persisted installed plugin index instead of receiving a Gateway `PluginLookUpTable`. That path now reconstructs the registry on demand; prefer passing the current lookup table or an explicit manifest registry through runtime flows when a caller already has one.
|
||||
|
||||
### Activation planning
|
||||
|
||||
Activation planning is part of the control plane. Callers can ask which plugins are relevant to a concrete command, provider, channel, route, agent harness, or capability before loading broader runtime registries.
|
||||
|
||||
The planner keeps current manifest behavior compatible:
|
||||
|
||||
- `activation.*` fields are explicit planner hints
|
||||
- `providers`, `channels`, `commandAliases`, `setup.providers`, `contracts.tools`, and hooks remain manifest ownership fallback
|
||||
- the ids-only planner API stays available for existing callers
|
||||
- the plan API reports reason labels so diagnostics can distinguish explicit hints from ownership fallback
|
||||
|
||||
<Warning>
|
||||
Do not treat `activation` as a lifecycle hook or a replacement for `register(...)`. It is metadata used to narrow loading. Prefer ownership fields when they already describe the relationship; use `activation` only for extra planner hints.
|
||||
</Warning>
|
||||
|
||||
### Channel plugins and the shared message tool
|
||||
|
||||
Channel plugins do not need to register a separate send/edit/react tool for normal chat actions. OpenClaw keeps one shared `message` tool in core, and channel plugins own the channel-specific discovery and execution behind it.
|
||||
|
||||
The current boundary is:
|
||||
|
||||
- core owns the shared `message` tool host, prompt wiring, session/thread bookkeeping, and execution dispatch
|
||||
- channel plugins own scoped action discovery, capability discovery, and any channel-specific schema fragments
|
||||
- channel plugins own provider-specific session conversation grammar, such as how conversation ids encode thread ids or inherit from parent conversations
|
||||
- channel plugins execute the final action through their action adapter
|
||||
|
||||
For channel plugins, the SDK surface is `ChannelMessageActionAdapter.describeMessageTool(...)`. That unified discovery call lets a plugin return its visible actions, capabilities, and schema contributions together so those pieces do not drift apart.
|
||||
|
||||
When a channel-specific message-tool param carries a media source such as a local path or remote media URL, the plugin should also return `mediaSourceParams` from `describeMessageTool(...)`. Core uses that explicit list to apply sandbox path normalization and outbound media-access hints without hardcoding plugin-owned param names. Prefer action-scoped maps there, not one channel-wide flat list, so a profile-only media param does not get normalized on unrelated actions like `send`.
|
||||
|
||||
Core passes runtime scope into that discovery step. Important fields include:
|
||||
|
||||
- `accountId`
|
||||
- `currentChannelId`
|
||||
- `currentThreadTs`
|
||||
- `currentMessageId`
|
||||
- `sessionKey`
|
||||
- `sessionId`
|
||||
- `agentId`
|
||||
- trusted inbound `requesterSenderId`
|
||||
|
||||
That matters for context-sensitive plugins. A channel can hide or expose message actions based on the active account, current room/thread/message, or trusted requester identity without hardcoding channel-specific branches in the core `message` tool.
|
||||
|
||||
This is why embedded-runner routing changes are still plugin work: the runner is responsible for forwarding the current chat/session identity into the plugin discovery boundary so the shared `message` tool exposes the right channel-owned surface for the current turn.
|
||||
|
||||
For channel-owned execution helpers, bundled plugins should keep the execution runtime inside their own plugin modules. Core no longer owns the Discord, Slack, Telegram, or WhatsApp message-action runtimes under `src/agents/tools`. We do not publish separate `plugin-sdk/*-action-runtime` subpaths, and bundled plugins should import their own local runtime code directly from their plugin-owned modules.
|
||||
|
||||
The same boundary applies to provider-named SDK seams in general: core should not import channel-specific convenience barrels for Discord, Signal, Slack, WhatsApp, or similar plugins. If core needs a behavior, either consume the bundled plugin's own `api.ts` / `runtime-api.ts` barrel or promote the need into a narrow generic capability in the shared SDK.
|
||||
|
||||
Bundled plugins follow the same rule. A bundled plugin's `runtime-api.ts` should not re-export its own branded `openclaw/plugin-sdk/<plugin-id>` facade. Those branded facades remain compatibility shims for external plugins and older consumers, but bundled plugins should use local exports plus narrow generic SDK subpaths such as `openclaw/plugin-sdk/channel-policy`, `openclaw/plugin-sdk/runtime-store`, or `openclaw/plugin-sdk/webhook-ingress`. New code should not add plugin-id-specific SDK facades unless the compatibility boundary for an existing external ecosystem requires it.
|
||||
|
||||
For polls specifically, there are two execution paths:
|
||||
|
||||
- `outbound.sendPoll` is the shared baseline for channels that fit the common poll model
|
||||
- `actions.handleAction("poll")` is the preferred path for channel-specific poll semantics or extra poll parameters
|
||||
|
||||
Core now defers shared poll parsing until after plugin poll dispatch declines the action, so plugin-owned poll handlers can accept channel-specific poll fields without being blocked by the generic poll parser first.
|
||||
|
||||
See [Plugin architecture internals](/plugins/architecture-internals) for the full startup sequence.
|
||||
|
||||
## Capability ownership model
|
||||
|
||||
OpenClaw treats a native plugin as the ownership boundary for a **company** or a **feature**, not as a grab bag of unrelated integrations.
|
||||
|
||||
That means:
|
||||
|
||||
- a company plugin should usually own all of that company's OpenClaw-facing surfaces
|
||||
- a feature plugin should usually own the full feature surface it introduces
|
||||
- channels should consume shared core capabilities instead of re-implementing provider behavior ad hoc
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Vendor multi-capability">
|
||||
`google` owns text inference, CLI backend, embeddings, speech, realtime voice, media understanding, image/music/video generation, and web search. `openai` owns text inference, embeddings, speech, realtime transcription, realtime voice, media understanding, image/video generation. `minimax` owns text inference plus media understanding, speech, image/music/video generation, and web search.
|
||||
</Accordion>
|
||||
<Accordion title="Vendor single-capability">
|
||||
`arcee` and `chutes` own text inference only; `microsoft` owns speech only. A vendor plugin can stay this narrow until it needs to cover more of that vendor's surface.
|
||||
</Accordion>
|
||||
<Accordion title="Feature plugin">
|
||||
`voice-call` owns call transport, tools, CLI, routes, and Twilio media-stream bridging, but consumes shared speech, realtime transcription, and realtime voice capabilities instead of importing vendor plugins directly.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
The intended end state is:
|
||||
|
||||
- a vendor's OpenClaw-facing surface lives in one plugin even if it spans text models, speech, images, and video
|
||||
- other vendors can do the same for their own surface area
|
||||
- channels do not care which vendor plugin owns the provider; they consume the shared capability contract exposed by core
|
||||
|
||||
This is the key distinction:
|
||||
|
||||
- **plugin** = ownership boundary
|
||||
- **capability** = core contract that multiple plugins can implement or consume
|
||||
|
||||
So if OpenClaw adds a new domain such as video, the first question is not "which provider should hardcode video handling?" The first question is "what is the core video capability contract?" Once that contract exists, vendor plugins can register against it and channel/feature plugins can consume it.
|
||||
|
||||
If the capability does not exist yet, the right move is usually:
|
||||
|
||||
<Steps>
|
||||
<Step title="Define the capability">
|
||||
Define the missing capability in core.
|
||||
</Step>
|
||||
<Step title="Expose through the SDK">
|
||||
Expose it through the plugin API/runtime in a typed way.
|
||||
</Step>
|
||||
<Step title="Wire consumers">
|
||||
Wire channels/features against that capability.
|
||||
</Step>
|
||||
<Step title="Vendor implementations">
|
||||
Let vendor plugins register implementations.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
This keeps ownership explicit while avoiding core behavior that depends on a single vendor or a one-off plugin-specific code path.
|
||||
|
||||
### Capability layering
|
||||
|
||||
Use this mental model when deciding where code belongs:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Core capability layer">
|
||||
Shared orchestration, policy, fallback, config merge rules, delivery semantics, and typed contracts.
|
||||
</Tab>
|
||||
<Tab title="Vendor plugin layer">
|
||||
Vendor-specific APIs, auth, model catalogs, speech synthesis, image generation, video backends, usage endpoints.
|
||||
</Tab>
|
||||
<Tab title="Channel/feature plugin layer">
|
||||
Discord/Slack/voice-call/etc. integration that consumes core capabilities and presents them on a surface.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
For example, TTS follows this shape:
|
||||
|
||||
- core owns reply-time TTS policy, fallback order, prefs, and channel delivery
|
||||
- `elevenlabs`, `google`, `microsoft`, and `openai` own synthesis implementations
|
||||
- `voice-call` consumes the telephony TTS runtime helper
|
||||
|
||||
That same pattern should be preferred for future capabilities.
|
||||
|
||||
### Multi-capability company plugin example
|
||||
|
||||
A company plugin should feel cohesive from the outside. If OpenClaw has shared contracts for models, speech, realtime transcription, realtime voice, media understanding, image generation, video generation, web fetch, and web search, a vendor can own all of its surfaces in one place:
|
||||
|
||||
```ts
|
||||
import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import {
|
||||
describeImageWithModel,
|
||||
transcribeOpenAiCompatibleAudio,
|
||||
} from "openclaw/plugin-sdk/media-understanding";
|
||||
import { createPluginBackedWebSearchProvider } from "openclaw/plugin-sdk/provider-web-search";
|
||||
|
||||
const plugin: OpenClawPluginDefinition = {
|
||||
id: "exampleai",
|
||||
name: "ExampleAI",
|
||||
register(api) {
|
||||
api.registerProvider({
|
||||
id: "exampleai",
|
||||
// auth/model catalog/runtime hooks
|
||||
});
|
||||
|
||||
api.registerSpeechProvider({
|
||||
id: "exampleai",
|
||||
// vendor speech config — implement the SpeechProviderPlugin interface directly
|
||||
});
|
||||
|
||||
api.registerMediaUnderstandingProvider({
|
||||
id: "exampleai",
|
||||
capabilities: ["image", "audio", "video"],
|
||||
async describeImage(req) {
|
||||
return describeImageWithModel({
|
||||
...req,
|
||||
provider: "exampleai",
|
||||
});
|
||||
},
|
||||
async transcribeAudio(req) {
|
||||
return transcribeOpenAiCompatibleAudio({
|
||||
...req,
|
||||
provider: "exampleai",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
api.registerWebSearchProvider(
|
||||
createPluginBackedWebSearchProvider({
|
||||
id: "exampleai-search",
|
||||
// credential + fetch logic
|
||||
}),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
```
|
||||
|
||||
What matters is not the exact helper names. The shape matters:
|
||||
|
||||
- one plugin owns the vendor surface
|
||||
- core still owns the capability contracts
|
||||
- channels and feature plugins consume `api.runtime.*` helpers, not vendor code
|
||||
- contract tests can assert that the plugin registered the capabilities it claims to own
|
||||
|
||||
### Capability example: video understanding
|
||||
|
||||
OpenClaw already treats image/audio/video understanding as one shared capability. The same ownership model applies there:
|
||||
|
||||
<Steps>
|
||||
<Step title="Core defines the contract">
|
||||
Core defines the media-understanding contract.
|
||||
</Step>
|
||||
<Step title="Vendor plugins register">
|
||||
Vendor plugins register `describeImage`, `transcribeAudio`, and `describeVideo` as applicable.
|
||||
</Step>
|
||||
<Step title="Consumers use the shared behavior">
|
||||
Channels and feature plugins consume the shared core behavior instead of wiring directly to vendor code.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That avoids baking one provider's video assumptions into core. The plugin owns the vendor surface; core owns the capability contract and fallback behavior.
|
||||
|
||||
Video generation already uses that same sequence: core owns the typed capability contract and runtime helper, and vendor plugins register `api.registerVideoGenerationProvider(...)` implementations against it.
|
||||
|
||||
Need a concrete rollout checklist? See [Capability Cookbook](/tools/capability-cookbook).
|
||||
|
||||
## Contracts and enforcement
|
||||
|
||||
The plugin API surface is intentionally typed and centralized in `OpenClawPluginApi`. That contract defines the supported registration points and the runtime helpers a plugin may rely on.
|
||||
|
||||
Why this matters:
|
||||
|
||||
- plugin authors get one stable internal standard
|
||||
- core can reject duplicate ownership such as two plugins registering the same provider id
|
||||
- startup can surface actionable diagnostics for malformed registration
|
||||
- contract tests can enforce bundled-plugin ownership and prevent silent drift
|
||||
|
||||
There are two layers of enforcement:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Runtime registration enforcement">
|
||||
The plugin registry validates registrations as plugins load. Examples: duplicate provider ids, duplicate speech provider ids, and malformed registrations produce plugin diagnostics instead of undefined behavior.
|
||||
</Accordion>
|
||||
<Accordion title="Contract tests">
|
||||
Bundled plugins are captured in contract registries during test runs so OpenClaw can assert ownership explicitly. Today this is used for model providers, speech providers, web search providers, and bundled registration ownership.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
The practical effect is that OpenClaw knows, up front, which plugin owns which surface. That lets core and channels compose seamlessly because ownership is declared, typed, and testable rather than implicit.
|
||||
|
||||
### What belongs in a contract
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Good contracts">
|
||||
- typed
|
||||
- small
|
||||
- capability-specific
|
||||
- owned by core
|
||||
- reusable by multiple plugins
|
||||
- consumable by channels/features without vendor knowledge
|
||||
|
||||
</Tab>
|
||||
<Tab title="Bad contracts">
|
||||
- vendor-specific policy hidden in core
|
||||
- one-off plugin escape hatches that bypass the registry
|
||||
- channel code reaching straight into a vendor implementation
|
||||
- ad hoc runtime objects that are not part of `OpenClawPluginApi` or `api.runtime`
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
When in doubt, raise the abstraction level: define the capability first, then let plugins plug into it.
|
||||
|
||||
## Execution model
|
||||
|
||||
Native OpenClaw plugins run **in-process** with the Gateway. They are not sandboxed. A loaded native plugin has the same process-level trust boundary as core code.
|
||||
|
||||
<Warning>
|
||||
Native plugin implications: a plugin can register tools, network handlers, hooks, and services; a plugin bug can crash or destabilize the gateway; and a malicious native plugin is equivalent to arbitrary code execution inside the OpenClaw process.
|
||||
</Warning>
|
||||
|
||||
Compatible bundles are safer by default because OpenClaw currently treats them as metadata/content packs. In current releases, that mostly means bundled skills.
|
||||
|
||||
Use allowlists and explicit install/load paths for non-bundled plugins. Treat workspace plugins as development-time code, not production defaults.
|
||||
|
||||
For bundled workspace package names, keep the plugin id anchored in the npm name: `@openclaw/<id>` by default, or an approved typed suffix such as `-provider`, `-plugin`, `-speech`, `-sandbox`, or `-media-understanding` when the package intentionally exposes a narrower plugin role.
|
||||
|
||||
<Note>
|
||||
**Trust note:** `plugins.allow` trusts **plugin ids**, not source provenance. A workspace plugin with the same id as a bundled plugin intentionally shadows the bundled copy when that workspace plugin is enabled/allowlisted. This is normal and useful for local development, patch testing, and hotfixes. Bundled-plugin trust is resolved from the source snapshot — the manifest and code on disk at load time — rather than from install metadata. A corrupted or substituted install record cannot silently widen a bundled plugin's trust surface beyond what the actual source claims.
|
||||
</Note>
|
||||
|
||||
## Export boundary
|
||||
|
||||
OpenClaw exports capabilities, not implementation convenience.
|
||||
|
||||
Keep capability registration public. Trim non-contract helper exports:
|
||||
|
||||
- bundled-plugin-specific helper subpaths
|
||||
- runtime plumbing subpaths not intended as public API
|
||||
- vendor-specific convenience helpers
|
||||
- setup/onboarding helpers that are implementation details
|
||||
|
||||
Reserved bundled-plugin helper subpaths have been retired from the generated SDK export map. Keep owner-specific helpers inside the owning plugin package; promote only reusable host behavior to generic SDK contracts such as `plugin-sdk/gateway-runtime`, `plugin-sdk/security-runtime`, and `plugin-sdk/plugin-config-runtime`.
|
||||
|
||||
## Internals and reference
|
||||
|
||||
For the load pipeline, registry model, provider runtime hooks, Gateway HTTP routes, message tool schemas, channel target resolution, provider catalogs, context engine plugins, and the guide to adding a new capability, see [Plugin architecture internals](/plugins/architecture-internals).
|
||||
|
||||
## Related
|
||||
|
||||
- [Building plugins](/plugins/building-plugins)
|
||||
- [Plugin manifest](/plugins/manifest)
|
||||
- [Plugin SDK setup](/plugins/sdk-setup)
|
||||
13
docs/plugins/building-extensions.md
Normal file
13
docs/plugins/building-extensions.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
summary: "Redirects to the current Building Plugins guide"
|
||||
title: "Building plugins (redirect)"
|
||||
read_when:
|
||||
- Legacy link to building-extensions
|
||||
---
|
||||
|
||||
This page has moved. See [Building Plugins](/plugins/building-plugins).
|
||||
|
||||
## Related
|
||||
|
||||
- [Building plugins](/plugins/building-plugins)
|
||||
- [Plugin architecture](/plugins/architecture)
|
||||
381
docs/plugins/building-plugins.md
Normal file
381
docs/plugins/building-plugins.md
Normal file
@@ -0,0 +1,381 @@
|
||||
---
|
||||
summary: "Create your first OpenClaw plugin in minutes"
|
||||
title: "Building plugins"
|
||||
sidebarTitle: "Getting Started"
|
||||
doc-schema-version: 1
|
||||
read_when:
|
||||
- You want to create a new OpenClaw plugin
|
||||
- You need a quick-start for plugin development
|
||||
- You are choosing between channel, provider, CLI backend, tool, or hook docs
|
||||
---
|
||||
|
||||
Plugins extend OpenClaw without changing core. A plugin can add a messaging
|
||||
channel, model provider, local CLI backend, agent tool, hook, media provider,
|
||||
or another plugin-owned capability.
|
||||
|
||||
You do not need to add an external plugin to the OpenClaw repository. Publish
|
||||
the package to [ClawHub](/clawhub) and users install it with:
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:<package-name>
|
||||
```
|
||||
|
||||
Bare package specs still install from npm during the launch cutover. Use the
|
||||
`clawhub:` prefix when you want ClawHub resolution.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node 22.19+, Node 23.11+, or Node 24+, and `npm` or `pnpm`.
|
||||
- TypeScript ESM modules.
|
||||
- For in-repo bundled plugin work, clone the repository and run `pnpm install`.
|
||||
Source-checkout plugin development is pnpm-only because OpenClaw discovers
|
||||
bundled plugins from `extensions/*` workspace packages.
|
||||
|
||||
## Choose the plugin shape
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Channel plugin" icon="messages-square" href="/plugins/sdk-channel-plugins">
|
||||
Connect OpenClaw to a messaging platform.
|
||||
</Card>
|
||||
<Card title="Provider plugin" icon="cpu" href="/plugins/sdk-provider-plugins">
|
||||
Add a model, media, search, fetch, speech, or realtime provider.
|
||||
</Card>
|
||||
<Card title="CLI backend plugin" icon="terminal" href="/plugins/cli-backend-plugins">
|
||||
Run a local AI CLI through OpenClaw model fallback.
|
||||
</Card>
|
||||
<Card title="Tool plugin" icon="wrench" href="/plugins/tool-plugins">
|
||||
Register agent tools.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Quickstart
|
||||
|
||||
Build a minimal tool plugin by registering one required agent tool. This is the
|
||||
shortest useful plugin shape and covers the package, manifest, entry point, and
|
||||
local proof.
|
||||
|
||||
<Steps>
|
||||
<Step title="Create package metadata">
|
||||
<CodeGroup>
|
||||
|
||||
```json package.json
|
||||
{
|
||||
"name": "@myorg/openclaw-my-plugin",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"typebox": "1.1.39"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"openclaw": ">=2026.3.24-beta.2"
|
||||
},
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"compat": {
|
||||
"pluginApi": ">=2026.3.24-beta.2",
|
||||
"minGatewayVersion": "2026.3.24-beta.2"
|
||||
},
|
||||
"build": {
|
||||
"openclawVersion": "2026.3.24-beta.2",
|
||||
"pluginSdkVersion": "2026.3.24-beta.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json openclaw.plugin.json
|
||||
{
|
||||
"id": "my-plugin",
|
||||
"name": "My Plugin",
|
||||
"description": "Adds a custom tool to OpenClaw",
|
||||
"contracts": {
|
||||
"tools": ["my_tool"]
|
||||
},
|
||||
"activation": {
|
||||
"onStartup": true
|
||||
},
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Published external plugins should point runtime entries at built JavaScript
|
||||
files. See [SDK entry points](/plugins/sdk-entrypoints) for the full entry
|
||||
point contract.
|
||||
|
||||
Every plugin needs a manifest, even with no config. Runtime tools must
|
||||
appear in `contracts.tools` so OpenClaw can discover ownership without
|
||||
eagerly loading every plugin runtime. Set `activation.onStartup`
|
||||
intentionally; this example loads on Gateway startup.
|
||||
|
||||
Host-trusted plugin surfaces are manifest-gated too and require explicit
|
||||
declaration for installed plugins: `api.registerAgentToolResultMiddleware(...)`
|
||||
needs each target runtime listed in `contracts.agentToolResultMiddleware`,
|
||||
and `api.registerTrustedToolPolicy(...)` needs each policy id in
|
||||
`contracts.trustedToolPolicies`. These declarations keep install-time
|
||||
inspection and runtime registration aligned.
|
||||
|
||||
For every manifest field, see [Plugin manifest](/plugins/manifest).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register the tool">
|
||||
```typescript index.ts
|
||||
import { Type } from "typebox";
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "Adds a custom tool to OpenClaw",
|
||||
register(api) {
|
||||
api.registerTool({
|
||||
name: "my_tool",
|
||||
description: "Echo one input value",
|
||||
parameters: Type.Object({ input: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Got: ${params.input}` }],
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Use `definePluginEntry` for non-channel plugins. Channel plugins use
|
||||
`defineChannelPluginEntry` from `openclaw/plugin-sdk/core` instead.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test the runtime">
|
||||
For an installed or external plugin, inspect the loaded runtime:
|
||||
|
||||
```bash
|
||||
openclaw plugins inspect my-plugin --runtime --json
|
||||
```
|
||||
|
||||
If the plugin registers a CLI command, run that command too and confirm
|
||||
output, for example `openclaw demo-plugin ping`.
|
||||
|
||||
For a bundled plugin in this repository, OpenClaw discovers source-checkout
|
||||
plugin packages from the `extensions/*` workspace. Run the closest targeted
|
||||
test:
|
||||
|
||||
```bash
|
||||
pnpm test extensions/my-plugin/
|
||||
pnpm check
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Test the package install">
|
||||
Before publishing a package-ready plugin, test the same install shape users
|
||||
will get. First add a build step, point runtime entries such as
|
||||
`openclaw.extensions` at built JavaScript like `./dist/index.js`, and make
|
||||
sure `npm pack` includes that `dist/` output. TypeScript source entries are
|
||||
only for source checkouts and local development paths.
|
||||
|
||||
Then pack the plugin and install the tarball with `npm-pack:`:
|
||||
|
||||
```bash
|
||||
npm pack --pack-destination /tmp
|
||||
openclaw plugins install npm-pack:/tmp/<plugin-package>.tgz --force
|
||||
openclaw plugins inspect my-plugin --runtime --json
|
||||
```
|
||||
|
||||
`npm-pack:` uses OpenClaw's managed per-plugin npm project, so it catches
|
||||
runtime dependency mistakes that source checkout testing can hide. It proves
|
||||
the package and dependency shape, not catalog-linked official trust.
|
||||
Runtime imports must be in `dependencies` or `optionalDependencies`;
|
||||
dependencies left only in `devDependencies` will not be installed for the
|
||||
managed runtime project.
|
||||
|
||||
Do not use a raw archive/path install as the final proof for official or
|
||||
privileged plugin behavior. Raw sources are useful for local debugging, but
|
||||
they do not prove the same dependency path as npm or ClawHub installs. If
|
||||
your plugin relies on trusted official plugin status, add a second proof
|
||||
through a catalog-backed official install or a published package path that
|
||||
records official trust. See
|
||||
[Plugin dependency resolution](/plugins/dependency-resolution) for
|
||||
install-root and dependency ownership details.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Publish">
|
||||
Validate the package before publishing:
|
||||
|
||||
```bash
|
||||
clawhub package publish your-org/your-plugin --dry-run
|
||||
clawhub package publish your-org/your-plugin
|
||||
```
|
||||
|
||||
Canonical ClawHub package snippets live in `docs/snippets/plugin-publish/`.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Install">
|
||||
Install the published package through ClawHub:
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:your-org/your-plugin
|
||||
```
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<a id="registering-agent-tools"></a>
|
||||
|
||||
## Registering tools
|
||||
|
||||
Tools can be required or optional. Required tools are always available when the
|
||||
plugin is enabled. Optional tools need explicit user opt-in before OpenClaw
|
||||
loads the owning plugin runtime.
|
||||
|
||||
```typescript
|
||||
register(api) {
|
||||
api.registerTool(
|
||||
{
|
||||
name: "workflow_tool",
|
||||
description: "Run a workflow",
|
||||
parameters: Type.Object({ pipeline: Type.String() }),
|
||||
async execute(_id, params) {
|
||||
return { content: [{ type: "text", text: params.pipeline }] };
|
||||
},
|
||||
},
|
||||
{ optional: true },
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Every tool registered with `api.registerTool(...)` must also be declared in the
|
||||
plugin manifest:
|
||||
|
||||
```json
|
||||
{
|
||||
"contracts": {
|
||||
"tools": ["workflow_tool"]
|
||||
},
|
||||
"toolMetadata": {
|
||||
"workflow_tool": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Users opt in with `tools.allow`:
|
||||
|
||||
```json5
|
||||
{
|
||||
tools: { allow: ["workflow_tool"] }, // or ["my-plugin"] for every tool from one plugin
|
||||
}
|
||||
```
|
||||
|
||||
Optional tools control whether a tool is exposed to the model. Use
|
||||
[plugin permission requests](/plugins/plugin-permission-requests) when a tool
|
||||
or hook should ask for approval after the model selects it and before the
|
||||
action runs.
|
||||
|
||||
Use optional tools for side effects, unusual binaries, or capabilities that
|
||||
should not be exposed by default. Tool names must not conflict with core tool
|
||||
names; conflicts are skipped and reported in plugin diagnostics. Malformed
|
||||
registrations are skipped and reported the same way: a missing non-empty
|
||||
`name`, a non-function `execute`, or a tool descriptor without a `parameters`
|
||||
object.
|
||||
|
||||
Tool factories receive a runtime-supplied context object. Use `ctx.activeModel`
|
||||
when a tool needs to log, display, or adapt to the active model for the current
|
||||
turn; it can include `provider`, `modelId`, and `modelRef`. Treat it as
|
||||
informational runtime metadata, not a security boundary against the local
|
||||
operator, installed plugin code, or a modified OpenClaw runtime. Sensitive
|
||||
local tools should still require an explicit plugin or operator opt-in and
|
||||
fail closed when active-model metadata is missing or unsuitable.
|
||||
|
||||
The manifest declares ownership and discovery; execution still calls the live
|
||||
registered tool implementation. Keep `toolMetadata.<tool>.optional: true`
|
||||
aligned with `api.registerTool(..., { optional: true })` so OpenClaw can avoid
|
||||
loading that plugin runtime until the tool is explicitly allowlisted.
|
||||
|
||||
## Import conventions
|
||||
|
||||
Import from focused SDK subpaths:
|
||||
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
||||
```
|
||||
|
||||
Do not import from the deprecated root barrel:
|
||||
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk";
|
||||
```
|
||||
|
||||
Within your plugin package, use local barrel files such as `api.ts` and
|
||||
`runtime-api.ts` for internal imports. Do not import your own plugin through an
|
||||
SDK path. Provider-specific helpers should stay in the provider package unless
|
||||
the seam is truly generic.
|
||||
|
||||
Custom Gateway RPC methods are an advanced entry point. Keep them on a
|
||||
plugin-specific prefix; core admin namespaces such as `config.*`,
|
||||
`exec.approvals.*`, `operator.admin.*`, `wizard.*`, and `update.*` stay reserved
|
||||
and resolve to `operator.admin`. The
|
||||
`openclaw/plugin-sdk/gateway-method-runtime` bridge is reserved for plugin HTTP
|
||||
routes that declare `contracts.gatewayMethodDispatch: ["authenticated-request"]`.
|
||||
|
||||
For the full import map, see [Plugin SDK overview](/plugins/sdk-overview).
|
||||
|
||||
## Pre-submission checklist
|
||||
|
||||
<Check>**package.json** has correct `openclaw` metadata</Check>
|
||||
<Check>**openclaw.plugin.json** manifest is present and valid</Check>
|
||||
<Check>Entry point uses `defineChannelPluginEntry` or `definePluginEntry`</Check>
|
||||
<Check>All imports use focused `plugin-sdk/<subpath>` paths</Check>
|
||||
<Check>Internal imports use local modules, not SDK self-imports</Check>
|
||||
<Check>Tests pass (`pnpm test <bundled-plugin-root>/my-plugin/`)</Check>
|
||||
<Check>`pnpm check` passes (in-repo plugins)</Check>
|
||||
|
||||
## Test against beta releases
|
||||
|
||||
1. Watch [openclaw/openclaw](https://github.com/openclaw/openclaw/releases) releases (`Watch` > `Releases`). Beta tags look like `v2026.3.N-beta.1`. You can also follow [@openclaw](https://x.com/openclaw) on X for release announcements.
|
||||
2. Test your plugin against the beta tag as soon as it appears. The window before stable is typically only a few hours.
|
||||
3. Post in your plugin's thread in the `plugin-forum` Discord channel ([discord.gg/clawd](https://discord.gg/clawd)) after testing, with either `all good` or what broke. Create a thread if you do not have one yet.
|
||||
4. If something breaks, open or update an issue titled `Beta blocker: <plugin-name> - <summary>` and apply the `beta-blocker` label. Link the issue in your thread.
|
||||
5. Open a PR to `main` titled `fix(<plugin-id>): beta blocker - <summary>` and link the issue in both the PR and your Discord thread. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation. Blockers with a PR get merged; blockers without one might ship anyway.
|
||||
6. Silence means green. Missing the window usually means your fix lands in the next cycle.
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Channel Plugins" icon="messages-square" href="/plugins/sdk-channel-plugins">
|
||||
Build a messaging channel plugin
|
||||
</Card>
|
||||
<Card title="Provider Plugins" icon="cpu" href="/plugins/sdk-provider-plugins">
|
||||
Build a model provider plugin
|
||||
</Card>
|
||||
<Card title="CLI Backend Plugins" icon="terminal" href="/plugins/cli-backend-plugins">
|
||||
Register a local AI CLI backend
|
||||
</Card>
|
||||
<Card title="SDK Overview" icon="book-open" href="/plugins/sdk-overview">
|
||||
Import map and registration API reference
|
||||
</Card>
|
||||
<Card title="Runtime Helpers" icon="settings" href="/plugins/sdk-runtime">
|
||||
TTS, search, subagent via api.runtime
|
||||
</Card>
|
||||
<Card title="Testing" icon="test-tubes" href="/plugins/sdk-testing">
|
||||
Test utilities and patterns
|
||||
</Card>
|
||||
<Card title="Plugin Manifest" icon="file-json" href="/plugins/manifest">
|
||||
Full manifest schema reference
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin hooks](/plugins/hooks)
|
||||
- [Plugin architecture](/plugins/architecture)
|
||||
313
docs/plugins/bundles.md
Normal file
313
docs/plugins/bundles.md
Normal file
@@ -0,0 +1,313 @@
|
||||
---
|
||||
summary: "Install and use Codex, Claude, and Cursor bundles as OpenClaw plugins"
|
||||
read_when:
|
||||
- You want to install a Codex, Claude, or Cursor-compatible bundle
|
||||
- You need to understand how OpenClaw maps bundle content into native features
|
||||
- You are debugging bundle detection or missing capabilities
|
||||
title: "Plugin bundles"
|
||||
---
|
||||
|
||||
OpenClaw can install plugins from three external ecosystems: **Codex**, **Claude**,
|
||||
and **Cursor**. These are called **bundles** - content and metadata packs that
|
||||
OpenClaw maps into native features like skills, hooks, and MCP tools.
|
||||
|
||||
<Info>
|
||||
Bundles are **not** the same as native OpenClaw plugins. Native plugins run
|
||||
in-process and can register any capability. Bundles are content packs with
|
||||
selective feature mapping and a narrower trust boundary.
|
||||
</Info>
|
||||
|
||||
## Why bundles exist
|
||||
|
||||
Many useful plugins are published in Codex, Claude, or Cursor format. Instead
|
||||
of requiring authors to rewrite them as native OpenClaw plugins, OpenClaw
|
||||
detects these formats and maps their supported content into the native feature
|
||||
set. You can install a Claude command pack or a Codex skill bundle and use it
|
||||
immediately.
|
||||
|
||||
## Install a bundle
|
||||
|
||||
<Steps>
|
||||
<Step title="Install from a directory, archive, or marketplace">
|
||||
```bash
|
||||
# Local directory
|
||||
openclaw plugins install ./my-bundle
|
||||
|
||||
# Archive
|
||||
openclaw plugins install ./my-bundle.tgz
|
||||
|
||||
# Claude marketplace
|
||||
openclaw plugins marketplace list <source>
|
||||
openclaw plugins install <plugin> --marketplace <source>
|
||||
```
|
||||
|
||||
`<source>` is a local marketplace path/repo or a git/GitHub source.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Verify detection">
|
||||
```bash
|
||||
openclaw plugins list
|
||||
openclaw plugins inspect <id>
|
||||
```
|
||||
|
||||
Bundles show `Format: bundle` plus a `Bundle format:` value of `codex`,
|
||||
`claude`, or `cursor`.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Restart and use">
|
||||
```bash
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
Mapped features (skills, hooks, MCP tools, LSP defaults) are available in the next session.
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## What OpenClaw maps from bundles
|
||||
|
||||
Not every bundle feature runs in OpenClaw today. Here is what works and what
|
||||
is detected but not yet wired.
|
||||
|
||||
### Supported now
|
||||
|
||||
| Feature | How it maps | Applies to |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------- | -------------- |
|
||||
| Skill content | Bundle skill roots load as normal OpenClaw skills | All formats |
|
||||
| Commands | `commands/` and `.cursor/commands/` treated as skill roots | Claude, Cursor |
|
||||
| Hook packs | OpenClaw-style `HOOK.md` + `handler.ts` layouts | Codex |
|
||||
| MCP tools | Bundle MCP config merged into embedded OpenClaw settings; supported stdio and HTTP servers loaded | All formats |
|
||||
| LSP servers | Claude `.lsp.json` and manifest-declared `lspServers` merged into embedded OpenClaw LSP defaults | Claude |
|
||||
| Settings | Claude `settings.json` imported as embedded OpenClaw defaults | Claude |
|
||||
|
||||
#### Skill content
|
||||
|
||||
- Bundle skill roots load as normal OpenClaw skill roots.
|
||||
- Claude `commands/` roots are treated as additional skill roots.
|
||||
- Cursor `.cursor/commands/` roots are treated as additional skill roots.
|
||||
|
||||
Claude markdown command files and Cursor command markdown both work through the
|
||||
normal OpenClaw skill loader.
|
||||
|
||||
#### Hook packs
|
||||
|
||||
Bundle hook roots work **only** when they use the normal OpenClaw hook-pack
|
||||
layout: `HOOK.md` plus `handler.ts` or `handler.js`. Today this is primarily
|
||||
the Codex-compatible case.
|
||||
|
||||
#### MCP for embedded OpenClaw
|
||||
|
||||
- Enabled bundles can contribute MCP server config.
|
||||
- OpenClaw merges bundle MCP config into the effective embedded OpenClaw
|
||||
settings as `mcpServers`.
|
||||
- OpenClaw exposes supported bundle MCP tools during embedded OpenClaw agent
|
||||
turns by launching stdio servers or connecting to HTTP servers.
|
||||
- The `coding` and `messaging` tool profiles include bundle MCP tools by
|
||||
default; use `tools.deny: ["bundle-mcp"]` to opt out for an agent or gateway.
|
||||
- Project-local embedded agent settings still apply after bundle defaults, so
|
||||
workspace settings can override bundle MCP entries when needed.
|
||||
- Bundle MCP tool catalogs are sorted deterministically before registration, so
|
||||
upstream `listTools()` order changes do not thrash prompt-cache tool blocks.
|
||||
|
||||
##### Transports
|
||||
|
||||
MCP servers can use stdio or HTTP transport.
|
||||
|
||||
**Stdio** launches a child process:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"my-server": {
|
||||
"command": "node",
|
||||
"args": ["server.js"],
|
||||
"env": { "PORT": "3000" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**HTTP** connects to a running MCP server, defaulting to `sse` unless
|
||||
`streamable-http` is requested:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"my-server": {
|
||||
"url": "http://localhost:3100/mcp",
|
||||
"transport": "streamable-http",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${MY_SECRET_TOKEN}"
|
||||
},
|
||||
"connectionTimeoutMs": 30000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `transport` accepts `"streamable-http"` or `"sse"`; omitted defaults to `sse`.
|
||||
- `type: "http"` is a CLI-native downstream shape; use `transport: "streamable-http"` in OpenClaw config. `openclaw mcp set` and `openclaw doctor --fix` normalize the common alias.
|
||||
- Only `http:` and `https:` URL schemes are allowed.
|
||||
- `headers` values support `${ENV_VAR}` interpolation.
|
||||
- A server entry with both `command` and `url` is rejected.
|
||||
- URL credentials (userinfo and query params) are redacted from tool
|
||||
descriptions and logs.
|
||||
- `connectionTimeoutMs` overrides the default 30-second connection timeout for
|
||||
both stdio and HTTP transports. Request timeout defaults to 60 seconds and
|
||||
can be overridden with `requestTimeoutMs`.
|
||||
|
||||
##### Tool naming
|
||||
|
||||
OpenClaw registers bundle MCP tools with provider-safe names in the form
|
||||
`serverName__toolName`. For example, a server keyed `"vigil-harbor"` exposing a
|
||||
`memory_search` tool registers as `vigil-harbor__memory_search`.
|
||||
|
||||
- Characters outside `A-Za-z0-9_-` are replaced with `-`.
|
||||
- Fragments that would start with a non-letter get a letter prefix, so numeric
|
||||
server keys such as `12306` become provider-safe tool prefixes.
|
||||
- Server prefixes are capped at 30 characters.
|
||||
- Full tool names are capped at 64 characters.
|
||||
- Empty server names fall back to `mcp`.
|
||||
- Colliding sanitized names are disambiguated with numeric suffixes.
|
||||
- Final exposed tool order is deterministic by safe name, keeping repeated
|
||||
embedded-agent turns cache-stable.
|
||||
- Profile filtering treats every tool from one bundle MCP server as
|
||||
plugin-owned by `bundle-mcp`, so profile allow/deny lists can reference
|
||||
either individual exposed tool names or the `bundle-mcp` plugin key.
|
||||
|
||||
#### Embedded OpenClaw settings
|
||||
|
||||
Claude `settings.json` is imported as default embedded OpenClaw settings when
|
||||
the bundle is enabled. OpenClaw sanitizes shell override keys before applying
|
||||
them:
|
||||
|
||||
- `shellPath`
|
||||
- `shellCommandPrefix`
|
||||
|
||||
#### Embedded OpenClaw LSP
|
||||
|
||||
- Enabled Claude bundles can contribute LSP server config.
|
||||
- OpenClaw loads `.lsp.json` plus any manifest-declared `lspServers` paths.
|
||||
- Bundle LSP config is merged into the effective embedded OpenClaw LSP
|
||||
defaults.
|
||||
- Only supported stdio-backed LSP servers are runnable today; unsupported
|
||||
transports still show up in `openclaw plugins inspect <id>`.
|
||||
|
||||
### Detected but not executed
|
||||
|
||||
These are recognized and shown in diagnostics, but OpenClaw does not run them:
|
||||
|
||||
- Claude `agents`, `hooks/hooks.json` automation, `outputStyles`
|
||||
- Cursor `.cursor/agents`, `.cursor/hooks.json`, `.cursor/rules`
|
||||
- Codex `.app.json` metadata beyond capability reporting
|
||||
|
||||
## Bundle formats
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Codex bundles">
|
||||
Markers: `.codex-plugin/plugin.json`
|
||||
|
||||
Optional content: `skills/`, `hooks/`, `.mcp.json`, `.app.json`
|
||||
|
||||
Codex bundles fit OpenClaw best when they use skill roots and OpenClaw-style
|
||||
hook-pack directories (`HOOK.md` + `handler.ts`).
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude bundles">
|
||||
Two detection modes:
|
||||
|
||||
- **Manifest-based:** `.claude-plugin/plugin.json`
|
||||
- **Manifestless:** default Claude layout (`skills/`, `commands/`, `agents/`, `hooks/`, `.mcp.json`, `.lsp.json`, `settings.json`)
|
||||
|
||||
Claude-specific behavior:
|
||||
|
||||
- `commands/` is treated as skill content
|
||||
- `settings.json` is imported into embedded OpenClaw settings (shell override keys are sanitized)
|
||||
- `.mcp.json` exposes supported stdio tools to embedded OpenClaw
|
||||
- `.lsp.json` plus manifest-declared `lspServers` paths load into embedded OpenClaw LSP defaults
|
||||
- `hooks/hooks.json` is detected but not executed
|
||||
- Custom component paths in the manifest are additive; they extend defaults, not replace them
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Cursor bundles">
|
||||
Markers: `.cursor-plugin/plugin.json`
|
||||
|
||||
Optional content: `skills/`, `.cursor/commands/`, `.cursor/agents/`, `.cursor/rules/`, `.cursor/hooks.json`, `.mcp.json`
|
||||
|
||||
- `.cursor/commands/` is treated as skill content
|
||||
- `.cursor/rules/`, `.cursor/agents/`, and `.cursor/hooks.json` are detect-only
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Detection precedence
|
||||
|
||||
OpenClaw checks for native plugin format first:
|
||||
|
||||
1. `openclaw.plugin.json` or a valid `package.json` with `openclaw.extensions` - treated as a **native plugin**
|
||||
2. Bundle markers (`.codex-plugin/`, `.claude-plugin/`, or default Claude/Cursor layout) - treated as a **bundle**
|
||||
|
||||
If a directory contains both, OpenClaw uses the native path. This prevents
|
||||
dual-format packages from being partially installed as bundles.
|
||||
|
||||
## Runtime dependencies and cleanup
|
||||
|
||||
- Third-party compatible bundles do not get startup `npm install` repair. They
|
||||
should be installed through `openclaw plugins install` and ship everything
|
||||
they need in the installed plugin directory.
|
||||
- OpenClaw-owned bundled plugins are either shipped lightweight in core or
|
||||
downloadable through the plugin installer. Gateway startup never runs a
|
||||
package manager for them.
|
||||
- `openclaw doctor --fix` removes stale local bundled-plugin install records
|
||||
and can recover downloadable plugins that are missing from the local plugin
|
||||
index when config still references them.
|
||||
|
||||
## Security
|
||||
|
||||
Bundles have a narrower trust boundary than native plugins:
|
||||
|
||||
- OpenClaw does **not** load arbitrary bundle runtime modules in-process.
|
||||
- Skills and hook-pack paths must stay inside the plugin root (boundary-checked).
|
||||
- Settings files are read with the same boundary checks.
|
||||
- Supported stdio MCP servers may be launched as subprocesses.
|
||||
|
||||
This makes bundles safer by default, but you should still treat third-party
|
||||
bundles as trusted content for the features they do expose.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Bundle is detected but capabilities do not run">
|
||||
Run `openclaw plugins inspect <id>`. If a capability is listed but marked as
|
||||
not wired, that is a product limit, not a broken install.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude command files do not appear">
|
||||
Make sure the bundle is enabled and the markdown files are inside a detected
|
||||
`commands/` or `skills/` root.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude settings do not apply">
|
||||
Only embedded OpenClaw settings from `settings.json` are supported. OpenClaw does
|
||||
not treat bundle settings as raw config patches.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude hooks do not execute">
|
||||
`hooks/hooks.json` is detect-only. If you need runnable hooks, use the
|
||||
OpenClaw hook-pack layout or ship a native plugin.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Related
|
||||
|
||||
- [Install and Configure Plugins](/tools/plugin)
|
||||
- [Building Plugins](/plugins/building-plugins) - create a native plugin
|
||||
- [Plugin Manifest](/plugins/manifest) - native manifest schema
|
||||
350
docs/plugins/cli-backend-plugins.md
Normal file
350
docs/plugins/cli-backend-plugins.md
Normal file
@@ -0,0 +1,350 @@
|
||||
---
|
||||
summary: "Build a plugin that registers a local AI CLI backend"
|
||||
title: "Building CLI backend plugins"
|
||||
sidebarTitle: "CLI backend plugins"
|
||||
read_when:
|
||||
- You are building a local AI CLI backend plugin
|
||||
- You want to register a backend for model refs such as acme-cli/model
|
||||
- You need to map a third-party CLI into OpenClaw's text fallback runner
|
||||
---
|
||||
|
||||
CLI backend plugins let OpenClaw call a local AI CLI as a text inference
|
||||
backend. The backend appears as a provider prefix in model refs:
|
||||
|
||||
```text
|
||||
acme-cli/acme-large
|
||||
```
|
||||
|
||||
Use a CLI backend when the upstream integration is already exposed as a local
|
||||
command, when the CLI owns local login state, or as a fallback when API
|
||||
providers are unavailable.
|
||||
|
||||
<Info>
|
||||
If the upstream service exposes a normal HTTP model API, write a
|
||||
[provider plugin](/plugins/sdk-provider-plugins) instead. If the upstream
|
||||
runtime owns complete agent sessions, tool events, compaction, or background
|
||||
task state, use an [agent harness](/plugins/sdk-agent-harness).
|
||||
</Info>
|
||||
|
||||
## What the plugin owns
|
||||
|
||||
A CLI backend plugin has three contracts:
|
||||
|
||||
| Contract | File | Purpose |
|
||||
| -------------------- | ---------------------- | --------------------------------------------------------- |
|
||||
| Package entry | `package.json` | Points OpenClaw at the plugin runtime module |
|
||||
| Manifest ownership | `openclaw.plugin.json` | Declares the backend id before runtime loads |
|
||||
| Runtime registration | `index.ts` | Calls `api.registerCliBackend(...)` with command defaults |
|
||||
|
||||
The manifest is discovery metadata: it does not execute the CLI or register
|
||||
runtime behavior. Runtime behavior starts when the plugin entry calls
|
||||
`api.registerCliBackend(...)`.
|
||||
|
||||
## Minimal backend plugin
|
||||
|
||||
<Steps>
|
||||
<Step title="Create package metadata">
|
||||
```json package.json
|
||||
{
|
||||
"name": "@acme/openclaw-acme-cli",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./index.ts"],
|
||||
"compat": {
|
||||
"pluginApi": ">=2026.3.24-beta.2",
|
||||
"minGatewayVersion": "2026.3.24-beta.2"
|
||||
},
|
||||
"build": {
|
||||
"openclawVersion": "2026.3.24-beta.2",
|
||||
"pluginSdkVersion": "2026.3.24-beta.2"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"openclaw": "^2026.3.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.9.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Published packages must ship built JavaScript runtime files. If your source
|
||||
entry is `./src/index.ts`, add `openclaw.runtimeExtensions` pointing at the
|
||||
built JavaScript peer. See [Entry points](/plugins/sdk-entrypoints).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Declare backend ownership">
|
||||
```json openclaw.plugin.json
|
||||
{
|
||||
"id": "acme-cli",
|
||||
"name": "Acme CLI",
|
||||
"description": "Run Acme's local AI CLI through OpenClaw",
|
||||
"cliBackends": ["acme-cli"],
|
||||
"setup": {
|
||||
"cliBackends": ["acme-cli"],
|
||||
"requiresRuntime": false
|
||||
},
|
||||
"activation": {
|
||||
"onStartup": false
|
||||
},
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cliBackends` is the runtime ownership list; it lets OpenClaw auto-load the
|
||||
plugin when config or model selection mentions `acme-cli/...`.
|
||||
|
||||
`setup.cliBackends` is the descriptor-first setup surface. Add it when
|
||||
model discovery, onboarding, or status should recognize the backend
|
||||
without loading plugin runtime. Use `requiresRuntime: false` only when
|
||||
those static descriptors are enough for setup.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register the backend">
|
||||
```typescript index.ts
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import {
|
||||
CLI_FRESH_WATCHDOG_DEFAULTS,
|
||||
CLI_RESUME_WATCHDOG_DEFAULTS,
|
||||
type CliBackendPlugin,
|
||||
} from "openclaw/plugin-sdk/cli-backend";
|
||||
|
||||
function buildAcmeCliBackend(): CliBackendPlugin {
|
||||
return {
|
||||
id: "acme-cli",
|
||||
liveTest: {
|
||||
defaultModelRef: "acme-cli/acme-large",
|
||||
defaultImageProbe: false,
|
||||
defaultMcpProbe: false,
|
||||
docker: {
|
||||
npmPackage: "@acme/acme-cli",
|
||||
binaryName: "acme",
|
||||
},
|
||||
},
|
||||
config: {
|
||||
command: "acme",
|
||||
args: ["chat", "--json"],
|
||||
output: "json",
|
||||
input: "stdin",
|
||||
modelArg: "--model",
|
||||
sessionArg: "--session",
|
||||
sessionMode: "existing",
|
||||
sessionIdFields: ["session_id", "conversation_id"],
|
||||
systemPromptFileArg: "--system-file",
|
||||
systemPromptWhen: "first",
|
||||
imageArg: "--image",
|
||||
imageMode: "repeat",
|
||||
reliability: {
|
||||
watchdog: {
|
||||
fresh: { ...CLI_FRESH_WATCHDOG_DEFAULTS },
|
||||
resume: { ...CLI_RESUME_WATCHDOG_DEFAULTS },
|
||||
},
|
||||
},
|
||||
serialize: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "acme-cli",
|
||||
name: "Acme CLI",
|
||||
description: "Run Acme's local AI CLI through OpenClaw",
|
||||
register(api) {
|
||||
api.registerCliBackend(buildAcmeCliBackend());
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The backend id must match the manifest `cliBackends` entry. The
|
||||
registered `config` is only the default; user config under
|
||||
`agents.defaults.cliBackends.acme-cli` merges over it at runtime.
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Config shape
|
||||
|
||||
`CliBackendConfig` describes how OpenClaw should launch and parse the CLI:
|
||||
|
||||
| Field | Use |
|
||||
| --------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `command` | Binary name or absolute command path |
|
||||
| `args` | Base argv for fresh runs |
|
||||
| `resumeArgs` | Alternate argv for resumed sessions; supports `{sessionId}` |
|
||||
| `output` / `resumeOutput` | Parser: `json`, `jsonl`, or `text` |
|
||||
| `jsonlDialect` | JSONL event dialect: `claude-stream-json` or `gemini-stream-json` |
|
||||
| `liveSession` | Long-lived CLI process mode (`claude-stdio`) |
|
||||
| `input` | Prompt transport: `arg` or `stdin` |
|
||||
| `maxPromptArgChars` | Max prompt length for `arg` mode before falling back to stdin |
|
||||
| `env` / `clearEnv` | Extra env vars to inject, or names to strip before launch |
|
||||
| `modelArg` | Flag used before the model id |
|
||||
| `modelAliases` | Map OpenClaw model ids to CLI-native ids |
|
||||
| `sessionArg` / `sessionArgs` | How to pass a session id |
|
||||
| `sessionMode` | `always`, `existing`, or `none` |
|
||||
| `sessionIdFields` | JSON fields OpenClaw reads from CLI output |
|
||||
| `systemPromptArg` / `systemPromptFileArg` | System prompt transport |
|
||||
| `systemPromptFileConfigArg` / `systemPromptFileConfigKey` | Config-override transport for a system prompt file (for example `-c`) |
|
||||
| `systemPromptMode` | `append` or `replace` |
|
||||
| `systemPromptWhen` | `first`, `always`, or `never` |
|
||||
| `imageArg` / `imageMode` | Image path flag and how to pass multiple images (`repeat` or `list`) |
|
||||
| `imagePathScope` | Where staged image files live before handoff: `temp` or `workspace` |
|
||||
| `serialize` | Keep same-backend runs ordered |
|
||||
| `reseedFromRawTranscriptWhenUncompacted` | Opt in to bounded raw-transcript reseed before compaction for safe session resets |
|
||||
| `reliability.outputLimits` | Max raw JSONL chars/lines retained for one live CLI turn (live-session backends) |
|
||||
| `reliability.watchdog` | No-output timeout tuning, separate for fresh vs resumed runs |
|
||||
|
||||
Prefer the smallest static config that matches the CLI. Add plugin callbacks
|
||||
only for behavior that really belongs to the backend.
|
||||
|
||||
## Advanced backend hooks
|
||||
|
||||
`CliBackendPlugin` can also define:
|
||||
|
||||
| Hook | Use |
|
||||
| ---------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `normalizeConfig(config, context)` | Rewrite legacy user config after merge |
|
||||
| `resolveExecutionArgs(ctx)` | Add request-scoped flags such as thinking effort or side-question isolation |
|
||||
| `prepareExecution(ctx)` | Create temporary auth or config bridges before launch |
|
||||
| `transformSystemPrompt(ctx)` | Apply a final CLI-specific system prompt transform |
|
||||
| `textTransforms` | Bidirectional prompt/output replacements |
|
||||
| `defaultAuthProfileId` | Prefer a specific OpenClaw auth profile |
|
||||
| `authEpochMode` | Decide how auth changes invalidate stored CLI sessions |
|
||||
| `nativeToolMode` | Declare whether the CLI has always-on native tools |
|
||||
| `sideQuestionToolMode` | Declare disabled native tools for `/btw` side questions |
|
||||
| `bundleMcp` / `bundleMcpMode` | Opt into OpenClaw's loopback MCP tool bridge |
|
||||
| `ownsNativeCompaction` | Backend owns its own compaction - OpenClaw defers |
|
||||
|
||||
Keep these hooks provider-owned. Do not add CLI-specific branches to core when
|
||||
a backend hook can express the behavior.
|
||||
|
||||
`ctx.executionMode` is `"agent"` for normal turns and `"side-question"` for
|
||||
ephemeral `/btw` calls. Use it when the CLI needs different one-shot flags,
|
||||
such as disabling native tools, session persistence, or resume behavior for
|
||||
BTW. If a backend normally has `nativeToolMode: "always-on"` but its
|
||||
side-question argv reliably disables those tools, also set
|
||||
`sideQuestionToolMode: "disabled"`; otherwise OpenClaw fails closed when BTW
|
||||
requires a no-tools CLI run.
|
||||
|
||||
### `ownsNativeCompaction`: opting out of OpenClaw compaction
|
||||
|
||||
If your backend runs an agent that compacts its **own** transcript, set
|
||||
`ownsNativeCompaction: true` so OpenClaw's safeguard summarizer never runs
|
||||
against its sessions - the CLI compaction lifecycle returns a no-op and the
|
||||
turn proceeds. `claude-cli` declares it because Claude Code compacts
|
||||
internally with no harness endpoint. Native-harness sessions such as Codex
|
||||
keep routing to their harness compaction endpoint instead.
|
||||
|
||||
**Only declare it when all of the following hold**, or a deferred
|
||||
over-budget session can stay over budget or go stale (OpenClaw no longer
|
||||
rescues it):
|
||||
|
||||
- the backend reliably compacts or bounds its own transcript as it nears its
|
||||
window;
|
||||
- it persists a resumable session so the compacted state survives turns
|
||||
(for example `--resume` / `--session-id`);
|
||||
- it is not a native-harness compaction session - matching `agentHarnessId`
|
||||
sessions route to the harness endpoint instead.
|
||||
|
||||
## MCP tool bridge
|
||||
|
||||
CLI backends do not receive OpenClaw tools by default. If the CLI can consume
|
||||
an MCP configuration, opt in explicitly:
|
||||
|
||||
```typescript
|
||||
return {
|
||||
id: "acme-cli",
|
||||
bundleMcp: true,
|
||||
bundleMcpMode: "codex-config-overrides",
|
||||
config: {
|
||||
command: "acme",
|
||||
args: ["chat", "--json"],
|
||||
output: "json",
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Supported bridge modes:
|
||||
|
||||
| Mode | Use |
|
||||
| ------------------------ | ---------------------------------------------------------------- |
|
||||
| `claude-config-file` | CLIs that accept an MCP config file |
|
||||
| `codex-config-overrides` | CLIs that accept config overrides on argv |
|
||||
| `gemini-system-settings` | CLIs that read MCP settings from their system settings directory |
|
||||
|
||||
Only enable the bridge when the CLI can actually consume it. If the CLI has
|
||||
its own built-in tool layer that cannot be disabled, set `nativeToolMode:
|
||||
"always-on"` so OpenClaw can fail closed when a caller requires no native
|
||||
tools.
|
||||
|
||||
## User configuration
|
||||
|
||||
Users can override any backend default:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
cliBackends: {
|
||||
"acme-cli": {
|
||||
command: "/opt/acme/bin/acme",
|
||||
args: ["chat", "--json", "--profile", "work"],
|
||||
modelAliases: {
|
||||
large: "acme-large-2026",
|
||||
},
|
||||
},
|
||||
},
|
||||
model: {
|
||||
primary: "openai/gpt-5.5",
|
||||
fallbacks: ["acme-cli/large"],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Document the minimum override users are likely to need - usually only
|
||||
`command` when the binary is outside `PATH`.
|
||||
|
||||
## Verification
|
||||
|
||||
For bundled plugins, add a focused test around the builder and setup
|
||||
registration, then run the plugin's targeted test lane:
|
||||
|
||||
```bash
|
||||
pnpm test extensions/acme-cli
|
||||
```
|
||||
|
||||
For local or installed plugins, verify discovery and one real model run:
|
||||
|
||||
```bash
|
||||
openclaw plugins inspect acme-cli --runtime --json
|
||||
openclaw agent --message "reply exactly: backend ok" --model acme-cli/acme-large
|
||||
```
|
||||
|
||||
If the backend supports images or MCP, add a live smoke that proves those
|
||||
paths with the real CLI. Do not rely on static inspection for prompt, image,
|
||||
MCP, or session-resume behavior.
|
||||
|
||||
## Checklist
|
||||
|
||||
<Check>`package.json` has `openclaw.extensions` and built runtime entries for published packages</Check>
|
||||
<Check>`openclaw.plugin.json` declares `cliBackends` and intentional `activation.onStartup`</Check>
|
||||
<Check>`setup.cliBackends` is present when setup/model discovery should see the backend cold</Check>
|
||||
<Check>`api.registerCliBackend(...)` uses the same backend id as the manifest</Check>
|
||||
<Check>User overrides under `agents.defaults.cliBackends.<id>` still win</Check>
|
||||
<Check>Session, system prompt, image, and output parser settings match the real CLI contract</Check>
|
||||
<Check>Targeted tests and at least one live CLI smoke prove the backend path</Check>
|
||||
|
||||
## Related
|
||||
|
||||
- [CLI backends](/gateway/cli-backends) - user configuration and runtime behavior
|
||||
- [Building plugins](/plugins/building-plugins) - package and manifest basics
|
||||
- [Plugin SDK overview](/plugins/sdk-overview) - registration API reference
|
||||
- [Plugin manifest](/plugins/manifest) - `cliBackends` and setup descriptors
|
||||
- [Agent harness](/plugins/sdk-agent-harness) - full external agent runtimes
|
||||
336
docs/plugins/codex-computer-use.md
Normal file
336
docs/plugins/codex-computer-use.md
Normal file
@@ -0,0 +1,336 @@
|
||||
---
|
||||
summary: "Set up Codex Computer Use for Codex-mode OpenClaw agents"
|
||||
title: "Codex Computer Use"
|
||||
read_when:
|
||||
- You want Codex-mode OpenClaw agents to use Codex Computer Use
|
||||
- You are deciding between Codex Computer Use, PeekabooBridge, and direct cua-driver MCP
|
||||
- You are deciding between Codex Computer Use and a direct cua-driver MCP setup
|
||||
- You are configuring computerUse for the bundled Codex plugin
|
||||
- You are troubleshooting /codex computer-use status or install
|
||||
---
|
||||
|
||||
Computer Use is a Codex-native MCP plugin for local desktop control. OpenClaw
|
||||
does not vendor the desktop app, execute desktop actions itself, or bypass
|
||||
Codex permissions. The bundled `codex` plugin only prepares Codex app-server:
|
||||
it enables Codex plugin support, finds or installs the configured Computer Use
|
||||
plugin, checks that the `computer-use` MCP server is available, and then lets
|
||||
Codex own the native MCP tool calls during Codex-mode turns.
|
||||
|
||||
Use this page when OpenClaw is already using the native Codex harness. For the
|
||||
runtime setup itself, see [Codex harness](/plugins/codex-harness).
|
||||
|
||||
## OpenClaw.app and Peekaboo
|
||||
|
||||
OpenClaw.app's Peekaboo integration is separate from Codex Computer Use. The
|
||||
macOS app can host a PeekabooBridge socket so the `peekaboo` CLI can reuse the
|
||||
app's local Accessibility and Screen Recording grants for Peekaboo's own
|
||||
automation tools. That bridge does not install or proxy Codex Computer Use, and
|
||||
Codex Computer Use does not call through the PeekabooBridge socket.
|
||||
|
||||
Use [Peekaboo bridge](/platforms/mac/peekaboo) when you want OpenClaw.app to be
|
||||
a permission-aware host for Peekaboo CLI automation. Use this page when a
|
||||
Codex-mode OpenClaw agent should have Codex's native `computer-use` MCP plugin
|
||||
available before the turn starts.
|
||||
|
||||
## iOS app
|
||||
|
||||
The iOS app is separate from Codex Computer Use. It does not install or proxy
|
||||
the Codex `computer-use` MCP server and it is not a desktop-control backend.
|
||||
Instead, the iOS app connects as an OpenClaw node and exposes mobile
|
||||
capabilities through node commands such as `canvas.*`, `camera.*`, `screen.*`,
|
||||
`location.*`, and `talk.*`.
|
||||
|
||||
Use [iOS](/platforms/ios) when you want an agent to drive an iPhone node
|
||||
through the gateway. Use this page when a Codex-mode agent should control the
|
||||
local macOS desktop through Codex's native Computer Use plugin.
|
||||
|
||||
## Direct cua-driver MCP
|
||||
|
||||
Codex Computer Use is not the only way to expose desktop control. If you want
|
||||
OpenClaw-managed runtimes to call TryCua's driver directly, use the upstream
|
||||
`cua-driver mcp` server through OpenClaw's MCP registry instead of the
|
||||
Codex-specific marketplace flow.
|
||||
|
||||
After installing `cua-driver`, either ask it for the OpenClaw command:
|
||||
|
||||
```bash
|
||||
cua-driver mcp-config --client openclaw
|
||||
```
|
||||
|
||||
or register the stdio server directly:
|
||||
|
||||
```bash
|
||||
openclaw mcp set cua-driver '{"command":"cua-driver","args":["mcp"]}'
|
||||
```
|
||||
|
||||
That path keeps the upstream MCP tool surface intact, including the driver
|
||||
schemas and structured MCP responses. Use it when you want the CUA driver
|
||||
available as a normal OpenClaw MCP server. Use the Codex Computer Use setup on
|
||||
this page when Codex app-server should own plugin installation, MCP reloads,
|
||||
and native tool calls inside Codex-mode turns.
|
||||
|
||||
CUA's driver is macOS-specific and still requires the local macOS permissions
|
||||
its app prompts for, such as Accessibility and Screen Recording. OpenClaw does
|
||||
not install `cua-driver`, grant those permissions, or bypass the upstream
|
||||
driver's safety model.
|
||||
|
||||
## Quick setup
|
||||
|
||||
Set `plugins.entries.codex.config.computerUse` when Codex-mode turns must have
|
||||
Computer Use available before a thread starts. `autoInstall: true` opts
|
||||
Computer Use in and lets OpenClaw install or re-enable it before the turn:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
computerUse: {
|
||||
autoInstall: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
With this config, OpenClaw checks Codex app-server before each Codex-mode
|
||||
turn. If Computer Use is missing but Codex app-server has already discovered
|
||||
an installable marketplace, OpenClaw asks Codex app-server to install or
|
||||
re-enable the plugin and reload MCP servers. On macOS, when no matching
|
||||
marketplace is registered and the standard Codex app bundle exists, OpenClaw
|
||||
also tries to register the bundled Codex marketplace from
|
||||
`/Applications/Codex.app/Contents/Resources/plugins/openai-bundled` before it
|
||||
fails. If setup still cannot make the MCP server available, the turn fails
|
||||
before the thread starts.
|
||||
|
||||
After changing Computer Use config, use `/new` or `/reset` in the affected
|
||||
chat before testing if an existing Codex thread has already started.
|
||||
|
||||
On macOS managed stdio startup, OpenClaw prefers the signed desktop Codex app
|
||||
bundle at `/Applications/Codex.app/Contents/Resources/codex` when it exists.
|
||||
That keeps Computer Use under the app bundle that owns the local
|
||||
desktop-control permissions. If the desktop app is not installed, OpenClaw
|
||||
falls back to the managed Codex binary installed beside the plugin. If an
|
||||
installed desktop app initializes with an unsupported app-server version,
|
||||
OpenClaw closes that child and retries the next managed binary candidate
|
||||
instead of letting a stale desktop app shadow the plugin-local fallback.
|
||||
Explicit `appServer.command` config or `OPENCLAW_CODEX_APP_SERVER_BIN` still
|
||||
overrides this managed selection.
|
||||
|
||||
## Commands
|
||||
|
||||
Use the `/codex computer-use` commands from any chat surface where the
|
||||
`codex` plugin command surface is available. These are OpenClaw chat/runtime
|
||||
commands, not `openclaw codex ...` CLI subcommands:
|
||||
|
||||
```text
|
||||
/codex computer-use status
|
||||
/codex computer-use install
|
||||
/codex computer-use install --source <marketplace-source>
|
||||
/codex computer-use install --marketplace-path <path>
|
||||
/codex computer-use install --marketplace <name>
|
||||
```
|
||||
|
||||
`status` is the default action and is read-only: it does not add marketplace
|
||||
sources, install plugins, or enable Codex plugin support. If no config opts
|
||||
Computer Use in, `status` can report disabled even after a one-off install
|
||||
command.
|
||||
|
||||
`install` enables Codex app-server plugin support, optionally adds a
|
||||
configured marketplace source, installs or re-enables the configured plugin
|
||||
through Codex app-server, reloads MCP servers, and verifies that the MCP
|
||||
server exposes tools. Because installation changes trusted host resources,
|
||||
only an owner or an `operator.admin` Gateway client can run `install`. Other
|
||||
authorized senders can continue to use the read-only `status` command,
|
||||
including with overrides.
|
||||
|
||||
## Marketplace choices
|
||||
|
||||
OpenClaw uses the same app-server API that Codex itself exposes. The
|
||||
marketplace fields choose where Codex should find `computer-use`.
|
||||
|
||||
| Field | Use when | Install support |
|
||||
| -------------------- | --------------------------------------------------------------- | -------------------------------------------------------- |
|
||||
| No marketplace field | You want Codex app-server to use marketplaces it already knows. | Yes, when app-server returns a local marketplace. |
|
||||
| `marketplaceSource` | You have a Codex marketplace source app-server can add. | Yes, for explicit `/codex computer-use install`. |
|
||||
| `marketplacePath` | You already know the local marketplace file path on the host. | Yes, for explicit install and turn-start auto-install. |
|
||||
| `marketplaceName` | You want to select one already registered marketplace by name. | Yes only when the selected marketplace has a local path. |
|
||||
|
||||
Fresh Codex homes may need a short moment to seed their official
|
||||
marketplaces. During install, OpenClaw polls `plugin/list` for up to
|
||||
`marketplaceDiscoveryTimeoutMs` milliseconds (default 60 seconds).
|
||||
|
||||
If multiple known marketplaces contain Computer Use, OpenClaw prefers
|
||||
`openai-bundled`, then `openai-curated`, then `local`. Unknown ambiguous
|
||||
matches fail closed and ask you to set `marketplaceName` or
|
||||
`marketplacePath`.
|
||||
|
||||
## Bundled macOS marketplace
|
||||
|
||||
Recent Codex desktop builds bundle Computer Use here:
|
||||
|
||||
```text
|
||||
/Applications/Codex.app/Contents/Resources/plugins/openai-bundled/plugins/computer-use
|
||||
```
|
||||
|
||||
When `computerUse.autoInstall` is true and no marketplace containing
|
||||
`computer-use` is registered, OpenClaw tries to add the standard bundled
|
||||
marketplace root automatically:
|
||||
|
||||
```text
|
||||
/Applications/Codex.app/Contents/Resources/plugins/openai-bundled
|
||||
```
|
||||
|
||||
You can also register it explicitly from a shell with Codex:
|
||||
|
||||
```bash
|
||||
codex plugin marketplace add /Applications/Codex.app/Contents/Resources/plugins/openai-bundled
|
||||
```
|
||||
|
||||
If you use a nonstandard Codex app path, run `/codex computer-use install
|
||||
--source <marketplace-root>` once, or set `computerUse.marketplacePath` to a
|
||||
local marketplace file path. Use `--marketplace-path` only when you have the
|
||||
marketplace JSON file path, not the bundled marketplace root.
|
||||
|
||||
## Remote catalog limit
|
||||
|
||||
Codex app-server can list and read remote-only catalog entries, but it does
|
||||
not currently support remote `plugin/install`. That means `marketplaceName`
|
||||
can select a remote-only marketplace for status checks, but installs and
|
||||
re-enables still need a local marketplace via `marketplaceSource` or
|
||||
`marketplacePath`.
|
||||
|
||||
If status says the plugin is available in a remote Codex marketplace but
|
||||
remote install is unsupported, run install with a local source or path:
|
||||
|
||||
```text
|
||||
/codex computer-use install --source <marketplace-source>
|
||||
/codex computer-use install --marketplace-path <path>
|
||||
```
|
||||
|
||||
## Configuration reference
|
||||
|
||||
| Field | Default | Meaning |
|
||||
| ------------------------------- | -------------- | ------------------------------------------------------------------------------ |
|
||||
| `enabled` | inferred | Require Computer Use. Defaults to true when another Computer Use field is set. |
|
||||
| `autoInstall` | false | Install or re-enable from already discovered marketplaces at turn start. |
|
||||
| `marketplaceDiscoveryTimeoutMs` | 60000 | How long install waits for Codex app-server marketplace discovery. |
|
||||
| `marketplaceSource` | unset | Source string passed to Codex app-server `marketplace/add`. |
|
||||
| `marketplacePath` | unset | Local Codex marketplace file path containing the plugin. |
|
||||
| `marketplaceName` | unset | Registered Codex marketplace name to select. |
|
||||
| `pluginName` | `computer-use` | Codex marketplace plugin name. |
|
||||
| `mcpServerName` | `computer-use` | MCP server name exposed by the installed plugin. |
|
||||
|
||||
Turn-start auto-install intentionally refuses configured `marketplaceSource`
|
||||
values. Adding a new source is an explicit setup operation, so use
|
||||
`/codex computer-use install --source <marketplace-source>` once, then let
|
||||
`autoInstall` handle future re-enables from discovered local marketplaces.
|
||||
Turn-start auto-install can use a configured `marketplacePath`, because that
|
||||
is already a local path on the host.
|
||||
|
||||
Each field also accepts an environment variable override, checked when the
|
||||
matching config key is unset:
|
||||
|
||||
| Field | Env var |
|
||||
| ------------------------------- | -------------------------------------------------------------- |
|
||||
| `enabled` | `OPENCLAW_CODEX_COMPUTER_USE` |
|
||||
| `autoInstall` | `OPENCLAW_CODEX_COMPUTER_USE_AUTO_INSTALL` |
|
||||
| `marketplaceDiscoveryTimeoutMs` | `OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS` |
|
||||
| `marketplaceSource` | `OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_SOURCE` |
|
||||
| `marketplacePath` | `OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_PATH` |
|
||||
| `marketplaceName` | `OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_NAME` |
|
||||
| `pluginName` | `OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_NAME` |
|
||||
| `mcpServerName` | `OPENCLAW_CODEX_COMPUTER_USE_MCP_SERVER_NAME` |
|
||||
|
||||
## What OpenClaw checks
|
||||
|
||||
OpenClaw reports a stable setup reason internally and formats the
|
||||
user-facing status for chat:
|
||||
|
||||
| Reason | Meaning | Next step |
|
||||
| ---------------------------- | ------------------------------------------------------ | --------------------------------------------- |
|
||||
| `disabled` | `computerUse.enabled` resolved to false. | Set `enabled` or another Computer Use field. |
|
||||
| `marketplace_missing` | No matching marketplace was available. | Configure source, path, or marketplace name. |
|
||||
| `plugin_not_installed` | Marketplace exists, but the plugin is not installed. | Run install or enable `autoInstall`. |
|
||||
| `plugin_disabled` | Plugin is installed but disabled in Codex config. | Run install to re-enable it. |
|
||||
| `remote_install_unsupported` | Selected marketplace is remote-only. | Use `marketplaceSource` or `marketplacePath`. |
|
||||
| `mcp_missing` | Plugin is enabled, but the MCP server is unavailable. | Check Codex Computer Use and OS permissions. |
|
||||
| `ready` | Plugin and MCP tools are available. | Start the Codex-mode turn. |
|
||||
| `check_failed` | A Codex app-server request failed during status check. | Check app-server connectivity and logs. |
|
||||
| `auto_install_blocked` | Turn-start setup would need to add a new source. | Run explicit install first. |
|
||||
|
||||
The chat output includes the plugin state, MCP server state, marketplace,
|
||||
tools when available, and the specific message for the failing setup step.
|
||||
|
||||
## macOS permissions
|
||||
|
||||
Computer Use is macOS-specific. The Codex-owned MCP server may need local OS
|
||||
permissions before it can inspect or control apps. If OpenClaw says Computer
|
||||
Use is installed but the MCP server is unavailable, verify the Codex-side
|
||||
Computer Use setup first:
|
||||
|
||||
- Codex app-server is running on the same host where desktop control should
|
||||
happen.
|
||||
- The Computer Use plugin is enabled in Codex config.
|
||||
- The `computer-use` MCP server appears in Codex app-server MCP status.
|
||||
- macOS has granted the required permissions for the desktop-control app.
|
||||
- The current host session can access the desktop being controlled.
|
||||
|
||||
OpenClaw intentionally fails closed when `computerUse.enabled` is true. A
|
||||
Codex-mode turn should not silently proceed without the native desktop tools
|
||||
that the config required.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Status says not installed.** Run `/codex computer-use install`. If the
|
||||
marketplace is not discovered, pass `--source` or `--marketplace-path`.
|
||||
|
||||
**Status says installed but disabled.** Run `/codex computer-use install`
|
||||
again. Codex app-server install writes the plugin config back to enabled.
|
||||
|
||||
**Status says remote install is unsupported.** Use a local marketplace
|
||||
source or path. Remote-only catalog entries can be inspected but not
|
||||
installed through the current app-server API.
|
||||
|
||||
**Status says the MCP server is unavailable.** Re-run install once so MCP
|
||||
servers reload. If it remains unavailable, fix the Codex Computer Use app,
|
||||
Codex app-server MCP status, or macOS permissions.
|
||||
|
||||
**Status or a probe times out on `computer-use.list_apps`.** The plugin and
|
||||
MCP server are present, but the local Computer Use bridge did not answer.
|
||||
Quit or restart Codex Computer Use, relaunch Codex Desktop if needed, then
|
||||
retry in a fresh OpenClaw session. If the host previously ran Computer Use
|
||||
through an older managed Codex app-server, refresh the installed plugin from
|
||||
the desktop bundled marketplace:
|
||||
|
||||
```text
|
||||
/codex computer-use install --source /Applications/Codex.app/Contents/Resources/plugins/openai-bundled
|
||||
```
|
||||
|
||||
**A Computer Use tool says `Native hook relay unavailable`.** The
|
||||
Codex-native tool hook could not reach an active OpenClaw relay through the
|
||||
local bridge or Gateway fallback. Start a fresh OpenClaw session with `/new`
|
||||
or `/reset`. If it works once and then fails again on a later tool call,
|
||||
`/new` is only clearing the current attempt; restart the Codex app-server or
|
||||
OpenClaw Gateway so old threads and hook registrations are dropped, then
|
||||
retry in a fresh session.
|
||||
|
||||
**Turn-start auto-install refuses a source.** This is intentional. Add the
|
||||
source with explicit `/codex computer-use install --source
|
||||
<marketplace-source>` first, then future turn-start auto-install can use the
|
||||
discovered local marketplace.
|
||||
|
||||
## Related
|
||||
|
||||
- [Codex harness](/plugins/codex-harness)
|
||||
- [Peekaboo bridge](/platforms/mac/peekaboo)
|
||||
- [iOS app](/platforms/ios)
|
||||
582
docs/plugins/codex-harness-reference.md
Normal file
582
docs/plugins/codex-harness-reference.md
Normal file
@@ -0,0 +1,582 @@
|
||||
---
|
||||
summary: "Configuration, auth, discovery, and app-server reference for the Codex harness"
|
||||
title: "Codex harness reference"
|
||||
read_when:
|
||||
- You need every Codex harness config field
|
||||
- You are changing app-server transport, auth, discovery, or timeout behavior
|
||||
- You are debugging Codex harness startup, model discovery, or environment isolation
|
||||
---
|
||||
|
||||
This reference covers detailed configuration for the bundled `codex` plugin.
|
||||
For setup and routing decisions, start with
|
||||
[Codex harness](/plugins/codex-harness).
|
||||
|
||||
## Plugin config surface
|
||||
|
||||
All Codex harness settings live under `plugins.entries.codex.config`.
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
discovery: {
|
||||
enabled: true,
|
||||
timeoutMs: 2500,
|
||||
},
|
||||
appServer: {
|
||||
mode: "guardian",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Top-level fields:
|
||||
|
||||
| Field | Default | Meaning |
|
||||
| -------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `discovery` | enabled | Model discovery settings for Codex app-server `model/list`. |
|
||||
| `appServer` | managed stdio app-server | Transport, command, auth, approval, sandbox, and timeout settings. |
|
||||
| `codexDynamicToolsLoading` | `"searchable"` | Use `"direct"` to put OpenClaw dynamic tools directly in the initial Codex tool context. |
|
||||
| `codexDynamicToolsExclude` | `[]` | Additional OpenClaw dynamic tool names to omit from Codex app-server turns. |
|
||||
| `codexPlugins` | disabled | Native Codex plugin/app support for migrated source-installed curated plugins. See [Native Codex plugins](/plugins/codex-native-plugins). |
|
||||
| `computerUse` | disabled | Codex Computer Use setup. See [Codex Computer Use](/plugins/codex-computer-use). |
|
||||
|
||||
## App-server transport
|
||||
|
||||
By default OpenClaw starts the managed Codex binary shipped with the bundled
|
||||
plugin (currently `@openai/codex` `0.142.5`):
|
||||
|
||||
```bash
|
||||
codex app-server --listen stdio://
|
||||
```
|
||||
|
||||
This keeps the app-server version tied to the bundled `codex` plugin instead of
|
||||
whichever separate Codex CLI happens to be installed locally. Set
|
||||
`appServer.command` only when you intentionally want a different executable.
|
||||
|
||||
For an already-running app-server, use WebSocket transport:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
transport: "websocket",
|
||||
url: "ws://gateway-host:39175",
|
||||
authToken: "${CODEX_APP_SERVER_TOKEN}",
|
||||
requestTimeoutMs: 60000,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`appServer` fields:
|
||||
|
||||
| Field | Default | Meaning |
|
||||
| --------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
|
||||
| `homeScope` | `"agent"` | `"agent"` isolates Codex state per OpenClaw agent. `"user"` shares the native `$CODEX_HOME` or `~/.codex`, uses native auth, and enables owner-only thread management. User scope requires stdio. |
|
||||
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary. |
|
||||
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
|
||||
| `url` | unset | WebSocket app-server URL. |
|
||||
| `authToken` | unset | Bearer token for WebSocket transport. Accepts a literal string or SecretInput such as `${CODEX_APP_SERVER_TOKEN}`. |
|
||||
| `headers` | `{}` | Extra WebSocket headers. Header values accept literal strings or SecretInput values, for example `x-codex-client-session-token: "${CODEX_CLIENT_SESSION_TOKEN}"`. |
|
||||
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. |
|
||||
| `remoteWorkspaceRoot` | unset | Remote Codex app-server workspace root. When set, OpenClaw infers the local workspace root from the resolved OpenClaw workspace, preserves the current cwd suffix under this remote root, and sends only the final app-server cwd to Codex. If the cwd is outside the resolved OpenClaw workspace root, OpenClaw fails closed instead of sending a gateway-local path to the remote app-server. |
|
||||
| `requestTimeoutMs` | `60000` | Timeout for app-server control-plane calls. |
|
||||
| `turnCompletionIdleTimeoutMs` | `60000` | Quiet window after Codex accepts a turn or after a turn-scoped app-server request while OpenClaw waits for `turn/completed`. |
|
||||
| `postToolRawAssistantCompletionIdleTimeoutMs` | `300000` | Completion-idle and progress guard used after a tool handoff, native tool completion, post-tool raw assistant progress, raw reasoning completion, or reasoning progress while OpenClaw waits for `turn/completed`. Use this for trusted or heavy workloads where post-tool synthesis can legitimately stay quiet longer than the final assistant release budget. |
|
||||
| `mode` | `"yolo"` unless local Codex requirements disallow YOLO | Preset for YOLO or guardian-reviewed execution. |
|
||||
| `approvalPolicy` | `"never"` or an allowed guardian approval policy | Native Codex approval policy sent to thread start, resume, and turn. |
|
||||
| `sandbox` | `"danger-full-access"` or an allowed guardian sandbox | Native Codex sandbox mode sent to thread start and resume. Active OpenClaw sandboxes narrow `danger-full-access` turns to Codex `workspace-write`; the turn network flag follows OpenClaw sandbox egress. |
|
||||
| `approvalsReviewer` | `"user"` or an allowed guardian reviewer | Use `"auto_review"` to let Codex review native approval prompts when allowed. |
|
||||
| `defaultWorkspaceDir` | current process directory | Workspace used by `/codex bind` when `--cwd` is omitted. |
|
||||
| `serviceTier` | unset | Optional Codex app-server service tier. `"priority"` enables fast-mode routing, `"flex"` requests flex processing, and `null` clears the override. Legacy `"fast"` is accepted as `"priority"`. |
|
||||
| `networkProxy` | disabled | Opt into Codex permissions-profile networking for app-server commands. OpenClaw defines the selected `permissions.<profile>.network` config and selects it with `default_permissions` instead of sending `sandbox`. |
|
||||
| `experimental.sandboxExecServer` | `false` | Preview opt-in that registers an OpenClaw sandbox-backed Codex environment with Codex app-server 0.132.0 or newer so native Codex execution can run inside the active OpenClaw sandbox. |
|
||||
|
||||
`appServer.networkProxy` is explicit because it changes the Codex sandbox
|
||||
contract. When enabled, OpenClaw also sets `features.network_proxy.enabled` and
|
||||
`default_permissions` in the Codex thread config so the generated permission
|
||||
profile can start Codex-managed networking. OpenClaw generates a
|
||||
collision-resistant `openclaw-network-<fingerprint>` profile name from the
|
||||
profile body by default; use `profileName` only when a stable local name is
|
||||
required.
|
||||
|
||||
```js
|
||||
export default {
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
config: {
|
||||
appServer: {
|
||||
sandbox: "workspace-write",
|
||||
networkProxy: {
|
||||
enabled: true,
|
||||
domains: {
|
||||
"api.openai.com": "allow",
|
||||
"blocked.example.com": "deny",
|
||||
},
|
||||
allowUpstreamProxy: true,
|
||||
proxyUrl: "http://127.0.0.1:3128",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
If the normal app-server runtime would be `danger-full-access`, enabling
|
||||
`networkProxy` uses workspace-style filesystem access for the generated
|
||||
permission profile instead. Codex-managed network enforcement is sandboxed
|
||||
networking, so a full-access profile would not protect outbound traffic.
|
||||
|
||||
The plugin blocks older or unversioned app-server handshakes: Codex app-server
|
||||
must report stable version `0.125.0` or newer.
|
||||
|
||||
OpenClaw treats non-loopback WebSocket app-server URLs as remote and requires
|
||||
identity-bearing WebSocket auth through `appServer.authToken` or an
|
||||
`Authorization` header. `appServer.authToken` and each `appServer.headers.*`
|
||||
value can be a SecretInput; the secrets runtime resolves SecretRefs and env
|
||||
shorthand before OpenClaw builds app-server start options, and unresolved
|
||||
structured SecretRefs fail before any token or header is sent. When native
|
||||
Codex plugins are configured, OpenClaw uses the connected app-server's plugin
|
||||
control plane to install or refresh those plugins and then refreshes app
|
||||
inventory so plugin-owned apps are visible to the Codex thread. `app/list` is
|
||||
still the authoritative inventory and metadata source, but OpenClaw policy
|
||||
decides whether `thread/start` sends `config.apps[appId].enabled = true` for a
|
||||
listed accessible app even if Codex currently marks it disabled. Unknown or
|
||||
missing app ids remain fail-closed; this path only activates marketplace
|
||||
plugins via `plugin/install` and refreshes inventory. Only connect OpenClaw to
|
||||
remote app-servers that are trusted to accept OpenClaw-managed plugin installs
|
||||
and app inventory refreshes.
|
||||
|
||||
## Approval and sandbox modes
|
||||
|
||||
Local stdio app-server sessions default to YOLO mode:
|
||||
`approvalPolicy: "never"`, `approvalsReviewer: "user"`, and
|
||||
`sandbox: "danger-full-access"`. This trusted local operator posture lets
|
||||
unattended OpenClaw turns and heartbeats make progress without native approval
|
||||
prompts that nobody is around to answer.
|
||||
|
||||
If Codex's local system requirements file disallows implicit YOLO approval,
|
||||
reviewer, or sandbox values, OpenClaw treats the implicit default as guardian
|
||||
instead and selects allowed guardian permissions. `tools.exec.mode: "auto"`
|
||||
also forces guardian-reviewed Codex approvals and does not preserve unsafe
|
||||
legacy `approvalPolicy: "never"` or `sandbox: "danger-full-access"` overrides;
|
||||
set `tools.exec.mode: "full"` for an intentional no-approval posture.
|
||||
Hostname-matching `[[remote_sandbox_config]]` entries in the same requirements
|
||||
file are honored for the sandbox default decision.
|
||||
|
||||
Set `appServer.mode: "guardian"` for Codex guardian-reviewed approvals:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
mode: "guardian",
|
||||
serviceTier: "priority",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The `guardian` preset expands to `approvalPolicy: "on-request"`,
|
||||
`approvalsReviewer: "auto_review"`, and `sandbox: "workspace-write"` when those
|
||||
values are allowed. Individual policy fields override `mode`. The older
|
||||
`guardian_subagent` reviewer value is still accepted as a compatibility alias,
|
||||
but new configs should use `auto_review`.
|
||||
|
||||
When an OpenClaw sandbox is active, the local Codex app-server process still
|
||||
runs on the Gateway host. OpenClaw therefore disables Codex native Code Mode,
|
||||
user MCP servers, and app-backed plugin execution for that turn instead of
|
||||
treating Codex host-side sandboxing as equivalent to the OpenClaw sandbox
|
||||
backend. Shell access is exposed through OpenClaw sandbox-backed dynamic tools
|
||||
such as `sandbox_exec` and `sandbox_process` when the normal exec/process tools
|
||||
are available.
|
||||
|
||||
<Note>
|
||||
On Docker-backed OpenClaw sandbox hosts (`agents.defaults.sandbox.mode` set to
|
||||
a Docker backend), `openclaw doctor` probes whether the host allows the
|
||||
unprivileged user (and, when Docker sandbox network egress is disabled,
|
||||
network) namespaces that nested Codex `bwrap` needs for `workspace-write`
|
||||
shell execution inside the sandbox container. A failed probe usually surfaces
|
||||
as `bwrap: setting up uid map: Permission denied` or
|
||||
`bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted` on
|
||||
Ubuntu/AppArmor hosts. Fix the reported host namespace policy for the OpenClaw
|
||||
service user and restart the gateway; prefer a scoped AppArmor profile for the
|
||||
service process over the host-wide
|
||||
`kernel.apparmor_restrict_unprivileged_userns=0` fallback, and do not grant
|
||||
broader Docker container privileges just to satisfy nested `bwrap`.
|
||||
</Note>
|
||||
|
||||
## Sandboxed native execution
|
||||
|
||||
The stable default is fail-closed: active OpenClaw sandboxing disables native
|
||||
Codex execution surfaces that would otherwise run from the Codex app-server
|
||||
host. Use `appServer.experimental.sandboxExecServer: true` only when you want
|
||||
to try Codex's remote environment support with OpenClaw's sandbox backend.
|
||||
This preview path requires Codex app-server 0.132.0 or newer.
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
experimental: {
|
||||
sandboxExecServer: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
When the flag is on and the current OpenClaw session is sandboxed, OpenClaw
|
||||
starts a local loopback exec-server backed by the active sandbox, registers it
|
||||
with Codex app-server, and starts the Codex thread and turn with that
|
||||
OpenClaw-owned environment. If the app-server cannot register the environment,
|
||||
the run fails closed instead of silently falling back to host execution.
|
||||
|
||||
This preview path is local-only. A remote WebSocket app-server cannot reach
|
||||
the loopback exec-server unless it is running on the same host, so OpenClaw
|
||||
rejects that combination.
|
||||
|
||||
## Auth and environment isolation
|
||||
|
||||
In the default per-agent home, auth is selected in this order:
|
||||
|
||||
1. An explicit OpenClaw Codex auth profile for the agent.
|
||||
2. The app-server's existing account in that agent's Codex home.
|
||||
3. For local stdio app-server launches only, `CODEX_API_KEY`, then
|
||||
`OPENAI_API_KEY`, when no app-server account is present and OpenAI auth is
|
||||
still required.
|
||||
|
||||
When OpenClaw sees a ChatGPT subscription-style Codex auth profile (OAuth or
|
||||
token credential type), it removes `CODEX_API_KEY` and `OPENAI_API_KEY` from
|
||||
the spawned Codex child process. That keeps Gateway-level API keys available
|
||||
for embeddings or direct OpenAI models without making native Codex app-server
|
||||
turns bill through the API by accident.
|
||||
|
||||
Explicit Codex API-key profiles and local stdio env-key fallback use
|
||||
app-server login instead of inherited child-process env. WebSocket app-server
|
||||
connections do not receive Gateway env API-key fallback; use an explicit auth
|
||||
profile or the remote app-server's own account.
|
||||
|
||||
Stdio app-server launches inherit OpenClaw's process environment by default.
|
||||
OpenClaw owns the Codex app-server account bridge and sets `CODEX_HOME` to a
|
||||
per-agent directory under that agent's OpenClaw state. That keeps Codex
|
||||
config, accounts, plugin cache/data, and thread state scoped to the OpenClaw
|
||||
agent instead of leaking in from the operator's personal `~/.codex` home.
|
||||
|
||||
Set `appServer.homeScope: "user"` to share native Codex state with Codex
|
||||
Desktop and the CLI. This local-stdio-only mode uses `$CODEX_HOME` when set
|
||||
and `~/.codex` otherwise, including native auth, config, plugins, and threads.
|
||||
OpenClaw skips its auth-profile bridge for the app-server. Verified owner
|
||||
turns can use `codex_threads` to list (with an optional `search` filter),
|
||||
read, fork, rename, archive, and unarchive those threads. Fork a thread before
|
||||
continuing it in OpenClaw; independent Codex processes do not coordinate
|
||||
concurrent writers for the same thread.
|
||||
|
||||
OpenClaw does not rewrite `HOME` for normal local app-server launches.
|
||||
Codex-run subprocesses such as `openclaw`, `gh`, `git`, cloud CLIs, and shell
|
||||
commands see the normal process home and can find user-home config and
|
||||
tokens. Codex may also discover `$HOME/.agents/skills` and
|
||||
`$HOME/.agents/plugins/marketplace.json`; that `.agents` discovery is
|
||||
intentionally shared with the operator home and is separate from isolated
|
||||
`~/.codex` state.
|
||||
|
||||
In the default agent scope, OpenClaw plugins and OpenClaw skill snapshots
|
||||
still flow through OpenClaw's own plugin registry and skill loader; personal
|
||||
Codex `~/.codex` assets do not. If you have useful Codex CLI skills or
|
||||
plugins from a Codex home that should become part of an isolated OpenClaw
|
||||
agent, inventory them explicitly:
|
||||
|
||||
```bash
|
||||
openclaw migrate codex --dry-run
|
||||
openclaw migrate apply codex --yes
|
||||
```
|
||||
|
||||
If a deployment needs additional environment isolation, add those variables
|
||||
to `appServer.clearEnv`:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
clearEnv: ["CODEX_API_KEY", "OPENAI_API_KEY"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`appServer.clearEnv` only affects the spawned Codex app-server child process.
|
||||
OpenClaw removes `CODEX_HOME` and `HOME` from this list during local launch
|
||||
normalization: `CODEX_HOME` stays pointed at the selected agent or user scope,
|
||||
and `HOME` stays inherited so subprocesses can use normal user-home state.
|
||||
|
||||
## Dynamic tools
|
||||
|
||||
Codex dynamic tools default to `searchable` loading, exposed under the
|
||||
`openclaw` namespace with `deferLoading: true`. OpenClaw does not expose
|
||||
dynamic tools that duplicate Codex-native workspace operations or Codex's own
|
||||
tool-search surface:
|
||||
|
||||
- `read`
|
||||
- `write`
|
||||
- `edit`
|
||||
- `apply_patch`
|
||||
- `exec`
|
||||
- `process`
|
||||
- `update_plan`
|
||||
- `tool_call`
|
||||
- `tool_describe`
|
||||
- `tool_search`
|
||||
- `tool_search_code`
|
||||
|
||||
Most remaining OpenClaw integration tools, such as messaging, media, cron,
|
||||
browser, nodes, gateway, `heartbeat_respond`, and `web_search`, are available
|
||||
through Codex tool search under that namespace. This keeps the initial model
|
||||
context smaller. A small set of tools stay directly callable regardless of
|
||||
`codexDynamicToolsLoading`, because Codex tool search can be unavailable or
|
||||
resolve a connector-only universe: `agents_list`, `sessions_spawn`, and
|
||||
`sessions_yield`. Developer instructions still steer normal Codex subagents
|
||||
toward native `spawn_agent` for Codex-native subagent work, while
|
||||
`sessions_spawn` remains available for explicit OpenClaw or ACP delegation.
|
||||
Message-tool-only source replies also stay direct, since that is a
|
||||
turn-control contract.
|
||||
|
||||
Set `codexDynamicToolsLoading: "direct"` only when connecting to a custom
|
||||
Codex app-server that cannot search deferred dynamic tools or when debugging
|
||||
the full tool payload.
|
||||
|
||||
## Timeouts
|
||||
|
||||
OpenClaw-owned dynamic tool calls are bounded independently from
|
||||
`appServer.requestTimeoutMs`. Each Codex `item/tool/call` request uses the
|
||||
first available timeout in this order:
|
||||
|
||||
- A positive per-call `timeoutMs` argument.
|
||||
- For `image_generate`, `agents.defaults.imageGenerationModel.timeoutMs`.
|
||||
- For `image_generate` without a configured timeout, the 120 second
|
||||
image-generation default.
|
||||
- For the media-understanding `image` tool, `tools.media.image.timeoutSeconds`
|
||||
converted to milliseconds, or the 60 second media default. For image
|
||||
understanding, this applies to the request itself and is not reduced by
|
||||
earlier preparation work.
|
||||
- For the `message` tool, a fixed 120 second default.
|
||||
- The 90 second dynamic-tool default.
|
||||
|
||||
This watchdog is the outer dynamic `item/tool/call` budget. Provider-specific
|
||||
request timeouts run inside that call and keep their own timeout semantics.
|
||||
Dynamic tool budgets are capped at 600000 ms. On timeout, OpenClaw aborts the
|
||||
tool signal where supported and returns a failed dynamic-tool response to
|
||||
Codex so the turn can continue instead of leaving the session in
|
||||
`processing`.
|
||||
|
||||
After Codex accepts a turn, and after OpenClaw responds to a turn-scoped
|
||||
app-server request, the harness expects Codex to make current-turn progress
|
||||
and eventually finish the native turn with `turn/completed`. If the
|
||||
app-server goes quiet for `appServer.turnCompletionIdleTimeoutMs`, OpenClaw
|
||||
best-effort interrupts the Codex turn, records a diagnostic timeout, and
|
||||
releases the OpenClaw session lane so follow-up chat messages are not queued
|
||||
behind a stale native turn.
|
||||
|
||||
Most non-terminal notifications for the same turn disarm that short watchdog
|
||||
because Codex has proven the turn is still alive. Tool handoffs use a longer
|
||||
post-tool idle budget: after OpenClaw returns an `item/tool/call` response,
|
||||
after native tool items such as `commandExecution` complete, after raw
|
||||
`custom_tool_call_output` completions, and after post-tool raw assistant
|
||||
progress, raw reasoning completions, or reasoning progress. The guard uses
|
||||
`appServer.postToolRawAssistantCompletionIdleTimeoutMs` when configured and
|
||||
defaults to five minutes otherwise. That same post-tool budget also extends
|
||||
the progress watchdog for the silent synthesis window before Codex emits the
|
||||
next current-turn event. Reasoning completions, commentary `agentMessage`
|
||||
completions, and pre-tool raw reasoning or assistant progress can be followed
|
||||
by an automatic final reply, so they use the post-progress reply guard
|
||||
instead of releasing the session lane immediately. Only final/non-commentary
|
||||
completed `agentMessage` items and pre-tool raw assistant completions arm the
|
||||
assistant-output release: if Codex then goes quiet without `turn/completed`,
|
||||
OpenClaw best-effort interrupts the native turn and releases the session
|
||||
lane. Replay-safe stdio app-server failures, including turn-completion idle
|
||||
timeouts without assistant, tool, active-item, or side-effect evidence, are
|
||||
retried once on a fresh app-server attempt. Unsafe timeouts still retire the
|
||||
stuck app-server client and release the OpenClaw session lane. They also
|
||||
clear the stale native thread binding instead of being replayed
|
||||
automatically. Completion-watch timeouts surface Codex-specific timeout text:
|
||||
replay-safe cases say the response may be incomplete, while unsafe cases tell
|
||||
the user to verify current state before retrying. Public timeout diagnostics
|
||||
include structural fields such as the last app-server notification method,
|
||||
raw assistant response item id/type/role, active request/item counts, and
|
||||
armed watch state. When the last notification is a raw assistant response
|
||||
item, they also include a bounded assistant text preview. They do not
|
||||
include raw prompt or tool content.
|
||||
|
||||
## Model discovery
|
||||
|
||||
By default, the Codex plugin asks the app-server for available models. Model
|
||||
availability is owned by Codex app-server, so the list can change when
|
||||
OpenClaw upgrades the bundled `@openai/codex` version or when a deployment
|
||||
points `appServer.command` at a different Codex binary. Availability can also
|
||||
be account-scoped. Use `/codex models` on a running gateway to see the live
|
||||
catalog for that harness and account.
|
||||
|
||||
If discovery fails or times out, OpenClaw uses a bundled fallback catalog:
|
||||
|
||||
| Model id | Display name | Reasoning efforts |
|
||||
| -------------- | ------------ | ------------------------ |
|
||||
| `gpt-5.5` | gpt-5.5 | low, medium, high, xhigh |
|
||||
| `gpt-5.4-mini` | GPT-5.4-Mini | low, medium, high, xhigh |
|
||||
|
||||
<Note>
|
||||
The current bundled harness is `@openai/codex` `0.142.5`. A `model/list` probe
|
||||
against that bundled app-server returned these public picker rows beyond the
|
||||
fallback catalog:
|
||||
|
||||
| Model id | Input modalities | Reasoning efforts |
|
||||
| --------------------- | ---------------- | ------------------------ |
|
||||
| `gpt-5.5` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.4` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.4-mini` | text, image | low, medium, high, xhigh |
|
||||
| `gpt-5.3-codex-spark` | text | low, medium, high, xhigh |
|
||||
|
||||
Live picker rows are account-scoped and can change with the account, Codex
|
||||
catalog, or bundled version; run `/codex models` for the current list rather
|
||||
than relying on any point-in-time table. Hidden models can also appear in the
|
||||
app-server catalog for internal or specialized flows without being normal
|
||||
model-picker choices.
|
||||
</Note>
|
||||
|
||||
Tune discovery under `plugins.entries.codex.config.discovery`:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
discovery: {
|
||||
enabled: true,
|
||||
timeoutMs: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Disable discovery when you want startup to avoid probing Codex and use only
|
||||
the fallback catalog:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
discovery: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Workspace bootstrap files
|
||||
|
||||
Codex handles `AGENTS.md` itself through native project-doc discovery.
|
||||
OpenClaw does not write synthetic Codex project-doc files or depend on Codex
|
||||
fallback filenames for persona files, because Codex fallbacks only apply when
|
||||
`AGENTS.md` is missing.
|
||||
|
||||
For OpenClaw workspace parity, the Codex harness forwards the other
|
||||
bootstrap files as developer instructions, but not identically:
|
||||
|
||||
- `TOOLS.md` is forwarded as **inherited** Codex developer instructions, so
|
||||
native Codex subagents spawned during the turn also see it.
|
||||
- `SOUL.md`, `IDENTITY.md`, and `USER.md` are forwarded as **turn-scoped**
|
||||
collaboration instructions. Native Codex subagents do not inherit them,
|
||||
which keeps subagent turns from picking up the parent agent's persona and
|
||||
user profile.
|
||||
- The compact loaded OpenClaw skills list is also forwarded as turn-scoped
|
||||
collaboration developer instructions, so native Codex subagents do not
|
||||
inherit it either.
|
||||
- `HEARTBEAT.md` content is not injected; heartbeat turns get a
|
||||
collaboration-mode pointer to read the file when it exists and is
|
||||
non-empty.
|
||||
- `MEMORY.md` content from the configured agent workspace is not pasted into
|
||||
native Codex turn input when memory tools are available for that
|
||||
workspace; when it exists, the harness adds a small workspace-memory
|
||||
pointer to turn-scoped collaboration developer instructions and Codex
|
||||
should use `memory_search` or `memory_get` when durable memory is relevant.
|
||||
If tools are disabled, memory search is unavailable, or the active
|
||||
workspace differs from the agent memory workspace, `MEMORY.md` uses the
|
||||
normal bounded turn-context path instead.
|
||||
- `BOOTSTRAP.md`, when present, is forwarded as OpenClaw turn input reference
|
||||
context.
|
||||
|
||||
## Environment overrides
|
||||
|
||||
Environment overrides remain available for local testing:
|
||||
|
||||
- `OPENCLAW_CODEX_APP_SERVER_BIN`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_ARGS`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_MODE=yolo|guardian`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_SANDBOX`
|
||||
|
||||
`OPENCLAW_CODEX_APP_SERVER_BIN` bypasses the managed binary when
|
||||
`appServer.command` is unset.
|
||||
|
||||
`OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1` was removed. Use
|
||||
`plugins.entries.codex.config.appServer.mode: "guardian"` instead, or
|
||||
`OPENCLAW_CODEX_APP_SERVER_MODE=guardian` for one-off local testing. Config is
|
||||
preferred for repeatable deployments because it keeps the plugin behavior in
|
||||
the same reviewed file as the rest of the Codex harness setup.
|
||||
|
||||
## Related
|
||||
|
||||
- [Codex harness](/plugins/codex-harness)
|
||||
- [Codex harness runtime](/plugins/codex-harness-runtime)
|
||||
- [Native Codex plugins](/plugins/codex-native-plugins)
|
||||
- [Codex Computer Use](/plugins/codex-computer-use)
|
||||
- [OpenAI provider](/providers/openai)
|
||||
- [Configuration reference](/gateway/configuration-reference)
|
||||
264
docs/plugins/codex-harness-runtime.md
Normal file
264
docs/plugins/codex-harness-runtime.md
Normal file
@@ -0,0 +1,264 @@
|
||||
---
|
||||
summary: "Runtime boundaries, hooks, tools, permissions, and diagnostics for the Codex harness"
|
||||
title: "Codex harness runtime"
|
||||
read_when:
|
||||
- You need the Codex harness runtime support contract
|
||||
- You are debugging native Codex tools, hooks, compaction, or feedback upload
|
||||
- You are changing plugin behavior across OpenClaw and Codex harness turns
|
||||
---
|
||||
|
||||
Runtime contract for Codex harness turns. For setup and routing, see
|
||||
[Codex harness](/plugins/codex-harness). For config fields, see
|
||||
[Codex harness reference](/plugins/codex-harness-reference).
|
||||
|
||||
## Overview
|
||||
|
||||
Codex owns the native model loop, native thread resume, native tool
|
||||
continuation, and native compaction. OpenClaw owns channel routing, session
|
||||
files, visible message delivery, OpenClaw dynamic tools, approvals, media
|
||||
delivery, and a transcript mirror around that boundary.
|
||||
|
||||
Prompt routing follows the selected runtime, not just the provider string. A
|
||||
native Codex turn gets Codex app-server developer instructions; an explicit
|
||||
OpenClaw compatibility route keeps the normal OpenClaw system prompt even when
|
||||
it uses Codex-flavored OpenAI auth or transport.
|
||||
|
||||
OpenClaw starts and resumes native Codex threads with Codex's built-in
|
||||
personality disabled (`personality: "none"`) so workspace personality files
|
||||
and OpenClaw agent identity stay authoritative. Native Codex keeps Codex-owned
|
||||
base/model instructions and project-doc loading otherwise. Lightweight
|
||||
OpenClaw runs (for example cron) still suppress project-doc loading.
|
||||
|
||||
OpenClaw developer instructions cover OpenClaw runtime concerns: source-channel
|
||||
delivery, OpenClaw dynamic tools, ACP delegation, adapter context, and the
|
||||
active agent workspace profile files. Skill catalogs and tool-routed
|
||||
`MEMORY.md` pointers are projected as turn-scoped collaboration developer
|
||||
instructions. When memory tools are unavailable, active `BOOTSTRAP.md` content
|
||||
and full `MEMORY.md` fall back to plain turn input context instead.
|
||||
|
||||
## Thread bindings and model changes
|
||||
|
||||
When an OpenClaw session is attached to an existing Codex thread, the next
|
||||
turn resends the currently selected model, approval policy, sandbox,
|
||||
approvals reviewer, and service tier to app-server. Switching from
|
||||
`openai/gpt-5.5` to `openai/gpt-5.2` keeps the thread binding but asks Codex to
|
||||
continue with the newly selected model.
|
||||
|
||||
## Visible replies and heartbeats
|
||||
|
||||
Direct/source chat turns through the Codex harness default to automatic final
|
||||
assistant delivery for internal WebChat surfaces, matching the Pi harness
|
||||
contract: the agent replies normally and OpenClaw posts the final text to the
|
||||
source conversation. Set `messages.visibleReplies: "message_tool"` to keep
|
||||
final assistant text private unless the agent calls `message(action="send")`.
|
||||
|
||||
Codex heartbeat turns get `heartbeat_respond` in the searchable OpenClaw tool
|
||||
catalog by default so the agent can record whether the wake should stay quiet
|
||||
or notify. Heartbeat initiative guidance is sent as a Codex collaboration-mode
|
||||
developer instruction scoped to the heartbeat turn; ordinary chat turns stay
|
||||
in Codex Default mode. When `HEARTBEAT.md` is non-empty, the heartbeat
|
||||
instructions point Codex at the file instead of inlining its contents.
|
||||
|
||||
## Hook boundaries
|
||||
|
||||
| Layer | Owner | Purpose |
|
||||
| ------------------------------------- | ------------------------ | ------------------------------------------------------------------- |
|
||||
| OpenClaw plugin hooks | OpenClaw | Product/plugin compatibility across OpenClaw and Codex harnesses. |
|
||||
| Codex app-server extension middleware | OpenClaw bundled plugins | Per-turn adapter behavior around OpenClaw dynamic tools. |
|
||||
| Codex native hooks | Codex | Low-level Codex lifecycle and native tool policy from Codex config. |
|
||||
|
||||
OpenClaw does not use project or global Codex `hooks.json` files to route
|
||||
plugin behavior. For the native tool and permission bridge, OpenClaw injects
|
||||
per-thread Codex config for `PreToolUse`, `PostToolUse`, `PermissionRequest`,
|
||||
and `Stop`.
|
||||
|
||||
When Codex app-server approvals are enabled (`approvalPolicy` is not
|
||||
`"never"`), the default injected native hook config omits `PermissionRequest`
|
||||
so Codex's app-server reviewer and OpenClaw's approval bridge handle real
|
||||
escalations after review. Add `permission_request` to
|
||||
`nativeHookRelay.events` to force the compatibility relay anyway. Other Codex
|
||||
hooks such as `SessionStart` and `UserPromptSubmit` remain Codex-level
|
||||
controls; they are not exposed as OpenClaw plugin hooks in the v1 contract.
|
||||
|
||||
For OpenClaw dynamic tools, OpenClaw executes the tool after Codex asks for
|
||||
the call, so plugin and middleware behavior runs in the harness adapter. For
|
||||
Codex-native tools, Codex owns the canonical tool record; OpenClaw can mirror
|
||||
selected events but cannot rewrite the native thread unless Codex exposes that
|
||||
through app-server or native hook callbacks.
|
||||
|
||||
Codex app-server report-mode `PreToolUse` events defer plugin approval to the
|
||||
matching app-server approval. If an OpenClaw `before_tool_call` hook returns
|
||||
`requireApproval` while the native payload sets `openclaw_approval_mode:
|
||||
"report"`, the native hook relay records the plugin approval requirement and
|
||||
returns no native decision. When Codex later sends the app-server approval
|
||||
request for the same tool use, OpenClaw opens the plugin approval prompt and
|
||||
maps the decision back to Codex. Codex `PermissionRequest` events are a
|
||||
separate approval path and can still route through OpenClaw approvals when
|
||||
configured for that bridge.
|
||||
|
||||
Codex app-server item notifications also provide async `after_tool_call`
|
||||
observations for native tool completions not already covered by the native
|
||||
`PostToolUse` relay. These are telemetry/compatibility only; they cannot
|
||||
block, delay, or mutate the native tool call.
|
||||
|
||||
Compaction and LLM lifecycle projections come from Codex app-server
|
||||
notifications and OpenClaw adapter state, not native Codex hook commands.
|
||||
`before_compaction`, `after_compaction`, `llm_input`, and `llm_output` are
|
||||
adapter-level observations, not byte-for-byte captures of Codex's internal
|
||||
request or compaction payloads.
|
||||
|
||||
Codex native `hook/started` and `hook/completed` app-server notifications are
|
||||
projected as `codex_app_server.hook` agent events for trajectory and
|
||||
debugging. They do not invoke OpenClaw plugin hooks.
|
||||
|
||||
## V1 support contract
|
||||
|
||||
Supported in Codex runtime v1:
|
||||
|
||||
| Surface | Support | Why |
|
||||
| --------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| OpenAI model loop through Codex | Supported | Codex app-server owns the OpenAI turn, native thread resume, and native tool continuation. |
|
||||
| OpenClaw channel routing and delivery | Supported | Telegram, Discord, Slack, WhatsApp, iMessage, and other channels stay outside the model runtime. |
|
||||
| OpenClaw dynamic tools | Supported | Codex asks OpenClaw to execute these tools, so OpenClaw stays in the execution path. |
|
||||
| Prompt and context plugins | Supported | OpenClaw projects OpenClaw-specific prompt/context into the Codex turn while leaving Codex-owned base, model, and configured project-doc prompts in the native Codex lane. OpenClaw disables Codex's built-in personality for native threads so agent workspace personality files remain authoritative. Native Codex developer instructions accept only command guidance explicitly scoped to `codex_app_server`; legacy global command hints remain for non-Codex prompt surfaces. |
|
||||
| Context engine lifecycle | Supported | Assemble, ingest, and after-turn maintenance run around Codex turns. Context engines do not replace native Codex compaction. |
|
||||
| Dynamic tool hooks | Supported | `before_tool_call`, `after_tool_call`, and tool-result middleware run around OpenClaw-owned dynamic tools. |
|
||||
| Lifecycle hooks | Supported as adapter observations | `llm_input`, `llm_output`, `agent_end`, `before_compaction`, and `after_compaction` fire with honest Codex-mode payloads. |
|
||||
| Final-answer revision gate | Supported through native hook relay | Codex `Stop` is relayed to `before_agent_finalize`; `revise` asks Codex for one more model pass before finalization. |
|
||||
| Native shell, patch, and MCP block or observe | Supported through native hook relay | Codex `PreToolUse` and `PostToolUse` are relayed for committed native tool surfaces, including MCP payloads on Codex app-server `0.125.0` or newer. Blocking is supported; argument rewriting is not. |
|
||||
| Native permission policy | Supported through Codex app-server approvals and compatibility native hook relay | Codex app-server approval requests route through OpenClaw after Codex review. The `PermissionRequest` native hook relay is opt-in for native approval modes because Codex emits it before guardian review. |
|
||||
| App-server trajectory capture | Supported | OpenClaw records the request it sent to app-server and the app-server notifications it receives. |
|
||||
|
||||
Not supported in Codex runtime v1:
|
||||
|
||||
| Surface | V1 boundary | Future path |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| Native tool argument mutation | Codex native pre-tool hooks can block, but OpenClaw does not rewrite Codex-native tool arguments. | Requires Codex hook/schema support for replacement tool input. |
|
||||
| Editable Codex-native transcript history | Codex owns canonical native thread history. OpenClaw owns a mirror and can project future context, but should not mutate unsupported internals. | Add explicit Codex app-server APIs if native thread surgery is needed. |
|
||||
| `tool_result_persist` for Codex-native tool records | That hook transforms OpenClaw-owned transcript writes, not Codex-native tool records. | Could mirror transformed records, but canonical rewrite needs Codex support. |
|
||||
| Rich native compaction metadata | OpenClaw can request native compaction, but does not receive a stable kept/dropped list, token delta, completion summary, or summary payload. | Needs richer Codex compaction events. |
|
||||
| Compaction intervention | OpenClaw does not let plugins or context engines veto, rewrite, or replace native Codex compaction. | Add Codex pre/post compaction hooks if plugins need to veto or rewrite native compaction. |
|
||||
| Byte-for-byte model API request capture | OpenClaw can capture app-server requests and notifications, but Codex core builds the final OpenAI API request internally. | Needs a Codex model-request tracing event or debug API. |
|
||||
|
||||
## Native permissions and MCP elicitations
|
||||
|
||||
For `PermissionRequest`, OpenClaw only returns explicit allow or deny
|
||||
decisions when policy decides. A no-decision result is not an allow: Codex
|
||||
treats it as no hook decision and falls through to its own guardian or user
|
||||
approval path.
|
||||
|
||||
Codex app-server approval modes omit this native hook by default. This
|
||||
applies unless `permission_request` is explicitly included in
|
||||
`nativeHookRelay.events` or a compatibility runtime installs it.
|
||||
|
||||
When an operator chooses `allow-always` for a Codex native permission
|
||||
request, OpenClaw remembers that exact provider/session/tool input/cwd
|
||||
fingerprint for a bounded session window. The remembered decision is
|
||||
intentionally exact-match only: a changed command, arguments, tool payload, or
|
||||
cwd creates a fresh approval.
|
||||
|
||||
Codex MCP tool approval elicitations route through OpenClaw's plugin approval
|
||||
flow when Codex marks `_meta.codex_approval_kind` as `"mcp_tool_call"`. Codex
|
||||
`request_user_input` prompts are sent back to the originating chat, and the
|
||||
next queued follow-up message answers that native server request instead of
|
||||
being steered as extra context. Other MCP elicitation requests fail closed.
|
||||
|
||||
For the general plugin approval flow that carries these prompts, see
|
||||
[Plugin permission requests](/plugins/plugin-permission-requests).
|
||||
|
||||
## Queue steering
|
||||
|
||||
Active-run queue steering maps onto Codex app-server `turn/steer`. With the
|
||||
default `messages.queue.mode: "steer"`, OpenClaw batches steer-mode chat
|
||||
messages for the configured quiet window and sends them as one `turn/steer`
|
||||
request in arrival order.
|
||||
|
||||
Codex review and manual compaction turns can reject same-turn steering. In
|
||||
that case, OpenClaw waits for the active run to finish before starting the
|
||||
prompt. Use `/queue followup` or `/queue collect` when messages should queue
|
||||
by default instead of steering. See [Steering queue](/concepts/queue-steering).
|
||||
|
||||
## Codex feedback upload
|
||||
|
||||
When `/diagnostics [note]` is approved for a session on the native Codex
|
||||
harness, OpenClaw also calls Codex app-server `feedback/upload` for relevant
|
||||
Codex threads, including logs for each listed thread and spawned Codex
|
||||
subthreads when available.
|
||||
|
||||
The upload goes through Codex's normal feedback path to OpenAI servers. If
|
||||
Codex feedback is disabled in that app-server, the command returns the
|
||||
app-server error. The completed diagnostics reply lists the channels,
|
||||
OpenClaw session ids, Codex thread ids, and local `codex resume <thread-id>`
|
||||
commands for the threads that were sent.
|
||||
|
||||
If you deny or ignore the approval, OpenClaw does not print those Codex ids
|
||||
and does not send Codex feedback. The upload does not replace the local
|
||||
Gateway diagnostics export. See [Diagnostics export](/gateway/diagnostics) for
|
||||
the approval, privacy, local bundle, and group-chat behavior.
|
||||
|
||||
Use `/codex diagnostics [note]` only when you want the Codex feedback upload
|
||||
for the currently attached thread without the full Gateway diagnostics
|
||||
bundle.
|
||||
|
||||
## Compaction and transcript mirror
|
||||
|
||||
When the selected model uses the Codex harness, native thread compaction
|
||||
belongs to Codex app-server. OpenClaw does not run preflight compaction for
|
||||
Codex turns, replace Codex compaction with context-engine compaction, or fall
|
||||
back to OpenClaw or public OpenAI summarization when native compaction cannot
|
||||
be started. OpenClaw keeps a transcript mirror for channel history, search,
|
||||
`/new`, `/reset`, and future model or harness switching.
|
||||
|
||||
Explicit compaction requests, such as `/compact` or a plugin-requested manual
|
||||
compact operation, start native Codex compaction with `thread/compact/start`.
|
||||
OpenClaw keeps the request and shared-client lease open until Codex emits the
|
||||
matching `contextCompaction` completion item and then reports the compaction
|
||||
turn as completed. If that terminal turn exceeds the configured compaction
|
||||
timeout, OpenClaw requests a native turn interrupt. The lease and per-thread
|
||||
compaction fence remain held until Codex reports terminal state or confirms
|
||||
the interrupt RPC. If Codex does not confirm within the interrupt grace
|
||||
period, OpenClaw retires the connection before releasing the fence. Remote
|
||||
connections also detach the matching thread binding so later work cannot
|
||||
overlap an unconfirmed remote turn. Other turns on a retired connection fail
|
||||
and can retry on a fresh client. Client closure, request cancellation, or a
|
||||
failed compaction turn returns a failed operation. Automatic context-pressure
|
||||
compaction is Codex's job; OpenClaw only starts native compaction for manually
|
||||
requested triggers.
|
||||
|
||||
When a context engine requests Codex thread-bootstrap projection, OpenClaw
|
||||
projects tool-call names and ids, input shapes, and redacted tool-result
|
||||
content into the fresh Codex thread. It does not copy raw tool-call argument
|
||||
values into that projection.
|
||||
|
||||
The mirror includes the user prompt, final assistant text, and lightweight
|
||||
Codex reasoning or plan records when the app-server emits them. OpenClaw
|
||||
records the native compaction start and terminal status, but it does not
|
||||
expose a human-readable compaction summary or an auditable list of which
|
||||
entries Codex kept after compaction.
|
||||
|
||||
Because Codex owns the canonical native thread, `tool_result_persist` does
|
||||
not rewrite Codex-native tool result records. It only applies when OpenClaw
|
||||
writes an OpenClaw-owned session transcript tool result.
|
||||
|
||||
## Media and delivery
|
||||
|
||||
OpenClaw continues to own media delivery and media provider selection. Image,
|
||||
video, music, PDF, TTS, and media understanding use matching provider/model
|
||||
settings such as `agents.defaults.imageGenerationModel`,
|
||||
`videoGenerationModel`, `pdfModel`, and `messages.tts`.
|
||||
|
||||
Text, images, video, music, TTS, approvals, and messaging-tool output continue
|
||||
through the normal OpenClaw delivery path; media generation does not require
|
||||
the legacy runtime. When Codex emits a native image-generation item with a
|
||||
`savedPath`, OpenClaw forwards that exact file through the normal reply-media
|
||||
path even if the Codex turn has no assistant text.
|
||||
|
||||
## Related
|
||||
|
||||
- [Codex harness](/plugins/codex-harness)
|
||||
- [Codex harness reference](/plugins/codex-harness-reference)
|
||||
- [Native Codex plugins](/plugins/codex-native-plugins)
|
||||
- [Plugin hooks](/plugins/hooks)
|
||||
- [Agent harness plugins](/plugins/sdk-agent-harness)
|
||||
- [Diagnostics export](/gateway/diagnostics)
|
||||
- [Trajectory export](/tools/trajectory)
|
||||
955
docs/plugins/codex-harness.md
Normal file
955
docs/plugins/codex-harness.md
Normal file
@@ -0,0 +1,955 @@
|
||||
---
|
||||
summary: "Run OpenClaw embedded agent turns through the bundled Codex app-server harness"
|
||||
title: "Codex harness"
|
||||
read_when:
|
||||
- You want to use the bundled Codex app-server harness
|
||||
- You need Codex harness config examples
|
||||
- You want Codex-only deployments to fail instead of falling back to OpenClaw
|
||||
---
|
||||
|
||||
The bundled `codex` plugin runs embedded OpenAI agent turns through Codex
|
||||
app-server instead of the built-in OpenClaw harness. Codex owns the
|
||||
low-level agent session: native thread resume, native tool continuation,
|
||||
native compaction, and app-server execution. OpenClaw still owns chat
|
||||
channels, session files, model selection, OpenClaw dynamic tools, approvals,
|
||||
media delivery, and the visible transcript mirror.
|
||||
|
||||
Use canonical OpenAI model refs such as `openai/gpt-5.5`. Do not configure
|
||||
legacy Codex GPT refs; put OpenAI agent auth order under `auth.order.openai`.
|
||||
Legacy Codex auth profile ids and legacy Codex auth order entries are
|
||||
repaired by `openclaw doctor --fix`.
|
||||
|
||||
When no OpenClaw sandbox is active, OpenClaw starts Codex app-server threads
|
||||
with Codex native code mode enabled (code-mode-only stays off by default), so
|
||||
native workspace/code capabilities remain available alongside OpenClaw
|
||||
dynamic tools routed through the app-server `item/tool/call` bridge. An
|
||||
active OpenClaw sandbox or restricted tool policy disables native code mode
|
||||
entirely unless you opt into the experimental sandbox exec-server path.
|
||||
|
||||
This Codex-native feature is separate from
|
||||
[OpenClaw code mode](/reference/code-mode), an opt-in QuickJS-WASI runtime
|
||||
for generic OpenClaw runs with a different `exec` input shape. For the
|
||||
broader model/provider/runtime split, start with
|
||||
[Agent runtimes](/concepts/agent-runtimes): `openai/gpt-5.5` is the model
|
||||
ref, `codex` is the runtime, and Telegram, Discord, Slack, or another
|
||||
channel is the communication surface.
|
||||
|
||||
## Requirements
|
||||
|
||||
- OpenClaw with the bundled `codex` plugin available. Include `codex` in
|
||||
`plugins.allow` if your config uses an allowlist.
|
||||
- Codex app-server `0.125.0` or newer. The plugin manages a compatible
|
||||
binary by default, so a `codex` command on `PATH` does not affect normal
|
||||
startup.
|
||||
- Codex auth through `openclaw models auth login --provider openai`, an
|
||||
app-server account already present in the agent's Codex home, or an
|
||||
explicit Codex API-key auth profile.
|
||||
|
||||
For auth precedence, environment isolation, custom app-server commands,
|
||||
model discovery, and the full config field list, see
|
||||
[Codex harness reference](/plugins/codex-harness-reference).
|
||||
|
||||
## Quickstart
|
||||
|
||||
Sign in with Codex OAuth:
|
||||
|
||||
```bash
|
||||
openclaw models auth login --provider openai
|
||||
```
|
||||
|
||||
Enable the bundled `codex` plugin and select an OpenAI agent model:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
If your config uses `plugins.allow`, add `codex` there too:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
allow: ["codex"],
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Restart the gateway after changing plugin config. If a chat already has a
|
||||
session, run `/new` or `/reset` first so the next turn resolves the harness
|
||||
from current config.
|
||||
|
||||
## Share threads with Codex Desktop and CLI
|
||||
|
||||
The default `appServer.homeScope: "agent"` isolates each OpenClaw agent from
|
||||
the operator's native Codex state. To let an owner inspect and manage the
|
||||
same native threads shown by Codex Desktop and the Codex CLI, opt into the
|
||||
user Codex home:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
homeScope: "user",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
User-home mode requires local stdio transport. It uses `$CODEX_HOME` when
|
||||
set and `~/.codex` otherwise, including that home's native Codex auth,
|
||||
config, plugins, and thread store. OpenClaw does not inject an OpenClaw auth
|
||||
profile into this app-server.
|
||||
|
||||
Owner turns gain the `codex_threads` tool: list, search, read, fork, rename,
|
||||
archive, and restore native threads. Fork a thread to continue it in
|
||||
OpenClaw; the fork attaches to the current OpenClaw session and stays
|
||||
visible to other native Codex clients. Archiving requires explicit
|
||||
confirmation that the thread is closed elsewhere.
|
||||
|
||||
Do not resume or write the same thread concurrently from OpenClaw and
|
||||
another Codex client. Codex coordinates live writers inside one app-server
|
||||
process, not across independent Desktop, CLI, and OpenClaw processes.
|
||||
Forking is the safe coexistence path.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Need | Set | Where |
|
||||
| -------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------- |
|
||||
| Enable the harness | `plugins.entries.codex.enabled: true` | OpenClaw config |
|
||||
| Keep an allowlisted plugin install | Include `codex` in `plugins.allow` | OpenClaw config |
|
||||
| Route OpenAI agent turns through Codex | `agents.defaults.model` or `agents.list[].model` as `openai/gpt-*` | OpenClaw agent config |
|
||||
| Sign in with ChatGPT/Codex OAuth | `openclaw models auth login --provider openai` | CLI auth profile |
|
||||
| Add API-key backup for Codex runs | `openai:*` API-key profile listed after subscription auth in `auth.order.openai` | CLI auth profile + OpenClaw config |
|
||||
| Fail closed when Codex is unavailable | Provider or model `agentRuntime.id: "codex"` | OpenClaw model/provider config |
|
||||
| Use direct OpenAI API traffic | Provider or model `agentRuntime.id: "openclaw"` with normal OpenAI auth | OpenClaw model/provider config |
|
||||
| Tune app-server behavior | `plugins.entries.codex.config.appServer.*` | Codex plugin config |
|
||||
| Enable native Codex plugin apps | `plugins.entries.codex.config.codexPlugins.*` | Codex plugin config |
|
||||
| Enable Codex Computer Use | `plugins.entries.codex.config.computerUse.*` | Codex plugin config |
|
||||
|
||||
Prefer `auth.order.openai` for subscription-first/API-key-backup ordering.
|
||||
Existing legacy Codex auth profile ids and legacy Codex auth order are
|
||||
doctor-only legacy state; do not write new legacy Codex GPT refs.
|
||||
|
||||
```json5
|
||||
{
|
||||
auth: {
|
||||
order: {
|
||||
openai: ["openai:user@example.com", "openai:api-key-backup"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Both profiles above still run through Codex for `openai/gpt-*` agent turns.
|
||||
The API key is only an auth fallback, not a request to switch to OpenClaw or
|
||||
plain OpenAI Responses.
|
||||
|
||||
### Compaction
|
||||
|
||||
Do not set `compaction.model` or `compaction.provider` on Codex-backed
|
||||
agents. Codex compacts through its native app-server thread state, so
|
||||
OpenClaw ignores those local summarizer overrides at runtime, and
|
||||
`openclaw doctor --fix` removes them when the agent uses Codex.
|
||||
|
||||
Lossless remains supported as a context engine for assembly, ingestion, and
|
||||
maintenance around Codex turns, configured through
|
||||
`plugins.slots.contextEngine: "lossless-claw"` and
|
||||
`plugins.entries.lossless-claw.config.summaryModel`, not through
|
||||
`agents.defaults.compaction.provider`. `openclaw doctor --fix` migrates the
|
||||
old `compaction.provider: "lossless-claw"` shape to the Lossless
|
||||
context-engine slot when Codex is the active runtime, but native Codex still
|
||||
owns compaction. The native app-server harness supports context engines
|
||||
that need pre-prompt assembly; generic CLI backends, including `codex-cli`,
|
||||
do not provide that host capability.
|
||||
|
||||
For Codex-backed agents, `/compact` starts native Codex app-server
|
||||
compaction on the bound thread. OpenClaw does not wait for completion,
|
||||
impose an OpenClaw timeout, restart the shared app-server, or fall back to a
|
||||
context-engine or public OpenAI summarizer. If the native Codex thread
|
||||
binding is missing or stale, the command fails closed instead of silently
|
||||
switching compaction backends.
|
||||
|
||||
The rest of this page covers deployment shape, fail-closed routing, guardian
|
||||
approval policy, native Codex plugins, and Computer Use. For full option
|
||||
lists, defaults, enums, discovery, environment isolation, timeouts, and
|
||||
app-server transport fields, see
|
||||
[Codex harness reference](/plugins/codex-harness-reference).
|
||||
|
||||
## Verify Codex runtime
|
||||
|
||||
Use `/status` in the chat where you expect Codex. A Codex-backed OpenAI
|
||||
agent turn shows:
|
||||
|
||||
```text
|
||||
Runtime: OpenAI Codex
|
||||
```
|
||||
|
||||
Then check Codex app-server state:
|
||||
|
||||
```text
|
||||
/codex status
|
||||
/codex models
|
||||
```
|
||||
|
||||
`/codex status` reports app-server connectivity, account, rate limits, MCP
|
||||
servers, and skills. `/codex models` lists the live Codex app-server catalog
|
||||
for the harness and account. If `/status` is surprising, see
|
||||
[Troubleshooting](#troubleshooting).
|
||||
|
||||
## Routing and model selection
|
||||
|
||||
Keep provider refs and runtime policy separate:
|
||||
|
||||
- Use `openai/gpt-*` for OpenAI agent turns through Codex.
|
||||
- Do not use legacy Codex GPT refs in config; run `openclaw doctor --fix` to
|
||||
repair legacy refs and stale session route pins.
|
||||
- `agentRuntime.id: "codex"` is optional for normal OpenAI auto mode, but
|
||||
useful when a deployment should fail closed if Codex is unavailable.
|
||||
- `agentRuntime.id: "openclaw"` opts a provider or model into the embedded
|
||||
OpenClaw runtime when that is intentional.
|
||||
- `/codex ...` controls native Codex app-server conversations from chat.
|
||||
- ACP/acpx is a separate external harness path. Use it only when the user
|
||||
asks for ACP/acpx or an external harness adapter.
|
||||
|
||||
| User intent | Use |
|
||||
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| Attach the current chat | `/codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]` |
|
||||
| Resume an existing Codex thread | `/codex resume <thread-id>` |
|
||||
| List or filter Codex threads | `/codex threads [filter]` |
|
||||
| List native Codex plugins | `/codex plugins list` |
|
||||
| Enable or disable a configured native Codex plugin | `/codex plugins enable <name>`, `/codex plugins disable <name>` |
|
||||
| Attach an existing Codex CLI session on a paired node | `/codex sessions --host <node> [filter]`, then `/codex resume <session-id> --host <node> --bind here` |
|
||||
| Change the bound thread's model, fast-mode, or permissions | `/codex model <model>`, `/codex fast [on\|off\|status]`, `/codex permissions [default\|yolo\|status]` |
|
||||
| Stop or steer the active turn | `/codex stop`, `/codex steer <text>` |
|
||||
| Detach the current binding | `/codex detach` (alias `/codex unbind`) |
|
||||
| Send Codex feedback only | `/codex diagnostics [note]` |
|
||||
| Start an ACP/acpx task | ACP/acpx session commands, not `/codex` |
|
||||
|
||||
| Use case | Configure | Verify | Notes |
|
||||
| ---------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------- | ------------------------------------- |
|
||||
| ChatGPT/Codex subscription with native Codex runtime | `openai/gpt-*` plus enabled `codex` plugin | `/status` shows `Runtime: OpenAI Codex` | Recommended path |
|
||||
| Fail closed if Codex is unavailable | Provider or model `agentRuntime.id: "codex"` | Turn fails instead of embedded fallback | Use for Codex-only deployments |
|
||||
| Direct OpenAI API-key traffic through OpenClaw | Provider or model `agentRuntime.id: "openclaw"` and normal OpenAI auth | `/status` shows OpenClaw runtime | Use only when OpenClaw is intentional |
|
||||
| Legacy config | legacy Codex GPT refs | `openclaw doctor --fix` rewrites it | Do not write new config this way |
|
||||
| ACP/acpx Codex adapter | ACP `sessions_spawn({ runtime: "acp" })` | ACP task/session status | Separate from native Codex harness |
|
||||
|
||||
`agents.defaults.imageModel` follows the same prefix split. Use `openai/gpt-*`
|
||||
for the normal OpenAI route and `codex/gpt-*` only when image understanding
|
||||
should run through a bounded Codex app-server turn. Doctor rewrites legacy
|
||||
Codex GPT refs to `openai/gpt-*`.
|
||||
|
||||
## Deployment patterns
|
||||
|
||||
### Basic Codex deployment
|
||||
|
||||
Use the quickstart config when all OpenAI agent turns should use Codex by
|
||||
default:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Mixed provider deployment
|
||||
|
||||
Keep Claude as the default agent and add a named Codex agent:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
},
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
default: true,
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
},
|
||||
{
|
||||
id: "codex",
|
||||
name: "Codex",
|
||||
model: "openai/gpt-5.5",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The `main` agent uses its normal provider path; the `codex` agent uses Codex
|
||||
app-server.
|
||||
|
||||
### Fail-closed Codex deployment
|
||||
|
||||
`openai/gpt-*` already resolves to Codex when the bundled plugin is
|
||||
available. Add explicit runtime policy for a written fail-closed rule:
|
||||
|
||||
```json5
|
||||
{
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
With Codex forced, OpenClaw fails early if the Codex plugin is disabled, the
|
||||
app-server is too old, or the app-server cannot start.
|
||||
|
||||
## App-server policy
|
||||
|
||||
By default, the plugin starts OpenClaw's managed Codex binary locally with
|
||||
stdio transport. Set `appServer.command` only to intentionally run a
|
||||
different executable. Use WebSocket transport only when an app-server is
|
||||
already running elsewhere:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
transport: "websocket",
|
||||
url: "ws://gateway-host:39175",
|
||||
authToken: "${CODEX_APP_SERVER_TOKEN}",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Local stdio app-server sessions default to the trusted local operator
|
||||
posture: `approvalPolicy: "never"`, `approvalsReviewer: "user"`, and
|
||||
`sandbox: "danger-full-access"`. If local Codex requirements disallow that
|
||||
implicit YOLO posture, OpenClaw selects allowed guardian permissions
|
||||
instead. When an OpenClaw sandbox is active for the session, OpenClaw
|
||||
disables Codex native Code Mode, user MCP servers, and app-backed plugin
|
||||
execution for that turn instead of relying on Codex host-side sandboxing.
|
||||
Shell access instead goes through OpenClaw sandbox-backed dynamic tools such
|
||||
as `sandbox_exec` and `sandbox_process` when the normal exec/process tools
|
||||
are available.
|
||||
|
||||
Use normalized OpenClaw exec mode for Codex native auto-review before
|
||||
sandbox escapes or extra permissions:
|
||||
|
||||
```json5
|
||||
{
|
||||
tools: {
|
||||
exec: {
|
||||
mode: "auto",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
For Codex app-server sessions, `tools.exec.mode: "auto"` maps to Codex
|
||||
Guardian-reviewed approvals: usually `approvalPolicy: "on-request"`,
|
||||
`approvalsReviewer: "auto_review"`, and `sandbox: "workspace-write"` when
|
||||
local requirements allow those values. In `tools.exec.mode: "auto"`,
|
||||
OpenClaw does not preserve legacy unsafe Codex `approvalPolicy: "never"` or
|
||||
`sandbox: "danger-full-access"` overrides; use `tools.exec.mode: "full"` for
|
||||
an intentional no-approval Codex posture. The legacy
|
||||
`plugins.entries.codex.config.appServer.mode: "guardian"` preset still
|
||||
works, but `tools.exec.mode: "auto"` is the normalized OpenClaw surface.
|
||||
|
||||
For the mode-level comparison with host exec approvals and ACPX
|
||||
permissions, see [Permission modes](/tools/permission-modes). For every
|
||||
app-server field, auth order, environment isolation, and timeout behavior,
|
||||
see [Codex harness reference](/plugins/codex-harness-reference).
|
||||
|
||||
## Commands and diagnostics
|
||||
|
||||
The bundled plugin registers `/codex` as a slash command on any channel that
|
||||
supports OpenClaw text commands.
|
||||
|
||||
Native execution and control require an owner or an `operator.admin`
|
||||
Gateway client: binding or resuming threads, sending or stopping turns,
|
||||
changing model, fast-mode, or permission state, compacting or reviewing, and
|
||||
detaching a binding. Other authorized senders keep read-only status, help,
|
||||
account, model, thread, MCP server, skill, and binding inspection commands.
|
||||
|
||||
Common forms:
|
||||
|
||||
- `/codex status` checks app-server connectivity, models, account, rate
|
||||
limits, MCP servers, and skills.
|
||||
- `/codex models` lists live Codex app-server models.
|
||||
- `/codex threads [filter]` lists recent Codex app-server threads.
|
||||
- `/codex resume <thread-id>` attaches the current OpenClaw session to an
|
||||
existing Codex thread.
|
||||
- `/codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]`
|
||||
attaches the current chat.
|
||||
- `/codex detach` (or `/codex unbind`) detaches the current binding.
|
||||
- `/codex binding` describes the current binding.
|
||||
- `/codex stop` stops the active turn; `/codex steer <text>` steers it.
|
||||
- `/codex model <model>`, `/codex fast [on|off|status]`, and
|
||||
`/codex permissions [default|yolo|status]` change per-conversation state.
|
||||
- `/codex compact` asks Codex app-server to compact the attached thread.
|
||||
- `/codex review` starts Codex native review for the attached thread.
|
||||
- `/codex diagnostics [note]` asks before sending Codex feedback for the
|
||||
attached thread.
|
||||
- `/codex account` shows account and rate-limit status.
|
||||
- `/codex mcp` lists Codex app-server MCP server status.
|
||||
- `/codex skills` lists Codex app-server skills.
|
||||
- `/codex plugins list`, `/codex plugins enable <name>`, and
|
||||
`/codex plugins disable <name>` manage configured native Codex plugins.
|
||||
- `/codex computer-use [status|install]` manages Codex Computer Use.
|
||||
- `/codex help` lists the full command tree.
|
||||
|
||||
For most support reports, start with `/diagnostics [note]` in the
|
||||
conversation where the bug happened. It creates one Gateway diagnostics
|
||||
report and, for Codex harness sessions, asks for approval to send the
|
||||
relevant Codex feedback bundle. See
|
||||
[Diagnostics export](/gateway/diagnostics) for the privacy model and group
|
||||
chat behavior. Use `/codex diagnostics [note]` only when you specifically
|
||||
want the Codex feedback upload for the currently attached thread without
|
||||
the full Gateway diagnostics bundle.
|
||||
|
||||
### Inspect Codex threads locally
|
||||
|
||||
The fastest way to inspect a bad Codex run is often to open the native
|
||||
Codex thread directly:
|
||||
|
||||
```bash
|
||||
codex resume <thread-id>
|
||||
```
|
||||
|
||||
Get the thread id from the completed `/diagnostics` reply, `/codex binding`,
|
||||
or `/codex threads [filter]`.
|
||||
|
||||
For upload mechanics and runtime-level diagnostics boundaries, see
|
||||
[Codex harness runtime](/plugins/codex-harness-runtime#codex-feedback-upload).
|
||||
|
||||
### Auth order
|
||||
|
||||
In the default per-agent home, auth is selected in this order:
|
||||
|
||||
1. Ordered OpenAI auth profiles for the agent, preferably under
|
||||
`auth.order.openai`. Run `openclaw doctor --fix` to migrate older legacy
|
||||
Codex auth profile ids and legacy Codex auth order.
|
||||
2. The app-server's existing account in that agent's Codex home.
|
||||
3. For local stdio app-server launches only, `CODEX_API_KEY`, then
|
||||
`OPENAI_API_KEY`, when no app-server account is present and OpenAI auth
|
||||
is still required.
|
||||
|
||||
When OpenClaw sees a ChatGPT subscription-style Codex auth profile, it
|
||||
removes `CODEX_API_KEY` and `OPENAI_API_KEY` from the spawned Codex child
|
||||
process. That keeps Gateway-level API keys available for embeddings or
|
||||
direct OpenAI models without making native Codex app-server turns bill
|
||||
through the API by accident. Explicit Codex API-key profiles and local
|
||||
stdio env-key fallback use app-server login instead of inherited
|
||||
child-process env. WebSocket app-server connections do not receive Gateway
|
||||
env API-key fallback; use an explicit auth profile or the remote
|
||||
app-server's own account.
|
||||
|
||||
If a subscription profile hits a Codex usage limit, OpenClaw records the
|
||||
reset time when Codex reports one and tries the next ordered auth profile
|
||||
for the same Codex run. When the reset time passes, the subscription
|
||||
profile becomes eligible again without changing the selected `openai/gpt-*`
|
||||
model or Codex runtime.
|
||||
|
||||
When native Codex plugins are configured, OpenClaw installs or refreshes
|
||||
those plugins through the connected app-server before exposing plugin-owned
|
||||
apps to the Codex thread. `app/list` remains the source of truth for app
|
||||
ids, accessibility, and metadata, but OpenClaw owns the per-thread
|
||||
enablement decision: if policy allows a listed accessible app, OpenClaw
|
||||
sends `thread/start.config.apps[appId].enabled = true` even when `app/list`
|
||||
currently reports that app disabled. This path does not invent app
|
||||
installation for unknown ids; OpenClaw only activates marketplace plugins
|
||||
with `plugin/install` and then refreshes inventory.
|
||||
|
||||
### Environment isolation
|
||||
|
||||
For local stdio app-server launches, OpenClaw sets `CODEX_HOME` to a
|
||||
per-agent directory so Codex config, auth/account files, plugin cache/data,
|
||||
and native thread state do not read or write the operator's personal
|
||||
`~/.codex` by default. OpenClaw preserves the normal process `HOME`;
|
||||
Codex-run subprocesses can still find user-home config and tokens, and
|
||||
Codex may discover shared `$HOME/.agents/skills` and
|
||||
`$HOME/.agents/plugins/marketplace.json` entries. With
|
||||
`appServer.homeScope: "user"`, OpenClaw instead uses the native user Codex
|
||||
home and its existing account without injecting an OpenClaw auth profile.
|
||||
|
||||
If a deployment needs additional environment isolation, add those
|
||||
variables to `appServer.clearEnv`:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
appServer: {
|
||||
clearEnv: ["CODEX_API_KEY", "OPENAI_API_KEY"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`appServer.clearEnv` only affects the spawned Codex app-server child
|
||||
process. OpenClaw removes `CODEX_HOME` and `HOME` from this list during
|
||||
local launch normalization: `CODEX_HOME` stays pointed at the selected
|
||||
agent or user scope, and `HOME` stays inherited so subprocesses can use
|
||||
normal user-home state.
|
||||
|
||||
### Dynamic tools and web search
|
||||
|
||||
Codex dynamic tools default to `searchable` loading. OpenClaw does not
|
||||
expose dynamic tools that duplicate Codex-native workspace operations:
|
||||
`read`, `write`, `edit`, `apply_patch`, `exec`, `process`, `update_plan`,
|
||||
`tool_call`, `tool_describe`, `tool_search`, and `tool_search_code`. Most
|
||||
remaining OpenClaw integration tools, such as messaging, media, cron,
|
||||
browser, nodes, gateway, and `heartbeat_respond`, are available through
|
||||
Codex tool search under the `openclaw` namespace, keeping the initial model
|
||||
context smaller.
|
||||
|
||||
Web search uses Codex's hosted `web_search` tool by default when search is
|
||||
enabled and no managed provider is selected. Native hosted search and
|
||||
OpenClaw's managed `web_search` dynamic tool are mutually exclusive so
|
||||
managed search cannot bypass native domain restrictions. OpenClaw uses the
|
||||
managed tool when hosted search is unavailable, explicitly disabled, or
|
||||
replaced by a selected managed provider. OpenClaw keeps Codex's standalone
|
||||
`web.run` extension disabled because production app-server traffic rejects
|
||||
its user-defined `web` namespace. `tools.web.search.enabled: false`
|
||||
disables both paths, as do tool-disabled LLM-only runs. Codex treats
|
||||
`"cached"` as a preference and resolves it to live external access for
|
||||
unrestricted app-server turns. Automatic managed fallback fails closed when
|
||||
native `allowedDomains` are set so the allowlist cannot be bypassed.
|
||||
Persistent effective search-policy changes rotate the bound Codex thread
|
||||
before the next turn; transient per-turn restrictions use a temporary
|
||||
restricted thread and preserve the existing binding for later resume.
|
||||
|
||||
`sessions_yield` and message-tool-only source replies stay direct because
|
||||
those are turn-control contracts. `sessions_spawn` stays searchable so
|
||||
Codex's native `spawn_agent` remains the primary Codex subagent surface,
|
||||
while explicit OpenClaw or ACP delegation is still available through the
|
||||
`openclaw` dynamic tool namespace. Heartbeat collaboration instructions
|
||||
tell Codex to search for `heartbeat_respond` before ending a heartbeat turn
|
||||
when the tool is not already loaded.
|
||||
|
||||
Set `codexDynamicToolsLoading: "direct"` only when connecting to a custom
|
||||
Codex app-server that cannot search deferred dynamic tools or when
|
||||
debugging the full tool payload.
|
||||
|
||||
### Config fields
|
||||
|
||||
Supported top-level Codex plugin fields:
|
||||
|
||||
| Field | Default | Meaning |
|
||||
| -------------------------- | -------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `codexDynamicToolsLoading` | `"searchable"` | Use `"direct"` to put OpenClaw dynamic tools directly in the initial Codex tool context. |
|
||||
| `codexDynamicToolsExclude` | `[]` | Additional OpenClaw dynamic tool names to omit from Codex app-server turns. |
|
||||
| `codexPlugins` | disabled | Native Codex plugin/app support for migrated source-installed curated plugins. |
|
||||
|
||||
Supported `appServer` fields:
|
||||
|
||||
| Field | Default | Meaning |
|
||||
| --------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
|
||||
| `homeScope` | `"agent"` | `"agent"` isolates Codex state per OpenClaw agent. `"user"` shares the native `$CODEX_HOME` or `~/.codex`, uses native auth, and enables owner-only thread management. User scope requires stdio. |
|
||||
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary; set it only for an explicit override. |
|
||||
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
|
||||
| `url` | unset | WebSocket app-server URL. |
|
||||
| `authToken` | unset | Bearer token for WebSocket transport. Accepts a literal string or SecretInput such as `${CODEX_APP_SERVER_TOKEN}`. |
|
||||
| `headers` | `{}` | Extra WebSocket headers. Header values accept literal strings or SecretInput values, for example `x-codex-client-session-token: "${CODEX_CLIENT_SESSION_TOKEN}"`. |
|
||||
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. OpenClaw keeps the selected `CODEX_HOME` and inherited `HOME` for local launches. |
|
||||
| `codeModeOnly` | `false` | Opt into Codex's code-mode-only tool surface. OpenClaw dynamic tools remain registered with Codex so nested `tools.*` calls return through the app-server `item/tool/call` bridge. |
|
||||
| `remoteWorkspaceRoot` | unset | Remote Codex app-server workspace root. When set, OpenClaw infers the local workspace root from the resolved OpenClaw workspace, preserves the current cwd suffix under this remote root, and sends only the final app-server cwd to Codex. If the cwd is outside the resolved OpenClaw workspace root, OpenClaw fails closed instead of sending a gateway-local path to the remote app-server. |
|
||||
| `requestTimeoutMs` | `60000` | Timeout for app-server control-plane calls. |
|
||||
| `turnCompletionIdleTimeoutMs` | `60000` | Quiet window after Codex accepts a turn or after a turn-scoped app-server request while OpenClaw waits for `turn/completed`. |
|
||||
| `postToolRawAssistantCompletionIdleTimeoutMs` | `300000` | Completion-idle and progress guard used after a tool handoff, native tool completion, post-tool raw assistant progress, raw reasoning completion, or reasoning progress while OpenClaw waits for `turn/completed`. Use this for trusted or heavy workloads where post-tool synthesis can legitimately stay quiet longer than the final assistant release budget. |
|
||||
| `mode` | `"yolo"` unless local Codex requirements disallow YOLO | Preset for YOLO or guardian-reviewed execution. Local stdio requirements that omit `danger-full-access`, `never` approval, or the `user` reviewer make the implicit default guardian. |
|
||||
| `approvalPolicy` | `"never"` or an allowed guardian approval policy | Native Codex approval policy sent to thread start/resume/turn. Guardian defaults prefer `"on-request"` when allowed. |
|
||||
| `sandbox` | `"danger-full-access"` or an allowed guardian sandbox | Native Codex sandbox mode sent to thread start/resume. Guardian defaults prefer `"workspace-write"` when allowed, otherwise `"read-only"`. When an OpenClaw sandbox is active, `danger-full-access` turns use Codex `workspace-write` with network access derived from the OpenClaw sandbox egress setting. |
|
||||
| `approvalsReviewer` | `"user"` or an allowed guardian reviewer | Use `"auto_review"` to let Codex review native approval prompts when allowed, otherwise `guardian_subagent` or `user`. `guardian_subagent` remains a legacy alias. |
|
||||
| `serviceTier` | unset | Optional Codex app-server service tier. `"priority"` enables fast-mode routing, `"flex"` requests flex processing, `null` clears the override, and legacy `"fast"` is accepted as `"priority"`. |
|
||||
| `networkProxy` | disabled | Opt into Codex permissions-profile networking for app-server commands. OpenClaw defines the selected `permissions.<profile>.network` config and selects it with `default_permissions` instead of sending `sandbox`. |
|
||||
| `experimental.sandboxExecServer` | `false` | Preview opt-in that registers an OpenClaw sandbox-backed Codex environment with Codex app-server 0.132.0 or newer so native Codex execution can run inside the active OpenClaw sandbox. |
|
||||
|
||||
`appServer.networkProxy` is explicit because it changes the Codex sandbox
|
||||
contract. When enabled, OpenClaw also sets `features.network_proxy.enabled`
|
||||
and `default_permissions` in the Codex thread config so the generated
|
||||
permission profile can start Codex managed networking. By default, OpenClaw
|
||||
generates a collision-resistant `openclaw-network-<fingerprint>` profile
|
||||
name from the profile body; use `profileName` only when a stable local name
|
||||
is required.
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
config: {
|
||||
appServer: {
|
||||
sandbox: "workspace-write",
|
||||
networkProxy: {
|
||||
enabled: true,
|
||||
domains: {
|
||||
"api.openai.com": "allow",
|
||||
"blocked.example.com": "deny",
|
||||
},
|
||||
unixSockets: {
|
||||
"/tmp/proxy.sock": "allow",
|
||||
"/tmp/blocked.sock": "none",
|
||||
},
|
||||
allowUpstreamProxy: true,
|
||||
proxyUrl: "http://127.0.0.1:3128",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
If the normal app-server runtime would be `danger-full-access`, enabling
|
||||
`networkProxy` uses workspace-style filesystem access for the generated
|
||||
permission profile: Codex managed network enforcement is sandboxed
|
||||
networking, so a full-access profile would not protect outbound traffic.
|
||||
Domain entries use `allow` or `deny`; Unix socket entries use Codex's
|
||||
`allow` or `none` values.
|
||||
|
||||
### Dynamic tool call timeouts
|
||||
|
||||
OpenClaw-owned dynamic tool calls are bounded independently from
|
||||
`appServer.requestTimeoutMs`: Codex `item/tool/call` requests use a 90
|
||||
second OpenClaw watchdog by default. A positive per-call `timeoutMs`
|
||||
argument extends or shortens that specific tool budget, capped at 600000 ms.
|
||||
The `image_generate` tool uses `agents.defaults.imageGenerationModel.timeoutMs`
|
||||
when the tool call does not provide its own timeout, or a 120 second
|
||||
image-generation default otherwise. The media-understanding `image` tool
|
||||
uses `tools.media.image.timeoutSeconds` or its 60 second media default; for
|
||||
image understanding, that timeout applies to the request itself and is not
|
||||
reduced by earlier preparation work. On timeout, OpenClaw aborts the tool
|
||||
signal where supported and returns a failed dynamic-tool response to Codex
|
||||
so the turn can continue instead of leaving the session in `processing`.
|
||||
This watchdog is the outer dynamic `item/tool/call` budget; provider-specific
|
||||
request timeouts run inside that call and keep their own timeout semantics.
|
||||
|
||||
After Codex accepts a turn, and after OpenClaw responds to a turn-scoped
|
||||
app-server request, the harness expects Codex to make current-turn progress
|
||||
and eventually finish the native turn with `turn/completed`. If the
|
||||
app-server goes quiet for `appServer.turnCompletionIdleTimeoutMs`, OpenClaw
|
||||
best-effort interrupts the Codex turn, records a diagnostic timeout, and
|
||||
releases the OpenClaw session lane so follow-up chat messages are not
|
||||
queued behind a stale native turn. Most non-terminal notifications for the
|
||||
same turn disarm that short watchdog because Codex has proven the turn is
|
||||
still alive.
|
||||
|
||||
Tool handoffs use a longer post-tool idle budget: after OpenClaw returns an
|
||||
`item/tool/call` response, after native tool items such as
|
||||
`commandExecution` complete, after raw `custom_tool_call_output`
|
||||
completions, and after post-tool raw assistant progress, raw reasoning
|
||||
completions, or reasoning progress. The guard uses
|
||||
`appServer.postToolRawAssistantCompletionIdleTimeoutMs` when configured and
|
||||
defaults to five minutes otherwise; that same budget also extends the
|
||||
progress watchdog for the silent synthesis window before Codex emits the
|
||||
next current-turn event. Global app-server notifications, such as
|
||||
rate-limit updates, do not reset turn-idle progress. Reasoning completions,
|
||||
commentary `agentMessage` completions, and pre-tool raw reasoning or
|
||||
assistant progress can be followed by an automatic final reply, so they use
|
||||
the post-progress reply guard instead of releasing the session lane
|
||||
immediately.
|
||||
|
||||
Only final/non-commentary completed `agentMessage` items and pre-tool raw
|
||||
assistant completions arm the assistant-output release: if Codex then goes
|
||||
quiet without `turn/completed`, OpenClaw best-effort interrupts the native
|
||||
turn and releases the session lane. If another turn watch wins that release
|
||||
race, OpenClaw still accepts the completed final assistant item once no
|
||||
native request, item, or dynamic tool completion remains active and the
|
||||
assistant-output release still belongs to the latest completed item, with
|
||||
no later item completion. This can preserve the final answer after
|
||||
completed tool work without replaying the turn. Partial assistant deltas,
|
||||
stale earlier replies, and empty later completions do not qualify.
|
||||
|
||||
Replay-safe stdio app-server failures, including turn-completion idle
|
||||
timeouts without assistant, tool, active-item, or side-effect evidence, are
|
||||
retried once on a fresh app-server attempt. Unsafe timeouts still retire the
|
||||
stuck app-server client and release the OpenClaw session lane; they also
|
||||
clear the stale native thread binding instead of being replayed
|
||||
automatically. Completion-watch timeouts surface Codex-specific timeout
|
||||
text: replay-safe cases say the response may be incomplete, while unsafe
|
||||
cases tell the user to verify current state before retrying. Public timeout
|
||||
diagnostics include structural fields such as the last app-server
|
||||
notification method, raw assistant response item id/type/role, active
|
||||
request/item counts, and armed watch state; when the last notification is a
|
||||
raw assistant response item, they also include a bounded assistant text
|
||||
preview. They do not include raw prompt or tool content.
|
||||
|
||||
### Local testing env overrides
|
||||
|
||||
- `OPENCLAW_CODEX_APP_SERVER_BIN` bypasses the managed binary when
|
||||
`appServer.command` is unset.
|
||||
- `OPENCLAW_CODEX_APP_SERVER_ARGS`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_MODE=yolo|guardian`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_SANDBOX`
|
||||
|
||||
`OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1` was removed. Use
|
||||
`plugins.entries.codex.config.appServer.mode: "guardian"` instead, or
|
||||
`OPENCLAW_CODEX_APP_SERVER_MODE=guardian` for one-off local testing. Config
|
||||
is preferred for repeatable deployments because it keeps the plugin
|
||||
behavior in the same reviewed file as the rest of the Codex harness setup.
|
||||
|
||||
## Native Codex plugins
|
||||
|
||||
Native Codex plugin support uses Codex app-server's own app and plugin
|
||||
capabilities in the same Codex thread as the OpenClaw harness turn. OpenClaw
|
||||
does not translate Codex plugins into synthetic `codex_plugin_*` OpenClaw
|
||||
dynamic tools.
|
||||
|
||||
`codexPlugins` affects only sessions that select the native Codex harness.
|
||||
It has no effect on built-in harness runs, normal OpenAI provider runs, ACP
|
||||
conversation bindings, or other harnesses.
|
||||
|
||||
Minimal migrated config:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
codexPlugins: {
|
||||
enabled: true,
|
||||
allow_destructive_actions: true,
|
||||
plugins: {
|
||||
"google-calendar": {
|
||||
enabled: true,
|
||||
marketplaceName: "openai-curated",
|
||||
pluginName: "google-calendar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Thread app config is computed when OpenClaw establishes a Codex harness
|
||||
session or replaces a stale Codex thread binding; it is not recomputed on
|
||||
every turn. After changing `codexPlugins`, use `/new`, `/reset`, or restart
|
||||
the gateway so future Codex harness sessions start with the updated app
|
||||
set.
|
||||
|
||||
For migration eligibility, app inventory, destructive action policy,
|
||||
elicitations, and native plugin diagnostics, see
|
||||
[Native Codex plugins](/plugins/codex-native-plugins).
|
||||
|
||||
OpenAI-side app and plugin access is controlled by the signed-in Codex
|
||||
account and, for Business and Enterprise/Edu workspaces, workspace app
|
||||
controls. See
|
||||
[Using Codex with your ChatGPT plan](https://help.openai.com/en/articles/11369540-using-codex-with-your-chatgpt-plan)
|
||||
for OpenAI's account and workspace-control overview.
|
||||
|
||||
## Computer Use
|
||||
|
||||
Computer Use has its own setup guide:
|
||||
[Codex Computer Use](/plugins/codex-computer-use).
|
||||
|
||||
Short version: OpenClaw does not vendor the desktop-control app or execute
|
||||
desktop actions itself. It prepares Codex app-server, verifies that the
|
||||
`computer-use` MCP server is available, and then lets Codex own the native
|
||||
MCP tool calls during Codex-mode turns.
|
||||
|
||||
## Runtime boundaries
|
||||
|
||||
The Codex harness changes the low-level embedded agent executor only.
|
||||
|
||||
- OpenClaw dynamic tools are supported. Codex asks OpenClaw to execute
|
||||
those tools, so OpenClaw remains in the execution path.
|
||||
- Codex-native shell, patch, MCP, and native app tools are owned by Codex.
|
||||
OpenClaw can observe or block selected native events through the
|
||||
supported relay, but it does not rewrite native tool arguments.
|
||||
- Codex owns native compaction. OpenClaw keeps a transcript mirror for
|
||||
channel history, search, `/new`, `/reset`, and future model or harness
|
||||
switching, but does not replace Codex compaction with an OpenClaw or
|
||||
context-engine summarizer.
|
||||
- Media generation, media understanding, TTS, approvals, and messaging-tool
|
||||
output continue through the matching OpenClaw provider/model settings.
|
||||
- `tool_result_persist` applies to OpenClaw-owned transcript tool results,
|
||||
not Codex-native tool result records.
|
||||
|
||||
For hook layers, supported V1 surfaces, native permission handling, queue
|
||||
steering, Codex feedback upload mechanics, and compaction details, see
|
||||
[Codex harness runtime](/plugins/codex-harness-runtime).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Codex does not appear as a normal `/model` provider:** expected for new
|
||||
configs. Select an `openai/gpt-*` model, enable
|
||||
`plugins.entries.codex.enabled`, and check whether `plugins.allow` excludes
|
||||
`codex`.
|
||||
|
||||
**OpenClaw uses the built-in harness instead of Codex:** confirm the model
|
||||
ref is `openai/gpt-*` on the official OpenAI provider and that the Codex
|
||||
plugin is installed and enabled. For strict proof while testing, set
|
||||
provider or model `agentRuntime.id: "codex"` — a forced Codex runtime fails
|
||||
instead of falling back to OpenClaw.
|
||||
|
||||
**OpenAI Codex runtime falls back to the API-key path:** collect a redacted
|
||||
gateway excerpt that shows the model, runtime, selected provider, and
|
||||
failure. Ask affected collaborators to run this read-only command on their
|
||||
OpenClaw host:
|
||||
|
||||
```bash
|
||||
(
|
||||
pattern='openai/gpt-5\.[45]|openai[-]codex|agentRuntime(\.id)?|harnessRuntime|Runtime: OpenAI Codex|legacy OpenAI Codex prefix|resolveSelectedOpenAIRuntimeProvider|candidateProvider[": ]+openai|status[": ]+401|Incorrect API key|No API key|api-key path|API-key path|OAuth'
|
||||
|
||||
if ls /tmp/openclaw/openclaw-*.log >/dev/null 2>&1; then
|
||||
grep -E -i -n "$pattern" /tmp/openclaw/openclaw-*.log 2>/dev/null || true
|
||||
else
|
||||
journalctl --user -u openclaw-gateway --since today --no-pager 2>/dev/null \
|
||||
| grep -E -i "$pattern" || true
|
||||
fi
|
||||
) | sed -E \
|
||||
-e 's/(Authorization: Bearer )[A-Za-z0-9._~+\/-]+/\1[REDACTED]/Ig' \
|
||||
-e 's/(Bearer )[A-Za-z0-9._~+\/-]+/\1[REDACTED]/Ig' \
|
||||
-e 's/(api[_ -]?key[=: ]+)[^ ,}"]+/\1[REDACTED]/Ig' \
|
||||
-e 's/(OPENAI_API_KEY[=: ]+)[^ ,}"]+/\1[REDACTED]/Ig' \
|
||||
-e 's/sk-[A-Za-z0-9_-]{12,}/sk-[REDACTED]/g' \
|
||||
-e 's/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/[EMAIL-REDACTED]/g' \
|
||||
| tail -200
|
||||
```
|
||||
|
||||
Useful excerpts usually include `openai/gpt-5.5` or `openai/gpt-5.4`,
|
||||
`Runtime: OpenAI Codex`, `agentRuntime.id` or `harnessRuntime`,
|
||||
`candidateProvider: "openai"`, and a `401`, `Incorrect API key`, or
|
||||
`No API key` result. A corrected run should show the OpenAI OAuth path
|
||||
instead of a plain OpenAI API-key failure.
|
||||
|
||||
**Legacy Codex model refs config remains:** run `openclaw doctor --fix`.
|
||||
Doctor rewrites legacy model refs to `openai/*`, removes stale session and
|
||||
whole-agent runtime pins, and preserves existing auth-profile overrides.
|
||||
|
||||
**The app-server is rejected:** use Codex app-server `0.125.0` or newer.
|
||||
Same-version prereleases or build-suffixed versions such as
|
||||
`0.125.0-alpha.2` or `0.125.0+custom` are rejected because OpenClaw tests
|
||||
the stable `0.125.0` protocol floor.
|
||||
|
||||
**`/codex status` cannot connect:** check that the bundled `codex` plugin
|
||||
is enabled, that `plugins.allow` includes it when an allowlist is
|
||||
configured, and that any custom `appServer.command`, `url`, `authToken`, or
|
||||
headers are valid.
|
||||
|
||||
**Model discovery is slow:** lower
|
||||
`plugins.entries.codex.config.discovery.timeoutMs` or disable discovery.
|
||||
See [Codex harness reference](/plugins/codex-harness-reference#model-discovery).
|
||||
|
||||
**WebSocket transport fails immediately:** check `appServer.url`,
|
||||
`authToken`, headers, and that the remote app-server speaks the same Codex
|
||||
app-server protocol version.
|
||||
|
||||
**Native shell or patch tools are blocked with `Native hook relay
|
||||
unavailable`:** the Codex thread is still trying to use a native hook relay
|
||||
id that OpenClaw no longer has registered. This is a native Codex hook
|
||||
transport problem, not an ACP backend, provider, GitHub, or shell-command
|
||||
failure. Start a fresh session in the affected chat with `/new` or `/reset`,
|
||||
then retry a harmless command. If that works once but the next native tool
|
||||
call fails again, treat `/new` as a temporary workaround only: copy the
|
||||
prompt into a fresh session after restarting the Codex app-server or
|
||||
OpenClaw Gateway so old threads are dropped and native hook registrations
|
||||
are recreated.
|
||||
|
||||
**A non-Codex model uses the built-in harness:** expected unless provider
|
||||
or model runtime policy routes it to another harness. Plain non-OpenAI
|
||||
provider refs stay on their normal provider path in `auto` mode.
|
||||
|
||||
**Computer Use is installed but tools do not run:** check
|
||||
`/codex computer-use status` from a fresh session. If a tool reports
|
||||
`Native hook relay unavailable`, use the native hook relay recovery above.
|
||||
See [Codex Computer Use](/plugins/codex-computer-use#troubleshooting).
|
||||
|
||||
## Related
|
||||
|
||||
- [Codex harness reference](/plugins/codex-harness-reference)
|
||||
- [Codex harness runtime](/plugins/codex-harness-runtime)
|
||||
- [Native Codex plugins](/plugins/codex-native-plugins)
|
||||
- [Codex Computer Use](/plugins/codex-computer-use)
|
||||
- [Agent runtimes](/concepts/agent-runtimes)
|
||||
- [Model providers](/concepts/model-providers)
|
||||
- [OpenAI provider](/providers/openai)
|
||||
- [OpenAI Codex help](https://help.openai.com/en/collections/14937394-codex)
|
||||
- [Agent harness plugins](/plugins/sdk-agent-harness)
|
||||
- [Plugin hooks](/plugins/hooks)
|
||||
- [Diagnostics export](/gateway/diagnostics)
|
||||
- [Status](/cli/status)
|
||||
- [Testing](/help/testing-live#live-codex-app-server-harness-smoke)
|
||||
263
docs/plugins/codex-native-plugins.md
Normal file
263
docs/plugins/codex-native-plugins.md
Normal file
@@ -0,0 +1,263 @@
|
||||
---
|
||||
summary: "Configure migrated native Codex plugins for Codex-mode OpenClaw agents"
|
||||
title: "Native Codex plugins"
|
||||
read_when:
|
||||
- You want Codex-mode OpenClaw agents to use native Codex plugins
|
||||
- You are migrating source-installed openai-curated Codex plugins
|
||||
- You are troubleshooting codexPlugins, app inventory, destructive actions, or plugin app diagnostics
|
||||
---
|
||||
|
||||
Native Codex plugin support lets a Codex-mode OpenClaw agent use Codex
|
||||
app-server's own app and plugin capabilities inside the same Codex thread that
|
||||
handles the OpenClaw turn. Plugin calls stay in the native Codex transcript;
|
||||
Codex app-server owns app-backed MCP execution. OpenClaw does not translate
|
||||
Codex plugins into synthetic `codex_plugin_*` OpenClaw dynamic tools.
|
||||
|
||||
Use this page after the base [Codex harness](/plugins/codex-harness) is
|
||||
working.
|
||||
|
||||
## Requirements
|
||||
|
||||
- The agent runtime must be the native Codex harness.
|
||||
- `plugins.entries.codex.enabled` is `true`.
|
||||
- `plugins.entries.codex.config.codexPlugins.enabled` is `true`.
|
||||
- The target Codex app-server can see the expected marketplace, plugin, and
|
||||
app inventory.
|
||||
- V1 supports only `openai-curated` plugins that migration observed as
|
||||
source-installed in the source Codex home.
|
||||
|
||||
`codexPlugins` has no effect on OpenClaw-provider runs, ACP conversation
|
||||
bindings, or other harnesses, because those paths never create Codex
|
||||
app-server threads with native `apps` config.
|
||||
|
||||
OpenAI-side Codex account, app availability, and workspace app/plugin controls
|
||||
come from the signed-in Codex account. See
|
||||
[Using Codex with your ChatGPT plan](https://help.openai.com/en/articles/11369540-using-codex-with-your-chatgpt-plan)
|
||||
for the OpenAI account and admin model.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Preview migration from the source Codex home:
|
||||
|
||||
```bash
|
||||
openclaw migrate codex --dry-run
|
||||
```
|
||||
|
||||
Add `--verify-plugin-apps` to make migration call source `app/list` and
|
||||
require every owned app to be present, enabled, and accessible before
|
||||
planning native activation:
|
||||
|
||||
```bash
|
||||
openclaw migrate codex --dry-run --verify-plugin-apps
|
||||
```
|
||||
|
||||
Apply the migration when the plan looks right:
|
||||
|
||||
```bash
|
||||
openclaw migrate apply codex --yes
|
||||
```
|
||||
|
||||
Migration writes explicit `codexPlugins` entries for eligible plugins and
|
||||
calls Codex app-server `plugin/install` for selected plugins. A migrated
|
||||
config looks like this:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
codex: {
|
||||
enabled: true,
|
||||
config: {
|
||||
codexPlugins: {
|
||||
enabled: true,
|
||||
allow_destructive_actions: true,
|
||||
plugins: {
|
||||
"google-calendar": {
|
||||
enabled: true,
|
||||
marketplaceName: "openai-curated",
|
||||
pluginName: "google-calendar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
After a `codexPlugins` change, new Codex conversations pick up the updated
|
||||
app set automatically. Run `/new` or `/reset` to refresh the current
|
||||
conversation. A gateway restart is not required for plugin enable/disable
|
||||
changes.
|
||||
|
||||
## Manage plugins from chat
|
||||
|
||||
`/codex plugins` inspects or changes configured native Codex plugins from the
|
||||
same chat where you operate the Codex harness:
|
||||
|
||||
```text
|
||||
/codex plugins
|
||||
/codex plugins list
|
||||
/codex plugins disable google-calendar
|
||||
/codex plugins enable google-calendar
|
||||
```
|
||||
|
||||
`/codex plugins` is an alias for `/codex plugins list`. The list shows each
|
||||
configured plugin's key, on/off state, Codex plugin name, and marketplace
|
||||
from `plugins.entries.codex.config.codexPlugins.plugins`.
|
||||
|
||||
`enable`/`disable` write only to `~/.openclaw/openclaw.json`; they never edit
|
||||
`~/.codex/config.toml` or install new Codex plugins. Only the owner or a
|
||||
gateway client with the `operator.admin` scope can run them.
|
||||
|
||||
Enabling a configured plugin also turns on the global `codexPlugins.enabled`
|
||||
switch. If the plugin was written disabled because migration returned
|
||||
`auth_required`, reauthorize the app in Codex before enabling it in OpenClaw.
|
||||
|
||||
## How native plugin setup works
|
||||
|
||||
The integration tracks three states:
|
||||
|
||||
| State | Meaning |
|
||||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Installed | Codex has the local plugin bundle in the target app-server runtime. |
|
||||
| Enabled | OpenClaw config allows the plugin for Codex harness turns. |
|
||||
| Accessible | Codex app-server confirms the plugin's app entries are available for the active account and map to the migrated plugin identity. |
|
||||
|
||||
Migration is the durable install/eligibility step:
|
||||
|
||||
- During planning, OpenClaw reads source Codex `plugin/read` details and
|
||||
checks that the source Codex app-server account is a ChatGPT subscription
|
||||
account. A non-ChatGPT or missing account response skips app-backed
|
||||
plugins with `codex_subscription_required`.
|
||||
- By default, migration skips the source `app/list` call: app-backed source
|
||||
plugins that pass the account gate are planned without source app
|
||||
accessibility verification, and account-lookup transport failures skip
|
||||
with `codex_account_unavailable`.
|
||||
- With `--verify-plugin-apps`, migration takes a fresh source `app/list`
|
||||
snapshot and requires every owned app to be present, enabled, and
|
||||
accessible before planning native activation. Account-lookup transport
|
||||
failures then fall through to the source app-inventory gate instead of
|
||||
skipping outright.
|
||||
|
||||
Runtime app inventory is the target-session accessibility check that runs
|
||||
after migration. Codex harness session setup computes a restrictive thread
|
||||
app config from the enabled and accessible plugin apps; it is not
|
||||
recomputed on every turn, so `/codex plugins enable`/`disable` only affect
|
||||
new Codex conversations. Use `/new` or `/reset` to pick up the change in the
|
||||
current conversation.
|
||||
|
||||
## V1 support boundary
|
||||
|
||||
- Only `openai-curated` plugins already installed in the source Codex
|
||||
app-server inventory are migration-eligible.
|
||||
- App-backed source plugins must pass the migration-time subscription gate.
|
||||
`--verify-plugin-apps` adds the source app-inventory gate. Subscription-gated
|
||||
accounts, and in verification mode inaccessible/disabled/missing source
|
||||
apps or app-inventory refresh failures, are reported as skipped manual
|
||||
items instead of enabled config entries. Unreadable plugin details are
|
||||
skipped before the app-inventory gate.
|
||||
- Migration writes explicit plugin identities (`marketplaceName` and
|
||||
`pluginName`); it does not write local `marketplacePath` cache paths.
|
||||
- `codexPlugins.enabled` is the only global enablement switch; there is no
|
||||
`plugins["*"]` wildcard or config key that grants arbitrary install
|
||||
authority.
|
||||
- Unsupported marketplaces, cached plugin bundles, hooks, and Codex config
|
||||
files are preserved in the migration report for manual review, not
|
||||
activated automatically.
|
||||
|
||||
## App inventory and ownership
|
||||
|
||||
OpenClaw reads Codex app inventory through app-server `app/list`, caches it
|
||||
in memory for one hour, and refreshes stale or missing entries
|
||||
asynchronously. The cache is process-local; restarting the CLI or gateway
|
||||
drops it, and OpenClaw rebuilds it from the next `app/list` read.
|
||||
|
||||
Migration and runtime use separate cache keys:
|
||||
|
||||
- Source migration verification uses the source Codex home and start
|
||||
options. It runs only with `--verify-plugin-apps` and forces a fresh
|
||||
source `app/list` traversal for that planning run.
|
||||
- Target runtime setup uses the target agent's Codex app-server identity
|
||||
when building the thread app config. Plugin activation invalidates that
|
||||
target cache key, then force-refreshes it after `plugin/install`.
|
||||
|
||||
A plugin app is exposed only when OpenClaw can map it back to the migrated
|
||||
plugin through stable ownership: an exact app id from plugin detail, a known
|
||||
MCP server name, or unique stable metadata. Display-name-only or ambiguous
|
||||
ownership is excluded until the next inventory refresh proves ownership.
|
||||
|
||||
## Thread app config
|
||||
|
||||
OpenClaw injects a restrictive `config.apps` patch for the Codex thread:
|
||||
`_default` is disabled, and only apps owned by enabled migrated plugins are
|
||||
enabled.
|
||||
|
||||
`destructive_enabled` on each app comes from the effective global or
|
||||
per-plugin `allow_destructive_actions` policy; `true`, `"auto"`, and `"ask"`
|
||||
all set `destructive_enabled: true`, and `false` sets it `false`. Codex still
|
||||
enforces destructive tool metadata from its native app tool annotations.
|
||||
`_default` is disabled with `open_world_enabled: false`; enabled plugin apps
|
||||
get `open_world_enabled: true`. OpenClaw does not expose a separate
|
||||
plugin-level open-world policy knob and does not maintain per-plugin
|
||||
destructive tool-name deny lists.
|
||||
|
||||
Tool approval mode defaults to automatic for plugin apps, so non-destructive
|
||||
read tools run without a same-thread approval prompt. Destructive tools stay
|
||||
controlled by each app's `destructive_enabled` policy.
|
||||
|
||||
## Destructive action policy
|
||||
|
||||
Destructive plugin elicitations are allowed by default for migrated Codex
|
||||
plugins, while unsafe schemas and ambiguous ownership fail closed:
|
||||
|
||||
- Global `allow_destructive_actions` defaults to `true`.
|
||||
- Per-plugin `allow_destructive_actions` overrides the global policy for
|
||||
that plugin.
|
||||
- `false`: OpenClaw returns a deterministic decline.
|
||||
- `true`: OpenClaw auto-accepts only safe schemas it can map to an approval
|
||||
response, such as a boolean approve field.
|
||||
- `"auto"`: OpenClaw exposes destructive plugin actions to Codex, then
|
||||
turns ownership-proven MCP approval elicitations into OpenClaw plugin
|
||||
approvals before returning the Codex approval response.
|
||||
- `"ask"`: OpenClaw uses the same Codex write/destructive gating as
|
||||
`"auto"`, clears durable Codex per-tool approval overrides for the app
|
||||
before the thread starts, and offers only one-shot approval or denial so
|
||||
durable approvals cannot suppress later write-action prompts. For each
|
||||
admitted app using `"ask"`, OpenClaw selects Codex's human approvals
|
||||
reviewer for that app so Codex sends its approval elicitations to
|
||||
OpenClaw; other apps and non-app thread approvals keep their configured
|
||||
reviewer and policy.
|
||||
- Missing plugin identity, ambiguous ownership, a missing or mismatched
|
||||
turn id, or an unsafe elicitation schema declines instead of prompting.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Code | Meaning | Fix |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| `auth_required` | Migration installed the plugin, but one of its apps still needs authentication. The entry is written disabled until you reauthorize. | Reauthorize the app in Codex, then enable the plugin in OpenClaw. |
|
||||
| `app_inaccessible`, `app_disabled`, `app_missing` | With `--verify-plugin-apps`, the source Codex app inventory did not show all owned apps as present, enabled, and accessible. | Reauthorize or enable the app in Codex, then rerun migration with `--verify-plugin-apps`. |
|
||||
| `app_inventory_unavailable` | Strict source app verification was requested but the source Codex app inventory refresh failed. | Fix source Codex app-server access, or retry without `--verify-plugin-apps` to accept the faster account-gated plan. |
|
||||
| `codex_subscription_required` | The source Codex app-server account was not a ChatGPT subscription account. | Log in to the Codex app with subscription auth, then rerun migration. |
|
||||
| `codex_account_unavailable` | The source Codex app-server account could not be read. | Fix source Codex app-server auth, or rerun with `--verify-plugin-apps` to let source app inventory decide eligibility. |
|
||||
| `marketplace_missing`, `plugin_missing` | The target Codex app-server cannot see the expected `openai-curated` marketplace or plugin. | Rerun migration against the target runtime, or inspect Codex app-server plugin status. |
|
||||
| `app_inventory_missing`, `app_inventory_stale` | App readiness came from an empty or stale cache. | OpenClaw schedules an async refresh automatically; plugin apps stay excluded until ownership and readiness are known. |
|
||||
| `app_ownership_ambiguous` | App inventory only matched by display name. | The app stays hidden from the Codex thread until a later refresh proves ownership. |
|
||||
|
||||
**Config changed but the agent cannot see the plugin:** run `/codex plugins
|
||||
list` to confirm the configured state, then `/new` or `/reset`. Existing
|
||||
Codex thread bindings keep the app config they started with until OpenClaw
|
||||
establishes a new harness session or replaces a stale binding.
|
||||
|
||||
**Destructive action is declined:** check the global and per-plugin
|
||||
`allow_destructive_actions` values. Even with `true`, `"auto"`, or `"ask"`,
|
||||
unsafe elicitation schemas and ambiguous plugin identity still fail closed.
|
||||
|
||||
## Related
|
||||
|
||||
- [Codex harness](/plugins/codex-harness)
|
||||
- [Codex harness reference](/plugins/codex-harness-reference)
|
||||
- [Codex harness runtime](/plugins/codex-harness-runtime)
|
||||
- [Configuration reference](/gateway/configuration-reference#codex-harness-plugin-config)
|
||||
- [Migrate CLI](/cli/migrate)
|
||||
78
docs/plugins/community.md
Normal file
78
docs/plugins/community.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
summary: "Find and publish community-maintained OpenClaw plugins"
|
||||
read_when:
|
||||
- You want to find third-party OpenClaw plugins
|
||||
- You want to publish or list your own plugin on ClawHub
|
||||
title: "Community plugins"
|
||||
doc-schema-version: 1
|
||||
---
|
||||
|
||||
Community plugins are third-party packages that extend OpenClaw with
|
||||
channels, tools, providers, hooks, or other capabilities. Use
|
||||
[ClawHub](/clawhub) as the primary discovery surface for public community
|
||||
plugins.
|
||||
|
||||
## Find plugins
|
||||
|
||||
Search ClawHub from the CLI:
|
||||
|
||||
```bash
|
||||
openclaw plugins search "calendar"
|
||||
```
|
||||
|
||||
Install a ClawHub plugin with an explicit source prefix:
|
||||
|
||||
```bash
|
||||
openclaw plugins install clawhub:<package-name>
|
||||
```
|
||||
|
||||
npm remains a supported direct-install path during the launch cutover:
|
||||
|
||||
```bash
|
||||
openclaw plugins install npm:<package-name>
|
||||
```
|
||||
|
||||
Use [Manage plugins](/plugins/manage-plugins) for common install, update,
|
||||
inspect, and uninstall examples. Use [`openclaw plugins`](/cli/plugins) for
|
||||
the full command reference and source-selection rules.
|
||||
|
||||
## Publish plugins
|
||||
|
||||
Publish public community plugins on ClawHub so OpenClaw users can discover
|
||||
and install them. ClawHub owns the live package listing, release history,
|
||||
scan status, and install hints; the docs do not maintain a static
|
||||
third-party plugin catalog.
|
||||
|
||||
```bash
|
||||
clawhub package publish your-org/your-plugin --dry-run
|
||||
clawhub package publish your-org/your-plugin
|
||||
```
|
||||
|
||||
Before publishing, make sure the plugin has package metadata, a plugin
|
||||
manifest, setup docs, and a clear maintenance owner. ClawHub validates owner
|
||||
scope, package name, version, file limits, and source metadata before
|
||||
creating a release, then keeps new releases hidden from normal install and
|
||||
download surfaces until review and verification finish.
|
||||
|
||||
Checklist before you publish:
|
||||
|
||||
| Requirement | Why |
|
||||
| -------------------- | --------------------------------------------------- |
|
||||
| Published on ClawHub | Users need `openclaw plugins install` hints to work |
|
||||
| Public GitHub repo | Source review, issue tracking, transparency |
|
||||
| Setup and usage docs | Users need to know how to configure it |
|
||||
| Active maintenance | Recent updates or responsive issue handling |
|
||||
|
||||
Full publishing contract:
|
||||
|
||||
- [ClawHub publishing](/clawhub/publishing) - owners, scopes, releases,
|
||||
review, package validation, and package transfer
|
||||
- [Building plugins](/plugins/building-plugins) - the plugin package shape
|
||||
and first publish workflow
|
||||
- [Plugin manifest](/plugins/manifest) - native plugin manifest fields
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugins](/tools/plugin) - install, configure, restart, and troubleshoot
|
||||
- [Manage plugins](/plugins/manage-plugins) - command examples
|
||||
- [ClawHub publishing](/clawhub/publishing) - publish and release rules
|
||||
203
docs/plugins/compatibility.md
Normal file
203
docs/plugins/compatibility.md
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
summary: "Plugin compatibility contracts, deprecation metadata, and migration expectations"
|
||||
title: "Plugin compatibility"
|
||||
read_when:
|
||||
- You maintain an OpenClaw plugin
|
||||
- You see a plugin compatibility warning
|
||||
- You are planning a plugin SDK or manifest migration
|
||||
---
|
||||
|
||||
OpenClaw keeps older plugin contracts wired through named compatibility
|
||||
adapters before removing them. This protects existing bundled and external
|
||||
plugins while the SDK, manifest, setup, config, and agent runtime contracts
|
||||
evolve.
|
||||
|
||||
## Compatibility registry
|
||||
|
||||
Plugin compatibility contracts are tracked in the core registry at
|
||||
`src/plugins/compat/registry.ts`. Each record has:
|
||||
|
||||
- a stable compatibility code
|
||||
- status: `active`, `deprecated`, `removal-pending`, or `removed`
|
||||
- owner: `sdk`, `config`, `setup`, `channel`, `provider`, `plugin-execution`,
|
||||
`agent-runtime`, or `core`
|
||||
- introduction and deprecation dates when applicable
|
||||
- replacement guidance
|
||||
- docs, diagnostics, and tests that cover the old and new behavior
|
||||
|
||||
The registry is the source for maintainer planning and future plugin
|
||||
inspector checks. If a plugin-facing behavior changes, add or update the
|
||||
compatibility record in the same change that adds the adapter.
|
||||
|
||||
Doctor repair and migration compatibility is tracked separately at
|
||||
`src/commands/doctor/shared/deprecation-compat.ts`. Those records cover old
|
||||
config shapes, install-ledger layouts, and repair shims that may need to
|
||||
stay available after the runtime compatibility path is removed.
|
||||
|
||||
Release sweeps should check both registries. Do not delete a doctor
|
||||
migration just because the matching runtime or config compatibility record
|
||||
expired; first verify there is no supported upgrade path that still needs
|
||||
the repair. Revalidate each replacement annotation during release planning
|
||||
too, since plugin ownership and config footprint can change as providers
|
||||
and channels move out of core.
|
||||
|
||||
## Deprecation policy
|
||||
|
||||
OpenClaw should not remove a documented plugin contract in the same release
|
||||
that introduces its replacement. Migration sequence:
|
||||
|
||||
1. Add the new contract.
|
||||
2. Keep the old behavior wired through a named compatibility adapter.
|
||||
3. Emit diagnostics or warnings when plugin authors can act.
|
||||
4. Document the replacement and timeline.
|
||||
5. Test both old and new paths.
|
||||
6. Wait through the announced migration window.
|
||||
7. Remove only with explicit breaking-release approval.
|
||||
|
||||
Deprecated records must include a warning start date, replacement, docs
|
||||
link, and a final removal date no more than three months after the warning
|
||||
starts. Do not add a deprecated compatibility path with an open-ended
|
||||
removal window unless maintainers explicitly decide it is permanent
|
||||
compatibility and mark it `active` instead.
|
||||
|
||||
## Current compatibility areas
|
||||
|
||||
The registry currently tracks around 70 compatibility codes across these
|
||||
areas. New plugin code should use the replacement in each area and in the
|
||||
specific migration guide; existing plugins can keep using a compatibility
|
||||
path until docs, diagnostics, and release notes announce a removal window.
|
||||
|
||||
- legacy broad SDK imports such as `openclaw/plugin-sdk/compat`
|
||||
- legacy hook-only plugin shapes and `before_agent_start`
|
||||
- legacy `api.on("deactivate", ...)` cleanup hook names while plugins
|
||||
migrate to `gateway_stop`
|
||||
- legacy `activate(api)` plugin entrypoints while plugins migrate to
|
||||
`register(api)`
|
||||
- legacy SDK aliases such as `openclaw/extension-api`,
|
||||
`openclaw/plugin-sdk/channel-runtime`, `openclaw/plugin-sdk/command-auth`
|
||||
status builders, `openclaw/plugin-sdk/test-utils` (replaced by focused
|
||||
`openclaw/plugin-sdk/*` test subpaths), and the `ClawdbotConfig` /
|
||||
`OpenClawSchemaType` type aliases
|
||||
- bundled plugin allowlist and enablement behavior
|
||||
- legacy provider/channel env-var manifest metadata
|
||||
- legacy provider plugin hooks and type aliases while providers move to
|
||||
explicit catalog, auth, thinking, replay, and transport hooks
|
||||
- legacy runtime aliases such as `api.runtime.taskFlow`,
|
||||
`api.runtime.subagent.getSession`, `api.runtime.stt`, and deprecated
|
||||
`api.runtime.config.loadConfig()` / `api.runtime.config.writeConfigFile(...)`
|
||||
- WhatsApp `WebInboundMessage` flat callback fields (see below)
|
||||
- WhatsApp `WebInboundMessage` top-level admission fields (see below)
|
||||
- legacy memory-plugin split registration while memory plugins move to
|
||||
`registerMemoryCapability`
|
||||
- legacy memory-specific embedding provider registration while embedding
|
||||
providers move to `api.registerEmbeddingProvider(...)` and
|
||||
`contracts.embeddingProviders`
|
||||
- legacy channel SDK helpers for native message schemas, mention gating,
|
||||
inbound envelope formatting, and approval capability nesting
|
||||
- legacy channel route key and comparable-target helper aliases while
|
||||
plugins move to `openclaw/plugin-sdk/channel-route`
|
||||
- activation hints being replaced by manifest contribution ownership
|
||||
- `setup-api` runtime fallback while setup descriptors move to cold
|
||||
`setup.requiresRuntime: false` metadata
|
||||
- provider `discovery` hooks while provider catalog hooks move to
|
||||
`catalog.run(...)`
|
||||
- channel `showConfigured` / `showInSetup` metadata while channel packages
|
||||
move to `openclaw.channel.exposure`
|
||||
- legacy runtime-policy config keys while doctor migrates operators to
|
||||
`agentRuntime`
|
||||
- generated bundled channel config metadata fallback while registry-first
|
||||
`channelConfigs` metadata lands
|
||||
- persisted plugin registry disable and install-migration env flags while
|
||||
repair flows migrate operators to `openclaw plugins registry --refresh`
|
||||
and `openclaw doctor --fix`
|
||||
- legacy plugin-owned web search, web fetch, and x_search config paths
|
||||
while doctor migrates them to `plugins.entries.<plugin>.config`
|
||||
- legacy `plugins.installs` authored config and bundled plugin load-path
|
||||
aliases while install metadata moves into the state-managed plugin ledger
|
||||
|
||||
### WhatsApp inbound callback flat aliases
|
||||
|
||||
WhatsApp runtime callbacks deliver `WebInboundMessage`: the canonical
|
||||
nested `event`, `payload`, `quote`, `group`, and `platform` contexts plus
|
||||
deprecated flat aliases for the shipped callback fields. New callback code
|
||||
should read the nested contexts. Code that constructs clean nested callback
|
||||
messages can use `WebInboundCallbackMessage`; compatibility listeners that
|
||||
still inject old flat test or plugin messages should use
|
||||
`LegacyFlatWebInboundMessage` or `WebInboundMessageInput`.
|
||||
|
||||
The flat aliases remain available until **2026-08-30**; that window applies
|
||||
only to flat alias access, not to the nested shape, which is the canonical
|
||||
runtime contract. Each flat alias's TypeScript `@deprecated` annotation
|
||||
names its exact nested replacement. Common examples:
|
||||
|
||||
- `id`, `timestamp`, and `isBatched` move under `event`.
|
||||
- `body`, `mediaPath`, `mediaType`, `mediaFileName`, `mediaUrl`, `location`,
|
||||
and `untrustedStructuredContext` move under `payload`.
|
||||
- `to`, `chatId`, sender/self fields, `sendComposing`, `reply(...)`, and
|
||||
`sendMedia(...)` move under `platform`.
|
||||
- `replyTo*` fields move under `quote`; group subject/participant/mention
|
||||
fields move under `group`.
|
||||
|
||||
`payload.untrustedStructuredContext` is extracted from inbound provider
|
||||
payloads. Plugins should inspect `label`, `source`, and `type` before
|
||||
treating its `payload` as authoritative.
|
||||
|
||||
### WhatsApp inbound admission fields
|
||||
|
||||
Accepted WhatsApp callback messages carry `admission`, a public-safe
|
||||
envelope for the access-control decision that admitted the message. New
|
||||
callback code should read admission facts from `msg.admission` instead of
|
||||
the older top-level admission fields.
|
||||
|
||||
The top-level fields remain available until **2026-08-30**. Each field's
|
||||
TypeScript `@deprecated` annotation names its replacement:
|
||||
|
||||
- `from` and `conversationId` move to `admission.conversation.id`.
|
||||
- `accountId` moves to `admission.accountId`.
|
||||
- `accessControlPassed` is a derived compatibility view of
|
||||
`admission.ingress.decision === "allow"`; on messages that already carry
|
||||
`admission`, writing the legacy boolean does not rewrite the ingress
|
||||
graph.
|
||||
- `chatType` moves to `admission.conversation.kind`.
|
||||
|
||||
## Plugin inspector package
|
||||
|
||||
The plugin inspector should live outside the core OpenClaw repo as a
|
||||
separate package/repository backed by the versioned compatibility and
|
||||
manifest contracts. The day-one CLI should be:
|
||||
|
||||
```sh
|
||||
openclaw-plugin-inspector ./my-plugin
|
||||
```
|
||||
|
||||
It should emit manifest/schema validation, the contract compatibility
|
||||
version being checked, install/source metadata checks, cold-path import
|
||||
checks, and deprecation/compatibility warnings. Use `--json` for stable
|
||||
machine-readable output in CI annotations. OpenClaw core should expose
|
||||
contracts and fixtures the inspector can consume, but should not publish the
|
||||
inspector binary from the main `openclaw` package.
|
||||
|
||||
### Maintainer acceptance lane
|
||||
|
||||
Use Crabbox-backed Blacksmith Testbox for the installable-package acceptance
|
||||
lane when validating the external inspector against OpenClaw plugin
|
||||
packages. Run it from a clean OpenClaw checkout after the package is built:
|
||||
|
||||
```sh
|
||||
pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "pnpm install && pnpm build && npm exec --yes @openclaw/plugin-inspector@0.1.0 -- ./extensions/telegram --json"
|
||||
pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "npm exec --yes @openclaw/plugin-inspector@0.1.0 -- ./extensions/discord --json"
|
||||
pnpm crabbox:run -- --provider blacksmith-testbox --timing-json --shell -- "npm exec --yes @openclaw/plugin-inspector@0.1.0 -- <clawhub-plugin-dir> --json"
|
||||
```
|
||||
|
||||
Keep this lane opt-in for maintainers, since it installs an external npm
|
||||
package and may inspect plugin packages cloned outside the repo. The local
|
||||
repo guards cover the SDK export map, compatibility registry metadata,
|
||||
deprecated SDK-import burn-down, and bundled extension import boundaries;
|
||||
Testbox inspector proof covers the package as external plugin authors
|
||||
consume it.
|
||||
|
||||
## Release notes
|
||||
|
||||
Release notes should include upcoming plugin deprecations with target dates
|
||||
and links to migration docs, before a compatibility path moves to
|
||||
`removal-pending` or `removed`.
|
||||
373
docs/plugins/copilot.md
Executable file
373
docs/plugins/copilot.md
Executable file
@@ -0,0 +1,373 @@
|
||||
---
|
||||
summary: "Run OpenClaw embedded agent turns through the external GitHub Copilot SDK harness"
|
||||
title: "Copilot SDK harness"
|
||||
read_when:
|
||||
- You want to use the GitHub Copilot SDK harness for an agent
|
||||
- You need configuration examples for the `copilot` runtime
|
||||
- You are wiring an agent to subscription Copilot (github / openclaw / copilot) and want it to run through the Copilot CLI
|
||||
---
|
||||
|
||||
The external `@openclaw/copilot` plugin runs embedded subscription Copilot
|
||||
agent turns through the GitHub Copilot CLI (`@github/copilot-sdk`) instead of
|
||||
OpenClaw's built-in PI harness. The Copilot CLI session owns the low-level
|
||||
agent loop: native tool execution, native compaction (`infiniteSessions`), and
|
||||
CLI-managed thread state under `copilotHome`. OpenClaw still owns chat
|
||||
channels, session files, model selection, dynamic tools (bridged), approvals,
|
||||
media delivery, the visible transcript mirror, `/btw` side questions (see
|
||||
[Side questions (`/btw`)](#side-questions-btw)), and `openclaw doctor`.
|
||||
|
||||
For the broader model/provider/runtime split, start with
|
||||
[Agent runtimes](/concepts/agent-runtimes).
|
||||
|
||||
## Requirements
|
||||
|
||||
- OpenClaw with the `@openclaw/copilot` plugin installed.
|
||||
- If your config uses `plugins.allow`, include `copilot` (the manifest id the
|
||||
plugin declares). An allowlist entry for the npm package name
|
||||
`@openclaw/copilot` will not match and leaves the plugin blocked, even with
|
||||
`agentRuntime.id: "copilot"` set.
|
||||
- A GitHub Copilot subscription that can drive the Copilot CLI, or a
|
||||
`gitHubToken` env var / auth-profile entry for headless or cron runs.
|
||||
- A writable `copilotHome` directory. Defaults to `<agentDir>/copilot` when
|
||||
OpenClaw provides an agent directory, otherwise
|
||||
`~/.openclaw/agents/<agentId>/copilot`.
|
||||
|
||||
`openclaw doctor` runs the plugin's [doctor contract](#doctor) for
|
||||
session-state ownership and future config migrations. It does not probe the
|
||||
Copilot CLI environment.
|
||||
|
||||
## Install
|
||||
|
||||
The Copilot runtime ships as an external plugin so the core `openclaw`
|
||||
package does not carry `@github/copilot-sdk` or its platform-specific
|
||||
`@github/copilot-<platform>-<arch>` CLI binary (roughly 260 MB together).
|
||||
Install it only for agents that opt into this runtime:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/copilot
|
||||
```
|
||||
|
||||
The setup wizard installs the plugin automatically the first time you select
|
||||
a `github-copilot/*` model **and** your config routes that model (or its
|
||||
provider) to the Copilot runtime via `agentRuntime: { id: "copilot" }`; see
|
||||
[Quickstart](#quickstart). Without that opt-in, OpenClaw uses its built-in
|
||||
GitHub Copilot provider and never installs this plugin.
|
||||
|
||||
The runtime resolves the SDK in this order:
|
||||
|
||||
1. `import("@github/copilot-sdk")` from the installed `@openclaw/copilot`
|
||||
package.
|
||||
2. The fallback dir `~/.openclaw/npm-runtime/copilot/` (legacy on-demand
|
||||
install target).
|
||||
|
||||
A missing SDK surfaces one error with code `COPILOT_SDK_MISSING` and the
|
||||
reinstall command above.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Pin one model (or one provider) to the harness:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "github-copilot/auto",
|
||||
models: {
|
||||
"github-copilot/auto": {
|
||||
agentRuntime: { id: "copilot" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Set `agentRuntime.id` on a single model entry to route only that model through
|
||||
the harness, or on a provider to route every model under that provider.
|
||||
|
||||
`github-copilot/auto` is the portable starting point. Named Copilot models are
|
||||
account- and organization-policy-dependent; confirm your authenticated
|
||||
Copilot CLI actually exposes a model before pinning it.
|
||||
|
||||
## Supported providers
|
||||
|
||||
The harness supports the canonical `github-copilot` provider (owned by
|
||||
`extensions/github-copilot`), plus custom `models.providers` entries when the
|
||||
model has a non-empty `baseUrl` and one of these `api` shapes:
|
||||
|
||||
- `anthropic-messages`
|
||||
- `azure-openai-responses`
|
||||
- `ollama` (OpenAI-compatible completions)
|
||||
- `openai-completions`
|
||||
- `openai-responses`
|
||||
|
||||
Native provider ids (`openai`, `anthropic`, `google`, `ollama`) stay owned by
|
||||
their native runtimes. Use a distinct custom provider id to route an endpoint
|
||||
through Copilot BYOK instead.
|
||||
|
||||
Copilot BYOK endpoints must be public HTTPS URLs. The harness gives the
|
||||
Copilot SDK a per-attempt loopback proxy, then forwards provider traffic
|
||||
through OpenClaw's guarded fetch path so DNS pinning and SSRF policy stay
|
||||
owned by OpenClaw. Use the native OpenClaw runtime for local Ollama, LM
|
||||
Studio, or LAN model servers.
|
||||
|
||||
## BYOK
|
||||
|
||||
Copilot BYOK uses the SDK's session-level custom provider contract. OpenClaw
|
||||
passes the resolved model endpoint, API key, bearer-token mode, headers, model
|
||||
id, and context/output limits; provider transport logic stays in the SDK, not
|
||||
core.
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "custom-proxy/llama-3.1-8b",
|
||||
models: {
|
||||
"custom-proxy/llama-3.1-8b": {
|
||||
agentRuntime: { id: "copilot" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
"custom-proxy": {
|
||||
baseUrl: "https://api.example.com/v1",
|
||||
apiKey: "${CUSTOM_PROXY_API_KEY}",
|
||||
api: "openai-responses",
|
||||
authHeader: true,
|
||||
models: [{ id: "llama-3.1-8b", name: "Llama 3.1 8B" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
BYOK sessions are keyed separately from subscription sessions and from other
|
||||
BYOK endpoints or credentials. Rotating the key, headers, model, or endpoint
|
||||
starts a fresh Copilot SDK session instead of resuming incompatible state.
|
||||
|
||||
## Auth
|
||||
|
||||
Precedence, applied per agent during `runCopilotAttempt`:
|
||||
|
||||
1. **Explicit `useLoggedInUser: true`** on the attempt input — uses the
|
||||
Copilot CLI's logged-in user under the agent's `copilotHome`.
|
||||
2. **Explicit `gitHubToken`** on the attempt input (requires `profileId` +
|
||||
`profileVersion`). For direct CLI invocations and tests that need to
|
||||
bypass auth-profile resolution.
|
||||
3. **Contract-resolved `resolvedApiKey` + `authProfileId`** — the production
|
||||
main path. Core resolves the agent's configured `github-copilot` auth
|
||||
profile (`src/infra/provider-usage.auth.ts:resolveProviderAuths`) before
|
||||
invoking the harness, so a `github-copilot:<profile>` auth profile works
|
||||
end-to-end for headless, cron, or multi-profile setups without env vars.
|
||||
4. **Env-var fallback**, checked in this order (first non-empty value wins,
|
||||
empty strings count as absent; mirrors the shipped `github-copilot`
|
||||
provider precedence in `extensions/github-copilot/auth.ts`):
|
||||
1. `OPENCLAW_GITHUB_TOKEN` — harness-specific override; lets you pin a
|
||||
token for the OpenClaw harness without disturbing system-wide `gh` /
|
||||
Copilot CLI config.
|
||||
2. `COPILOT_GITHUB_TOKEN` — standard Copilot SDK / CLI env var.
|
||||
3. `GH_TOKEN` — standard `gh` CLI env var.
|
||||
4. `GITHUB_TOKEN` — generic GitHub token fallback.
|
||||
|
||||
The synthesized pool profile id is `env:<NAME>`; the profile version is a
|
||||
non-reversible sha256 fingerprint of the token, so rotating the env value
|
||||
busts the client pool cleanly.
|
||||
|
||||
5. **Default `useLoggedInUser`** when no token signal is available.
|
||||
|
||||
Each agent gets its own `copilotHome` so Copilot CLI tokens, sessions, and
|
||||
config never leak between agents on the same machine. Default:
|
||||
`<agentDir>/copilot` (keeps SDK state out of the same directory as
|
||||
OpenClaw's `models.json` / `auth-profiles.json`), or
|
||||
`~/.openclaw/agents/<agentId>/copilot` when no agent directory is supplied.
|
||||
Override with `copilotHome: <path>` on the attempt input for a custom
|
||||
location (for example, a shared mount for migration).
|
||||
|
||||
Live harness tests use `OPENCLAW_COPILOT_AGENT_LIVE_TOKEN` for a direct
|
||||
token. The shared live-test setup scrubs `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`,
|
||||
and `GITHUB_TOKEN` after staging real auth profiles into the isolated test
|
||||
home, so a `gh auth token` value passed through the dedicated variable avoids
|
||||
false skips without leaking into unrelated suites.
|
||||
|
||||
## Configuration surface
|
||||
|
||||
The harness reads config from per-attempt input (`runCopilotAttempt({...})`)
|
||||
plus a small set of env defaults inside `extensions/copilot/src/`:
|
||||
|
||||
| Field | Purpose |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `copilotHome` | Per-agent CLI state directory (defaults above). |
|
||||
| `model` | String or `{ provider, id, api?, baseUrl?, headers?, authHeader? }`. Omit to use the agent's normal model selection; the harness verifies the resolved provider is supported. |
|
||||
| `reasoningEffort` | `"low" \| "medium" \| "high" \| "xhigh"`. Maps from OpenClaw's `ThinkLevel` / `ReasoningLevel` resolution in `auto-reply/thinking.ts`. |
|
||||
| `infiniteSessionConfig` | Optional override for the SDK `infiniteSessions` block driven by `harness.compact`. Safe to leave as-is. |
|
||||
| `hooksConfig` | Optional native Copilot SDK `SessionHooks` config for tool/MCP, user-prompt, session, and error callbacks. Separate from OpenClaw's portable lifecycle hooks. |
|
||||
| `permissionPolicy` | Optional override for the SDK's `onPermissionRequest` handler for built-in SDK tool kinds (`shell`, `write`, `read`, `url`, `mcp`, `memory`, `hook`). Defaults to `rejectAllPolicy` as a safety net; see [Permissions and ask_user](#permissions-and-ask_user) for why it never actually fires. |
|
||||
| `enableSessionTelemetry` | Optional SDK session telemetry flag. |
|
||||
|
||||
OpenClaw plugin hooks need no Copilot-specific attempt configuration. The
|
||||
harness runs `before_prompt_build` (and the legacy `before_agent_start`
|
||||
compatibility hook), `llm_input`, `llm_output`, and `agent_end` through the
|
||||
standard harness helpers. Successful SDK compactions also run
|
||||
`before_compaction` and `after_compaction`. Bridged OpenClaw tools run
|
||||
`before_tool_call` and report `after_tool_call`; `hooksConfig` remains for
|
||||
native SDK-only callbacks with no portable equivalent.
|
||||
|
||||
Nothing else in OpenClaw needs to know about these fields. Other plugins,
|
||||
channels, and core code see only the standard `AgentHarnessAttemptParams` /
|
||||
`AgentHarnessAttemptResult` shape.
|
||||
|
||||
## Compaction
|
||||
|
||||
When `harness.compact` runs, the Copilot SDK harness:
|
||||
|
||||
1. Resumes the tracked SDK session without continuing pending work.
|
||||
2. Calls the SDK's session-scoped history compaction RPC.
|
||||
3. Returns the SDK compaction outcome without writing compatibility marker
|
||||
files under the workspace.
|
||||
|
||||
The OpenClaw-side transcript mirror (below) keeps receiving post-compaction
|
||||
messages, so user-facing chat history stays consistent.
|
||||
|
||||
## Transcript mirroring
|
||||
|
||||
`runCopilotAttempt` dual-writes each turn's mirrorable messages into the
|
||||
OpenClaw audit transcript via
|
||||
`extensions/copilot/src/dual-write-transcripts.ts`. The mirror is scoped per
|
||||
session (`copilot:${sessionId}`) and keyed per message
|
||||
(`${role}:${sha256_16(role,content)}`), so re-emitted prior-turn entries
|
||||
collide with existing on-disk keys instead of duplicating.
|
||||
|
||||
Two layers of failure containment wrap the mirror so a transcript write
|
||||
failure never fails the attempt: an internal best-effort wrapper, plus a
|
||||
defense-in-depth `.catch(...)` at the attempt level. Failures are logged, not
|
||||
surfaced.
|
||||
|
||||
## Side questions (`/btw`)
|
||||
|
||||
`/btw` is **not** native on this harness. `createCopilotAgentHarness()`
|
||||
deliberately leaves `harness.runSideQuestion` undefined
|
||||
(asserted in `extensions/copilot/harness.test.ts`, `describe("runSideQuestion")`),
|
||||
so OpenClaw's `/btw` dispatcher (`src/agents/btw.ts`) falls through to the
|
||||
same path it uses for every non-Codex runtime: the configured model provider
|
||||
is called directly with a short side-question prompt and streamed back via
|
||||
`streamSimple` (no CLI session, no extra pool slot).
|
||||
|
||||
This keeps Copilot CLI sessions reserved for the agent's main turn loop, and
|
||||
keeps `/btw` behavior identical to other non-Codex runtimes.
|
||||
|
||||
## Doctor
|
||||
|
||||
`extensions/copilot/doctor-contract-api.ts` is auto-loaded by
|
||||
`src/plugins/doctor-contract-registry.ts`. It contributes:
|
||||
|
||||
- An empty `legacyConfigRules` (no retired fields yet).
|
||||
- A no-op `normalizeCompatibilityConfig` (kept so future field retirements
|
||||
have a stable in-tree home).
|
||||
- One `sessionRouteStateOwners` entry: provider `github-copilot`, runtime
|
||||
`copilot`, CLI session key `copilot`, auth profile prefix `github-copilot:`.
|
||||
|
||||
## Limitations
|
||||
|
||||
- The harness claims `github-copilot` plus unowned custom BYOK provider ids.
|
||||
Manifest-owned native provider ids stay on their owning runtime even when
|
||||
`agentRuntime.id` is forced to `copilot`.
|
||||
- No TUI surface; PI's TUI remains the fallback for runtimes without a peer
|
||||
surface.
|
||||
- PI session state does not migrate when an agent switches to `copilot`.
|
||||
Selection is per attempt; existing PI sessions remain valid.
|
||||
- `ask_user` uses the same OpenClaw prompt-and-reply path as the Codex
|
||||
harness: when the Copilot SDK asks for user input, OpenClaw posts a
|
||||
blocking prompt to the active channel/TUI, and the next queued user
|
||||
message resolves the SDK request.
|
||||
|
||||
## Permissions and ask_user
|
||||
|
||||
Permission enforcement for bridged OpenClaw tools happens **inside the tool
|
||||
wrapper**, not via the SDK's `onPermissionRequest` callback. The same
|
||||
`wrapToolWithBeforeToolCallHook` that PI uses
|
||||
(`src/agents/agent-tools.before-tool-call.ts`) is applied by
|
||||
`createOpenClawCodingTools` to every coding tool: loop detection, trusted
|
||||
plugin policies, before-tool-call hooks, and two-phase plugin approvals via
|
||||
the gateway (`plugin.approval.request`) all run through the exact same code
|
||||
path as native PI attempts.
|
||||
|
||||
The SDK Tool returned by `convertOpenClawToolToSdkTool` is marked with:
|
||||
|
||||
- `overridesBuiltInTool: true` — replaces the Copilot CLI's built-in tool of
|
||||
the same name (edit, read, write, bash, ...) so every tool call routes back
|
||||
to OpenClaw.
|
||||
- `skipPermission: true` — tells the SDK not to fire
|
||||
`onPermissionRequest({kind: "custom-tool"})` before invoking the tool. The
|
||||
wrapped `execute()` already performs the richer OpenClaw policy check; an
|
||||
SDK-level prompt would either short-circuit OpenClaw's enforcement
|
||||
(allow-all) or block every tool call (reject-all) — neither matches PI
|
||||
parity.
|
||||
|
||||
The in-tree Codex harness uses the same split: bridged OpenClaw tools are
|
||||
wrapped (`extensions/codex/src/app-server/dynamic-tools.ts`) and the
|
||||
codex-app-server's own native approval kinds
|
||||
(`item/commandExecution/requestApproval`, `item/fileChange/requestApproval`,
|
||||
`item/permissions/requestApproval`) route through `plugin.approval.request`
|
||||
(`extensions/codex/src/app-server/approval-bridge.ts`). The Copilot SDK
|
||||
equivalent — fail-closed `rejectAllPolicy` for any non-`custom-tool` kind
|
||||
that ever reaches `onPermissionRequest` — is the same safety net, and it
|
||||
never fires in practice because `overridesBuiltInTool: true` displaces every
|
||||
built-in.
|
||||
|
||||
For the wrapped-tool layer to make policy decisions equivalent to PI, the
|
||||
harness forwards the full PI attempt-tool context to
|
||||
`createOpenClawCodingTools`: identity (`senderIsOwner`, `memberRoleIds`,
|
||||
`ownerOnlyToolAllowlist`, ...), channel/routing (`groupId`,
|
||||
`currentChannelId`, `replyToMode`, message-tool toggles), auth
|
||||
(`authProfileStore`), run identity (`sessionKey` / `runSessionKey` derived
|
||||
from `sandboxSessionKey`, `runId`), model context (`modelApi`,
|
||||
`modelContextWindowTokens`, `modelCompat`, `modelHasVision`), and run hooks
|
||||
(`onToolOutcome`, `onYield`). Without those fields, owner-only allowlists
|
||||
silently deny by default, plugin-trust policies cannot resolve to the right
|
||||
scope, and `session_status: "current"` resolves to a stale sandbox key. The
|
||||
bridge builder is `extensions/copilot/src/tool-bridge.ts`, mirroring the PI
|
||||
authoritative call at `src/agents/embedded-agent-runner/run/attempt.ts:1262`.
|
||||
`runAttempt` resolves sandbox context through the shared
|
||||
`resolveSandboxContext` seam, passes the SDK an effective working directory,
|
||||
and forwards `sandbox` plus the subagent-spawn workspace into the tool
|
||||
bridge. The bridge also forwards the bounded tool-construction controls it
|
||||
can enforce at the SDK boundary: `includeCoreTools`, the runtime tool
|
||||
allowlist, and `toolConstructionPlan`.
|
||||
|
||||
The bridge also uses the shared harness tool-surface helper from
|
||||
`openclaw/plugin-sdk/agent-harness-tool-runtime` for PI parity. When
|
||||
tool-search is enabled, the SDK sees compact control tools plus a hidden
|
||||
catalog executor instead of every OpenClaw tool schema. When code mode is
|
||||
enabled, the helper builds the same code-mode control surface and catalog
|
||||
lifecycle used by other agent harnesses. Local-model lean defaults,
|
||||
runtime-compatible schema filtering, directory hydration, and catalog
|
||||
cleanup all stay in the shared helper so Copilot and Codex-adjacent
|
||||
harnesses do not drift.
|
||||
|
||||
### Session-level GitHub token
|
||||
|
||||
The Copilot SDK contract distinguishes the **client-level** GitHub token
|
||||
(`CopilotClientOptions.gitHubToken`, authenticates the CLI process itself)
|
||||
from the **session-level** token (`SessionConfig.gitHubToken`, determines
|
||||
content exclusion, model routing, and quota for that session; honored on
|
||||
both `createSession` and `resumeSession`). The harness resolves auth once via
|
||||
`resolveCopilotAuth` and sets both fields when the auth mode is `gitHubToken`
|
||||
(an explicit `auth.gitHubToken` or a contract-resolved `resolvedApiKey` from
|
||||
a configured `github-copilot` auth profile). When the resolved mode is
|
||||
`useLoggedInUser`, the session-level field is omitted so the SDK keeps
|
||||
deriving identity from the logged-in identity.
|
||||
|
||||
`ask_user` uses `SessionConfig.onUserInputRequest`. The bridge accepts choice
|
||||
indexes or labels for fixed-choice requests, accepts free-form answers when
|
||||
the SDK request allows them, and cancels a pending request when the OpenClaw
|
||||
attempt is aborted.
|
||||
|
||||
## Related
|
||||
|
||||
- [Agent runtimes](/concepts/agent-runtimes)
|
||||
- [Codex harness](/plugins/codex-harness)
|
||||
- [Agent harness plugins (SDK reference)](/plugins/sdk-agent-harness)
|
||||
222
docs/plugins/dependency-resolution.md
Normal file
222
docs/plugins/dependency-resolution.md
Normal file
@@ -0,0 +1,222 @@
|
||||
---
|
||||
summary: "How OpenClaw installs plugin packages and resolves plugin dependencies"
|
||||
read_when:
|
||||
- You are debugging plugin package installs
|
||||
- You are changing plugin startup, doctor, or package-manager install behavior
|
||||
- You are maintaining packaged OpenClaw installs or bundled plugin manifests
|
||||
title: "Plugin dependency resolution"
|
||||
sidebarTitle: "Dependencies"
|
||||
---
|
||||
|
||||
OpenClaw handles plugin dependencies at install/update time only. Runtime
|
||||
loading never runs a package manager, repairs a dependency tree, or mutates
|
||||
the OpenClaw package directory.
|
||||
|
||||
## Responsibility split
|
||||
|
||||
Plugin packages own their dependency graph:
|
||||
|
||||
- Runtime dependencies live in the plugin package's `dependencies` or
|
||||
`optionalDependencies`.
|
||||
- SDK/core imports are peer or supplied OpenClaw imports.
|
||||
- Local development plugins bring their own already-installed dependencies.
|
||||
- npm and git plugins install into OpenClaw-owned package roots.
|
||||
|
||||
OpenClaw owns only the plugin lifecycle:
|
||||
|
||||
- Discover the plugin source.
|
||||
- Install or update the package when explicitly requested.
|
||||
- Record install metadata.
|
||||
- Load the plugin entrypoint.
|
||||
- Fail with an actionable error when dependencies are missing.
|
||||
|
||||
## Install roots
|
||||
|
||||
OpenClaw uses stable per-source roots:
|
||||
|
||||
- npm packages install into per-plugin projects under
|
||||
`~/.openclaw/npm/projects/<encoded-package>`.
|
||||
- git packages clone under `~/.openclaw/git`.
|
||||
- Local/path/archive installs are copied or referenced without dependency
|
||||
repair.
|
||||
|
||||
npm installs run in that per-plugin project root with:
|
||||
|
||||
```bash
|
||||
cd ~/.openclaw/npm/projects/<encoded-package>
|
||||
npm install --omit=dev --omit=peer --legacy-peer-deps --ignore-scripts --no-audit --no-fund
|
||||
```
|
||||
|
||||
`openclaw plugins install npm-pack:<path.tgz>` uses the same per-plugin npm
|
||||
project root for a local npm-pack tarball: OpenClaw reads the tarball's npm
|
||||
metadata, adds it to the managed project as a copied `file:` dependency, runs
|
||||
the normal npm install above, then verifies the installed lockfile metadata
|
||||
before trusting the plugin. This path exists for package-acceptance and
|
||||
release-candidate proof, where a local pack artifact should behave like the
|
||||
registry artifact it simulates.
|
||||
|
||||
Use `npm-pack:` when testing official or external plugin packages before
|
||||
publish. A raw archive or path install is useful for local debugging, but it
|
||||
does not prove the same dependency path as an installed npm or ClawHub
|
||||
package. `npm-pack:` proves the managed package install shape; it is not, by
|
||||
itself, proof that the plugin is catalog-linked official content.
|
||||
|
||||
When behavior depends on bundled-plugin or trusted official plugin status,
|
||||
pair the local package proof with a catalog-backed official install or a
|
||||
published package path that records official trust. Privileged helper access
|
||||
and trusted-official scope handling should be validated on that trusted
|
||||
install path, not inferred from a local tarball install.
|
||||
|
||||
If a plugin fails at runtime with a missing import, fix the package manifest
|
||||
instead of repairing the managed project by hand. Runtime imports belong in
|
||||
the plugin package `dependencies` or `optionalDependencies`; `devDependencies`
|
||||
are not installed for managed runtime projects. A local `npm install` inside
|
||||
`~/.openclaw/npm/projects/<encoded-package>` can unblock a temporary
|
||||
diagnostic, but it is not package-acceptance proof because the next install or
|
||||
update recreates the project from package metadata.
|
||||
|
||||
npm may hoist transitive dependencies to the per-plugin project's
|
||||
`node_modules` beside the plugin package. OpenClaw scans the managed project
|
||||
root before trusting the install, and removes that project on uninstall, so
|
||||
hoisted runtime dependencies stay inside that plugin's cleanup boundary.
|
||||
|
||||
Published npm plugin packages can ship `npm-shrinkwrap.json`; npm uses that
|
||||
publishable lockfile during install, and OpenClaw's managed npm project root
|
||||
supports it through the normal install path. OpenClaw-owned publishable
|
||||
plugin packages must include a package-local shrinkwrap generated from that
|
||||
package's published dependency graph:
|
||||
|
||||
```bash
|
||||
pnpm deps:shrinkwrap:generate
|
||||
pnpm deps:shrinkwrap:check
|
||||
```
|
||||
|
||||
The generator strips plugin `devDependencies`, applies the workspace override
|
||||
policy, and writes `extensions/<id>/npm-shrinkwrap.json` for each plugin with
|
||||
`openclaw.release.publishToNpm: true`. Third-party plugin packages may also
|
||||
ship a shrinkwrap; OpenClaw does not require one for community packages, but
|
||||
npm respects it when present.
|
||||
|
||||
Before treating a local package as release-candidate proof, inspect the
|
||||
tarball that will be installed:
|
||||
|
||||
```bash
|
||||
npm pack --pack-destination /tmp
|
||||
tar -xOf /tmp/<plugin-package>.tgz package/package.json
|
||||
tar -tf /tmp/<plugin-package>.tgz | grep '^package/dist/'
|
||||
```
|
||||
|
||||
For dependency changes, also verify a production install can resolve the
|
||||
runtime packages without dev dependencies:
|
||||
|
||||
```bash
|
||||
tmpdir=$(mktemp -d)
|
||||
(
|
||||
cd "$tmpdir"
|
||||
npm init -y >/dev/null
|
||||
npm install --package-lock-only --omit=dev --omit=peer --legacy-peer-deps --ignore-scripts /tmp/<plugin-package>.tgz
|
||||
)
|
||||
rm -rf "$tmpdir"
|
||||
```
|
||||
|
||||
OpenClaw-owned npm plugin packages can also publish with explicit
|
||||
`bundledDependencies`. The npm publish path overlays the runtime dependency
|
||||
name list, strips dev-only workspace metadata from the published manifest,
|
||||
runs a script-free npm install for the package-local runtime dependencies,
|
||||
then packs or publishes the plugin tarball with those dependency files
|
||||
included. Native-heavy packages (Codex, ACPX, Copilot, llama.cpp,
|
||||
memory-lancedb, Tlon) opt out with
|
||||
`openclaw.release.bundleRuntimeDependencies: false`; they still ship a
|
||||
shrinkwrap, but npm resolves runtime dependencies during install instead of
|
||||
embedding every platform binary in the plugin tarball. The root `openclaw`
|
||||
package does not bundle its full dependency tree.
|
||||
|
||||
Plugins that import `openclaw/plugin-sdk/*` declare `openclaw` as a peer
|
||||
dependency. OpenClaw does not let npm install a separate registry copy of the
|
||||
host package into a managed project, because a stale host package can affect
|
||||
npm's peer resolution inside that plugin. Managed npm installs skip npm peer
|
||||
resolution/materialization, and OpenClaw reasserts plugin-local
|
||||
`node_modules/openclaw` links for installed packages that declare the host
|
||||
peer, after install or update.
|
||||
|
||||
git installs clone or refresh the repository, then run:
|
||||
|
||||
```bash
|
||||
npm install --omit=dev --ignore-scripts --no-audit --no-fund
|
||||
```
|
||||
|
||||
The installed plugin then loads from that package directory, so
|
||||
package-local and parent `node_modules` resolution work the same way they do
|
||||
for a normal Node package.
|
||||
|
||||
## Local plugins
|
||||
|
||||
Local plugins are developer-controlled directories. OpenClaw never runs
|
||||
`npm install`, `pnpm install`, or dependency repair for them; if a local
|
||||
plugin has dependencies, install them in that plugin before loading it.
|
||||
|
||||
Third-party TypeScript local plugins load through Jiti as an emergency path.
|
||||
Packaged JavaScript plugins and bundled internal plugins load through native
|
||||
import/require instead.
|
||||
|
||||
## Startup and reload
|
||||
|
||||
Gateway startup and config reload never install plugin dependencies. They
|
||||
read the plugin install records, compute the entrypoint, and load it.
|
||||
|
||||
A missing dependency at runtime fails plugin load with an error that points
|
||||
the operator to an explicit fix:
|
||||
|
||||
```bash
|
||||
openclaw plugins update <id>
|
||||
openclaw plugins install <source>
|
||||
openclaw doctor --fix
|
||||
```
|
||||
|
||||
`doctor --fix` cleans legacy OpenClaw-generated dependency state and can
|
||||
recover downloadable plugins that are missing from local install records when
|
||||
config still references them. Doctor does not repair dependencies for an
|
||||
already-installed local plugin.
|
||||
|
||||
## Bundled plugins
|
||||
|
||||
Lightweight and core-critical bundled plugins ship as part of OpenClaw. They
|
||||
should either carry no heavy runtime dependency tree, or move out to a
|
||||
downloadable package on ClawHub/npm.
|
||||
|
||||
For the current generated list of plugins that ship in the core package,
|
||||
install externally, or stay source-only, see
|
||||
[Plugin inventory](/plugins/plugin-inventory).
|
||||
|
||||
Bundled plugin manifests must not request dependency staging. Large or
|
||||
optional plugin functionality should be packaged as a normal plugin and
|
||||
installed through the same npm/git/ClawHub path as third-party plugins.
|
||||
|
||||
In source checkouts, OpenClaw treats the repository as a pnpm monorepo.
|
||||
After `pnpm install`, bundled plugins load from `extensions/<id>` so
|
||||
package-local workspace dependencies are available and edits are picked up
|
||||
directly. Source checkout development is pnpm-only; plain `npm install` at
|
||||
the repository root does not prepare bundled plugin dependencies.
|
||||
|
||||
| Install shape | Bundled plugin location | Dependency owner |
|
||||
| -------------------------------- | ------------------------------------- | -------------------------------------------------------------------- |
|
||||
| `npm install -g openclaw` | Built runtime tree inside the package | OpenClaw package and explicit plugin install/update/doctor flows |
|
||||
| Git checkout plus `pnpm install` | `extensions/<id>` workspace packages | The pnpm workspace, including each plugin package's own dependencies |
|
||||
| `openclaw plugins install ...` | Managed npm project/git/ClawHub root | The plugin install/update flow |
|
||||
|
||||
## Legacy cleanup
|
||||
|
||||
Older OpenClaw versions generated bundled-plugin dependency roots at startup
|
||||
or during doctor repair. Current doctor cleanup removes those stale
|
||||
directories and symlinks with `--fix`, including old `plugin-runtime-deps`
|
||||
roots, global Node-prefix package symlinks pointing at pruned
|
||||
`plugin-runtime-deps` targets, `.openclaw-runtime-deps*` manifests, generated
|
||||
plugin `node_modules`, install stage directories, and package-local pnpm
|
||||
stores. Packaged postinstall also removes those global symlinks before
|
||||
pruning the legacy target roots, so upgrades do not leave dangling ESM
|
||||
package imports.
|
||||
|
||||
Older npm installs also used a shared `~/.openclaw/npm/node_modules` root.
|
||||
Current install, update, uninstall, and doctor flows still recognize that
|
||||
legacy flat root for recovery and cleanup only. New npm installs create
|
||||
per-plugin project roots instead.
|
||||
1203
docs/plugins/google-meet.md
Normal file
1203
docs/plugins/google-meet.md
Normal file
File diff suppressed because it is too large
Load Diff
605
docs/plugins/hooks.md
Normal file
605
docs/plugins/hooks.md
Normal file
@@ -0,0 +1,605 @@
|
||||
---
|
||||
summary: "Plugin hooks: intercept agent, tool, message, session, and Gateway lifecycle events"
|
||||
title: "Plugin hooks"
|
||||
read_when:
|
||||
- You are building a plugin that needs before_tool_call, before_agent_reply, message hooks, or lifecycle hooks
|
||||
- You need to block, rewrite, or require approval for tool calls from a plugin
|
||||
- You are deciding between internal hooks and plugin hooks
|
||||
---
|
||||
|
||||
Plugin hooks are in-process extension points for OpenClaw plugins: inspect or
|
||||
change agent runs, tool calls, message flow, session lifecycle, subagent
|
||||
routing, installs, or Gateway startup.
|
||||
|
||||
Use [internal hooks](/automation/hooks) instead for a small operator-installed
|
||||
`HOOK.md` script reacting to command and Gateway events such as `/new`,
|
||||
`/reset`, `/stop`, `agent:bootstrap`, or `gateway:startup`.
|
||||
|
||||
## Quick start
|
||||
|
||||
Register typed hooks with `api.on(...)` from the plugin entry:
|
||||
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "tool-preflight",
|
||||
name: "Tool Preflight",
|
||||
register(api) {
|
||||
api.on(
|
||||
"before_tool_call",
|
||||
async (event) => {
|
||||
if (event.toolName !== "web_search") {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
requireApproval: {
|
||||
title: "Run web search",
|
||||
description: `Allow search query: ${String(event.params.query ?? "")}`,
|
||||
severity: "info",
|
||||
timeoutMs: 60_000,
|
||||
timeoutBehavior: "deny",
|
||||
},
|
||||
};
|
||||
},
|
||||
{ priority: 50 },
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Handlers run sequentially in descending `priority`; same-priority handlers
|
||||
keep registration order.
|
||||
|
||||
`api.on(name, handler, opts?)` accepts:
|
||||
|
||||
| Option | Effect |
|
||||
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `priority` | Ordering; higher runs first. |
|
||||
| `timeoutMs` | Per-hook budget. When set, the runner aborts that handler after the budget and moves on instead of blocking on the configured model timeout. Omit to use the runner's default per-hook timeout. |
|
||||
|
||||
Operators can set hook budgets without patching plugin code:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"entries": {
|
||||
"my-plugin": {
|
||||
"hooks": {
|
||||
"timeoutMs": 30000,
|
||||
"timeouts": {
|
||||
"before_prompt_build": 90000,
|
||||
"agent_end": 60000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`hooks.timeouts.<hookName>` overrides `hooks.timeoutMs`, which overrides the
|
||||
plugin-authored `api.on(..., { timeoutMs })` value. Each value must be a
|
||||
positive integer up to 600000 ms. Prefer per-hook overrides for known-slow
|
||||
hooks so one plugin does not get a longer budget everywhere.
|
||||
|
||||
Each hook receives `event.context.pluginConfig`, the resolved config for the
|
||||
plugin that registered that handler. OpenClaw injects it per handler without
|
||||
mutating the shared event object other plugins see.
|
||||
|
||||
## Hook catalog
|
||||
|
||||
Hooks are grouped by the surface they extend. **Bold** names accept a decision
|
||||
result (block, cancel, override, or require approval); the rest are
|
||||
observation-only.
|
||||
|
||||
**Agent turn**
|
||||
|
||||
| Hook | Purpose |
|
||||
| ------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `before_model_resolve` | Override provider or model before session messages load |
|
||||
| `agent_turn_prepare` | Consume queued plugin turn injections and add same-turn context before prompt hooks |
|
||||
| `before_prompt_build` | Add dynamic context or system-prompt text before the model call |
|
||||
| `before_agent_start` | Compatibility-only combined phase; prefer the two hooks above |
|
||||
| **`before_agent_run`** | Inspect the final prompt and session messages before model submission; can block the run |
|
||||
| **`before_agent_reply`** | Short-circuit the model turn with a synthetic reply or silence |
|
||||
| **`before_agent_finalize`** | Inspect the natural final answer and request one more model pass |
|
||||
| `agent_end` | Observe final messages, success state, and run duration |
|
||||
| `heartbeat_prompt_contribution` | Add heartbeat-only context for background monitor and lifecycle plugins |
|
||||
|
||||
**Conversation observation**
|
||||
|
||||
| Hook | Purpose |
|
||||
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `model_call_started` / `model_call_ended` | Sanitized provider/model call metadata: timing, outcome, bounded request-id hashes. No prompt or response content. |
|
||||
| `llm_input` | Provider input: system prompt, prompt, history |
|
||||
| `llm_output` | Provider output, usage, and the resolved `contextTokenBudget` when available |
|
||||
|
||||
**Tools**
|
||||
|
||||
| Hook | Purpose |
|
||||
| -------------------------- | --------------------------------------------------------- |
|
||||
| **`before_tool_call`** | Rewrite tool params, block execution, or require approval |
|
||||
| `after_tool_call` | Observe tool results, errors, and duration |
|
||||
| `resolve_exec_env` | Contribute plugin-owned environment variables to `exec` |
|
||||
| **`tool_result_persist`** | Rewrite the assistant message produced from a tool result |
|
||||
| **`before_message_write`** | Inspect or block an in-progress message write (rare) |
|
||||
|
||||
**Messages and delivery**
|
||||
|
||||
| Hook | Purpose |
|
||||
| --------------------------- | ----------------------------------------------------------------- |
|
||||
| **`inbound_claim`** | Claim an inbound message before agent routing (synthetic replies) |
|
||||
| `message_received` | Observe inbound content, sender, thread, and metadata |
|
||||
| **`message_sending`** | Rewrite outbound content or cancel delivery |
|
||||
| **`reply_payload_sending`** | Mutate or cancel normalized reply payloads before delivery |
|
||||
| `message_sent` | Observe outbound delivery success or failure |
|
||||
| **`before_dispatch`** | Inspect or rewrite an outbound dispatch before channel handoff |
|
||||
| **`reply_dispatch`** | Participate in the final reply-dispatch pipeline |
|
||||
|
||||
**Sessions and compaction**
|
||||
|
||||
| Hook | Purpose |
|
||||
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `session_start` / `session_end` | Track session lifecycle boundaries. `reason` is one of `new`, `reset`, `idle`, `daily`, `compaction`, `deleted`, `shutdown`, `restart`, or `unknown`. `shutdown`/`restart` fire from the Gateway shutdown finalizer when the process stops or restarts with active sessions, so plugins (memory, transcript stores) can finalize ghost rows instead of leaving them open across restarts. The finalizer is bounded so a slow plugin cannot block SIGTERM/SIGINT. |
|
||||
| `before_compaction` / `after_compaction` | Observe or annotate compaction cycles |
|
||||
| `before_reset` | Observe session-reset events (`/reset`, programmatic resets) |
|
||||
|
||||
**Subagents**
|
||||
|
||||
- `subagent_spawned` / `subagent_ended` - observe subagent launch and completion.
|
||||
- `subagent_delivery_target` - compatibility hook for completion delivery when no core session binding can project a route.
|
||||
- `subagent_spawning` - deprecated compatibility hook. Core now prepares `thread: true` subagent bindings through channel session-binding adapters before `subagent_spawned` fires.
|
||||
- `subagent_spawned` includes `resolvedModel` and `resolvedProvider` when OpenClaw has resolved the child session's native model before launch.
|
||||
- `subagent_ended` carries `targetSessionKey` (identity - matches `subagent_spawned.childSessionKey`), `targetKind` (`"subagent"` or `"acp"`), `reason`, optional `outcome` (`"ok"`, `"error"`, `"timeout"`, `"killed"`, `"reset"`, or `"deleted"`), optional `error`, `runId`, `endedAt`, `accountId`, and `sendFarewell`. It does **not** include `agentId` or `childSessionKey`; use `targetSessionKey` to correlate with the matching `subagent_spawned` event.
|
||||
|
||||
**Lifecycle**
|
||||
|
||||
| Hook | Purpose |
|
||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `gateway_start` / `gateway_stop` | Start or stop plugin-owned services with the Gateway |
|
||||
| `deactivate` | Deprecated compatibility alias for `gateway_stop`; use `gateway_stop` in new plugins |
|
||||
| `cron_changed` | Observe Gateway-owned cron lifecycle changes (added, updated, removed, started, finished, scheduled) |
|
||||
| **`before_install`** | Inspect staged skill or plugin install material from a loaded plugin runtime |
|
||||
|
||||
## Debug runtime hooks
|
||||
|
||||
Use `before_model_resolve` to switch provider or model for an agent turn - it
|
||||
runs before model resolution. `llm_output` only runs after a model attempt
|
||||
produces assistant output.
|
||||
|
||||
For proof of the effective session model, inspect runtime registrations, then
|
||||
use `openclaw sessions` or the Gateway session/status surfaces. To debug
|
||||
provider payloads, start the Gateway with `--raw-stream` and
|
||||
`--raw-stream-path <path>` to write raw model stream events to a jsonl file.
|
||||
|
||||
## Tool call policy
|
||||
|
||||
`before_tool_call` receives:
|
||||
|
||||
- `event.toolName`
|
||||
- `event.params`
|
||||
- optional `event.toolKind` and `event.toolInputKind`, host-authoritative
|
||||
discriminators for tools that intentionally share names; for example, outer
|
||||
code-mode `exec` calls use `toolKind: "code_mode_exec"` and include
|
||||
`toolInputKind: "javascript" | "typescript"` when the input language is
|
||||
known
|
||||
- optional `event.derivedPaths`, best-effort host-derived target path hints
|
||||
for well-known tool envelopes such as `apply_patch`; these paths may be
|
||||
incomplete or over-approximate what the tool will actually touch (for
|
||||
example, with malformed or partial inputs)
|
||||
- optional `event.runId`
|
||||
- optional `event.toolCallId`
|
||||
- context fields such as `ctx.agentId`, `ctx.sessionKey`, `ctx.sessionId`,
|
||||
`ctx.runId`, `ctx.toolKind`, `ctx.toolInputKind`, and diagnostic `ctx.trace`
|
||||
|
||||
It can return:
|
||||
|
||||
```typescript
|
||||
type BeforeToolCallResult = {
|
||||
params?: Record<string, unknown>;
|
||||
block?: boolean;
|
||||
blockReason?: string;
|
||||
requireApproval?: {
|
||||
title: string;
|
||||
description: string;
|
||||
severity?: "info" | "warning" | "critical";
|
||||
timeoutMs?: number;
|
||||
timeoutBehavior?: "allow" | "deny";
|
||||
allowedDecisions?: Array<"allow-once" | "allow-always" | "deny">;
|
||||
pluginId?: string;
|
||||
onResolution?: (
|
||||
decision: "allow-once" | "allow-always" | "deny" | "timeout" | "cancelled",
|
||||
) => Promise<void> | void;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Guard behavior for typed lifecycle hooks:
|
||||
|
||||
- `block: true` is terminal and skips lower-priority handlers.
|
||||
- `block: false` is treated as no decision.
|
||||
- `params` rewrites the tool parameters for execution.
|
||||
- `requireApproval` pauses the agent run and asks the user through plugin
|
||||
approvals. `/approve` can approve both exec and plugin approvals. In Codex
|
||||
app-server report-mode native `PreToolUse` relays, this defers to the
|
||||
matching app-server approval request; see
|
||||
[Codex harness runtime](/plugins/codex-harness-runtime#hook-boundaries).
|
||||
- A lower-priority `block: true` can still block after a higher-priority hook
|
||||
requested approval.
|
||||
- `onResolution` receives the resolved decision: `allow-once`, `allow-always`,
|
||||
`deny`, `timeout`, or `cancelled`.
|
||||
|
||||
See [Plugin permission requests](/plugins/plugin-permission-requests) for
|
||||
approval routing, decision behavior, and when to use `requireApproval` instead
|
||||
of optional tools or exec approvals.
|
||||
|
||||
Plugins that need host-level policy can register trusted tool policies with
|
||||
`api.registerTrustedToolPolicy(...)`. These run before ordinary
|
||||
`before_tool_call` hooks and before normal hook decisions. Bundled trusted
|
||||
policies run first; installed-plugin trusted policies run next in plugin-load
|
||||
order; ordinary `before_tool_call` hooks run after them. Bundled plugins keep
|
||||
the existing trusted-policy path. Installed plugins must be explicitly enabled
|
||||
and declare every policy id in `contracts.trustedToolPolicies`; undeclared ids
|
||||
are rejected before registration. Policy ids are scoped to the registering
|
||||
plugin, so different plugins may reuse the same local id. Use this tier only
|
||||
for host-trusted gates such as workspace policy, budget enforcement, or
|
||||
reserved workflow safety.
|
||||
|
||||
### Exec environment hook
|
||||
|
||||
`resolve_exec_env` lets plugins contribute environment variables to `exec`
|
||||
tool invocations before the command runs. It receives:
|
||||
|
||||
- `event.sessionKey`
|
||||
- `event.toolName`, currently always `"exec"`
|
||||
- `event.host`, one of `"gateway"`, `"sandbox"`, or `"node"`
|
||||
- context fields such as `ctx.agentId`, `ctx.sessionKey`,
|
||||
`ctx.messageProvider`, and `ctx.channelId`
|
||||
|
||||
Return a `Record<string, string>` to merge into the exec environment. Handlers
|
||||
run in priority order; later results override earlier results for the same
|
||||
key.
|
||||
|
||||
Hook output is filtered through the host exec environment key policy before
|
||||
merging. `PATH` is always dropped (command resolution and safe-bin checks
|
||||
depend on it). Invalid keys and dangerous host override keys such as `LD_*`,
|
||||
`DYLD_*`, `NODE_OPTIONS`, proxy variables (`HTTP_PROXY`, `HTTPS_PROXY`,
|
||||
`ALL_PROXY`, `NO_PROXY`), and TLS override variables (`NODE_TLS_REJECT_UNAUTHORIZED`,
|
||||
`SSL_CERT_FILE`, and similar) are dropped. The filtered plugin env is included
|
||||
in Gateway approval/audit metadata and forwarded to node-host execution
|
||||
requests.
|
||||
|
||||
### Tool result persistence
|
||||
|
||||
Tool results can include structured `details` for UI rendering, diagnostics,
|
||||
media routing, or plugin-owned metadata. Treat `details` as runtime metadata,
|
||||
not prompt content:
|
||||
|
||||
- OpenClaw strips `toolResult.details` before provider replay and compaction
|
||||
input so metadata does not become model context.
|
||||
- Persisted session entries keep only bounded `details`. Oversized details are
|
||||
replaced with a compact summary and `persistedDetailsTruncated: true`.
|
||||
- `tool_result_persist` and `before_message_write` run before the final
|
||||
persistence cap. Keep returned `details` small and avoid placing
|
||||
prompt-relevant text only in `details`; put model-visible tool output in
|
||||
`content`.
|
||||
|
||||
## Prompt and model hooks
|
||||
|
||||
Use the phase-specific hooks for new plugins:
|
||||
|
||||
- `before_model_resolve`: receives only the current prompt and attachment
|
||||
metadata. Return `providerOverride` or `modelOverride`.
|
||||
- `agent_turn_prepare`: receives the current prompt, prepared session
|
||||
messages, and any exactly-once queued injections drained for this session.
|
||||
Return `prependContext` or `appendContext`.
|
||||
- `before_prompt_build`: receives the current prompt and session messages.
|
||||
Return `prependContext`, `appendContext`, `systemPrompt`,
|
||||
`prependSystemContext`, or `appendSystemContext`.
|
||||
- `heartbeat_prompt_contribution`: runs only for heartbeat turns and returns
|
||||
`prependContext` or `appendContext`. Intended for background monitors that
|
||||
need to summarize current state without changing user-initiated turns.
|
||||
|
||||
`before_agent_start` remains for compatibility. Prefer the explicit hooks
|
||||
above so the plugin does not depend on a legacy combined phase.
|
||||
|
||||
`before_agent_run` runs after prompt construction and before any model input,
|
||||
including prompt-local image loading and `llm_input` observation. It receives
|
||||
the current user input as `prompt`, plus loaded session history in `messages`
|
||||
and the active system prompt. Return `{ outcome: "block", reason, message? }`
|
||||
to stop the run before the model reads the prompt. `reason` is internal;
|
||||
`message` is the user-facing replacement. Only `pass` and `block` outcomes are
|
||||
supported; unsupported decision shapes fail closed.
|
||||
|
||||
When a run is blocked, OpenClaw stores only the replacement text in
|
||||
`message.content` plus non-sensitive block metadata such as the blocking
|
||||
plugin id and timestamp. The original user text is not retained in transcript
|
||||
or future context. Internal block reasons are treated as sensitive and
|
||||
excluded from transcript, history, broadcast, log, and diagnostics payloads.
|
||||
Observability should use sanitized fields such as blocker id, outcome,
|
||||
timestamp, or a safe category.
|
||||
|
||||
`before_agent_start` and `agent_end` include `event.runId` when OpenClaw can
|
||||
identify the active run; the same value is also on `ctx.runId`. Cron-driven
|
||||
runs also expose `ctx.jobId` (the originating cron job id) on the agent-turn
|
||||
context so hooks can scope metrics, side effects, or state to a specific
|
||||
scheduled job. `ctx.jobId` is not part of the `before_tool_call` tool context.
|
||||
|
||||
For channel-originated runs, `ctx.channel` and `ctx.messageProvider` identify
|
||||
the provider surface such as `discord` or `telegram`, while `ctx.channelId` is
|
||||
the conversation target identifier when OpenClaw can derive one from the
|
||||
session key or delivery metadata.
|
||||
|
||||
When sender identity is available, agent hook contexts also include:
|
||||
|
||||
- `ctx.senderId` - channel-scoped sender ID (e.g. Feishu `open_id`, Discord
|
||||
user ID). Populated when the run originates from a user message with known
|
||||
sender metadata.
|
||||
- `ctx.chatId` - transport-native conversation identifier (e.g. Feishu
|
||||
`chat_id`, Telegram `chat_id`). Populated when the originating channel
|
||||
provides a native conversation ID.
|
||||
- `ctx.channelContext.sender.id` - the same sender ID as `ctx.senderId`, under
|
||||
a channel-owned object plugins can extend with channel-specific fields.
|
||||
- `ctx.channelContext.chat.id` - the same conversation ID as `ctx.chatId`,
|
||||
under a channel-owned object plugins can extend with channel-specific
|
||||
fields.
|
||||
|
||||
Core only defines the nested `id` fields. Channel plugins that pass richer
|
||||
sender or chat metadata through the inbound helper can augment
|
||||
`PluginHookChannelSenderContext` or `PluginHookChannelChatContext` from
|
||||
`openclaw/plugin-sdk/channel-inbound`:
|
||||
|
||||
```ts
|
||||
declare module "openclaw/plugin-sdk/channel-inbound" {
|
||||
interface PluginHookChannelSenderContext {
|
||||
unionId?: string;
|
||||
userId?: string;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Channel plugins pass those fields through the inbound SDK helper:
|
||||
|
||||
```ts
|
||||
buildChannelInboundEventContext({
|
||||
// ...
|
||||
channelContext: {
|
||||
sender: { id: senderOpenId, unionId, userId },
|
||||
chat: { id: chatId },
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
These fields are optional and absent for system-originated runs (heartbeat,
|
||||
cron, exec-event).
|
||||
|
||||
`ctx.senderExternalId` remains as a deprecated source-compatibility field for
|
||||
older plugins. Core does not populate it; new channel-specific sender
|
||||
identities should live under `ctx.channelContext.sender` through module
|
||||
augmentation.
|
||||
|
||||
`agent_end` is an observation hook. Gateway and persistent harness paths run
|
||||
it fire-and-forget after the turn, while short-lived one-shot CLI paths wait
|
||||
for the hook promise before process cleanup so trusted plugins can flush
|
||||
terminal observability or capture state. The hook runner applies a 30 second
|
||||
timeout so a wedged plugin or embedding endpoint cannot leave the hook promise
|
||||
pending forever. A timeout is logged and OpenClaw continues; it does not
|
||||
cancel plugin-owned network work unless the plugin also uses its own abort
|
||||
signal.
|
||||
|
||||
Use `model_call_started` and `model_call_ended` for provider-call telemetry
|
||||
that should not receive raw prompts, history, responses, headers, request
|
||||
bodies, or provider request IDs. These hooks include stable metadata such as
|
||||
`runId`, `callId`, `provider`, `model`, optional `api`/`transport`, terminal
|
||||
`durationMs`/`outcome`, and `upstreamRequestIdHash` when OpenClaw can derive a
|
||||
bounded provider request-id hash. When the runtime has resolved
|
||||
context-window metadata, the hook event and context also include
|
||||
`contextTokenBudget`, the effective token budget after model/config/agent
|
||||
caps, plus `contextWindowSource` and `contextWindowReferenceTokens` when a
|
||||
lower cap was applied.
|
||||
|
||||
`before_agent_finalize` runs only when a harness is about to accept a natural
|
||||
final assistant answer. It is not the `/stop` cancellation path and does not
|
||||
run when the user aborts a turn. Return `{ action: "revise", reason }` to ask
|
||||
the harness for one more model pass before finalization, `{ action:
|
||||
"finalize", reason? }` to force finalization, or omit a result to continue.
|
||||
Codex native `Stop` hooks are relayed into this hook as OpenClaw
|
||||
`before_agent_finalize` decisions.
|
||||
|
||||
When returning `action: "revise"`, plugins can include `retry` metadata to
|
||||
make the extra model pass bounded and replay-safe:
|
||||
|
||||
```typescript
|
||||
type BeforeAgentFinalizeRetry = {
|
||||
instruction: string;
|
||||
idempotencyKey?: string;
|
||||
maxAttempts?: number;
|
||||
};
|
||||
```
|
||||
|
||||
`instruction` is appended to the revision reason sent to the harness.
|
||||
`idempotencyKey` lets the host count retries for the same plugin request
|
||||
across equivalent finalize decisions, and `maxAttempts` caps how many extra
|
||||
passes the host will allow before continuing with the natural final answer.
|
||||
|
||||
Non-bundled plugins that need raw conversation hooks (`before_model_resolve`,
|
||||
`before_agent_reply`, `llm_input`, `llm_output`, `before_agent_finalize`,
|
||||
`agent_end`, or `before_agent_run`) must set:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": {
|
||||
"entries": {
|
||||
"my-plugin": {
|
||||
"hooks": {
|
||||
"allowConversationAccess": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Prompt-mutating hooks and durable next-turn injections can be disabled per
|
||||
plugin with `plugins.entries.<id>.hooks.allowPromptInjection=false`.
|
||||
|
||||
### Session extensions and next-turn injections
|
||||
|
||||
Workflow plugins can persist small JSON-compatible session state with
|
||||
`api.session.state.registerSessionExtension(...)` and update it through the
|
||||
Gateway `sessions.pluginPatch` method. Session rows project registered
|
||||
extension state through `pluginExtensions`, letting Control UI and other
|
||||
clients render plugin-owned status without learning plugin internals.
|
||||
`api.registerSessionExtension(...)` still works but is deprecated in favor of
|
||||
the `api.session.state` namespace.
|
||||
|
||||
Use `api.session.workflow.enqueueNextTurnInjection(...)` when a plugin needs
|
||||
durable context to reach the next model turn exactly once (the top-level
|
||||
`api.enqueueNextTurnInjection(...)` is a deprecated alias with the same
|
||||
behavior). OpenClaw drains queued injections before prompt hooks, drops
|
||||
expired injections, and deduplicates by `idempotencyKey` per plugin. This is
|
||||
the right seam for approval resumes, policy summaries, background monitor
|
||||
deltas, and command continuations that should be visible to the model on the
|
||||
next turn but should not become permanent system prompt text.
|
||||
|
||||
Cleanup semantics are part of the contract. Session extension cleanup and
|
||||
runtime lifecycle cleanup callbacks receive `reset`, `delete`, `disable`, or
|
||||
`restart`. The host removes the owning plugin's persistent session extension
|
||||
state and pending next-turn injections for reset/delete/disable; restart
|
||||
keeps durable session state while cleanup callbacks let plugins release
|
||||
scheduler jobs, run context, and other out-of-band resources for the old
|
||||
runtime generation.
|
||||
|
||||
## Message hooks
|
||||
|
||||
Use message hooks for channel-level routing and delivery policy:
|
||||
|
||||
- `message_received`: observe inbound content, sender, `threadId`,
|
||||
`messageId`, `senderId`, optional run/session correlation, and metadata.
|
||||
- `message_sending`: rewrite `content` or return `{ cancel: true }`.
|
||||
- `reply_payload_sending`: rewrite normalized `ReplyPayload` objects
|
||||
(including `presentation`, `delivery`, media refs, and text) or return
|
||||
`{ cancel: true }`.
|
||||
- `message_sent`: observe final success or failure.
|
||||
|
||||
For audio-only TTS replies, `content` may contain the hidden spoken
|
||||
transcript even when the channel payload has no visible text/caption.
|
||||
Rewriting that `content` updates the hook-visible transcript only; it is not
|
||||
rendered as a media caption.
|
||||
|
||||
`reply_payload_sending` events may include `usageState`, a best-effort live
|
||||
per-turn model/usage/context snapshot. Durable delivery, recovered replay, and
|
||||
replies without exact run correlation omit it.
|
||||
|
||||
Message hook contexts expose stable correlation fields when available:
|
||||
`ctx.sessionKey`, `ctx.runId`, `ctx.messageId`, `ctx.senderId`, `ctx.trace`,
|
||||
`ctx.traceId`, `ctx.spanId`, `ctx.parentSpanId`, and `ctx.callDepth`. Inbound
|
||||
and `before_dispatch` contexts also expose reply metadata when the channel
|
||||
has visibility-filtered quoted message data: `replyToId`, `replyToIdFull`,
|
||||
`replyToBody`, `replyToSender`, and `replyToIsQuote`. Prefer these
|
||||
first-class fields before reading legacy metadata.
|
||||
|
||||
Prefer typed `threadId` and `replyToId` fields before using channel-specific
|
||||
metadata.
|
||||
|
||||
Decision rules:
|
||||
|
||||
- `message_sending` with `cancel: true` is terminal.
|
||||
- `message_sending` with `cancel: false` is treated as no decision.
|
||||
- Rewritten `content` continues to lower-priority hooks unless a later hook
|
||||
cancels delivery.
|
||||
- `reply_payload_sending` runs after payload normalization and before channel
|
||||
delivery, including replies routed back to the originating channel.
|
||||
Handlers run sequentially and each handler sees the latest payload produced
|
||||
by higher-priority handlers.
|
||||
- `reply_payload_sending` payloads do not expose runtime trust markers such as
|
||||
`trustedLocalMedia`; plugins can edit payload shape but cannot grant local
|
||||
media trust.
|
||||
- `message_sending` can return `cancelReason` and bounded `metadata` with a
|
||||
cancellation. New message lifecycle APIs expose this as a suppressed
|
||||
delivery outcome with reason `cancelled_by_message_sending_hook`; legacy
|
||||
direct delivery keeps returning an empty result array for compatibility.
|
||||
- `message_sent` is observation-only. Handler failures are logged and do not
|
||||
change the delivery result.
|
||||
|
||||
## Install hooks
|
||||
|
||||
Use `security.installPolicy` for operator-owned allow/block decisions. That
|
||||
policy runs from OpenClaw config, covers CLI install and update paths, and
|
||||
fails closed when enabled but unavailable.
|
||||
|
||||
`before_install` is a plugin-runtime lifecycle hook. It runs after
|
||||
`security.installPolicy` only in the OpenClaw process where plugin hooks have
|
||||
already been loaded, such as Gateway-backed install flows. It is useful for
|
||||
plugin-owned observations, warnings, and compatibility checks, but it is not
|
||||
the primary enterprise or host security boundary for installs. The
|
||||
`builtinScan` field remains in the event payload for compatibility, but
|
||||
OpenClaw no longer runs built-in install-time dangerous-code blocking, so it
|
||||
is an empty `ok` result. Return additional findings or
|
||||
`{ block: true, blockReason }` to stop the install in that process.
|
||||
|
||||
`block: true` is terminal. `block: false` is treated as no decision. Handler
|
||||
failures block the install fail-closed.
|
||||
|
||||
## Gateway lifecycle
|
||||
|
||||
Use `gateway_start` for plugin services that need Gateway-owned state. The
|
||||
context exposes `ctx.config`, `ctx.workspaceDir`, and `ctx.getCron?.()` for
|
||||
cron inspection and updates. Use `gateway_stop` to clean up long-running
|
||||
resources.
|
||||
|
||||
Do not rely on the internal `gateway:startup` hook for plugin-owned runtime
|
||||
services.
|
||||
|
||||
`cron_changed` fires for Gateway-owned cron lifecycle events with a typed
|
||||
event payload covering `added`, `updated`, `removed`, `started`, `finished`,
|
||||
and `scheduled` reasons. The event carries a `PluginHookGatewayCronJob`
|
||||
snapshot (including `state.nextRunAtMs`, `state.lastRunStatus`, and
|
||||
`state.lastError` when present) plus a `PluginHookGatewayCronDeliveryStatus`
|
||||
of `not-requested` | `delivered` | `not-delivered` | `unknown`. Removed events
|
||||
still carry the deleted job snapshot so external schedulers can reconcile
|
||||
state. Use `ctx.getCron?.()` and `ctx.config` from the runtime context when
|
||||
syncing external wake schedulers, and keep OpenClaw as the source of truth
|
||||
for due checks and execution.
|
||||
|
||||
## Upcoming deprecations
|
||||
|
||||
A few hook-adjacent surfaces are deprecated but still supported. Migrate
|
||||
before the next major release:
|
||||
|
||||
- **Plaintext channel envelopes** in `inbound_claim` and `message_received`
|
||||
handlers. Read `BodyForAgent` and the structured user-context blocks
|
||||
instead of parsing flat envelope text. See
|
||||
[Plaintext channel envelopes → BodyForAgent](/plugins/sdk-migration#active-deprecations).
|
||||
- **`before_agent_start`** remains for compatibility. New plugins should use
|
||||
`before_model_resolve` and `before_prompt_build` instead of the combined
|
||||
phase.
|
||||
- **`subagent_spawning`** remains for compatibility with older plugins, but
|
||||
new plugins should not return thread routing from it. Core prepares
|
||||
`thread: true` subagent bindings through channel session-binding adapters
|
||||
before `subagent_spawned` fires.
|
||||
- **`deactivate`** remains as a deprecated cleanup compatibility alias until
|
||||
after 2026-08-16. New plugins should use `gateway_stop`.
|
||||
- **`onResolution` in `before_tool_call`** now uses the typed
|
||||
`PluginApprovalResolution` union (`allow-once` / `allow-always` / `deny` /
|
||||
`timeout` / `cancelled`) instead of a free-form `string`.
|
||||
- **`api.registerSessionExtension` / `api.enqueueNextTurnInjection`** remain
|
||||
as top-level compatibility aliases. New plugins should use
|
||||
`api.session.state.registerSessionExtension(...)` and
|
||||
`api.session.workflow.enqueueNextTurnInjection(...)`.
|
||||
|
||||
For the full list - memory capability registration, provider thinking
|
||||
profile, external auth providers, provider discovery types, task runtime
|
||||
accessors, and the `command-auth` → `command-status` rename - see
|
||||
[Plugin SDK migration → Active deprecations](/plugins/sdk-migration#active-deprecations).
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin SDK migration](/plugins/sdk-migration) - active deprecations and removal timeline
|
||||
- [Building plugins](/plugins/building-plugins)
|
||||
- [Plugin SDK overview](/plugins/sdk-overview)
|
||||
- [Plugin entry points](/plugins/sdk-entrypoints)
|
||||
- [Internal hooks](/automation/hooks)
|
||||
- [Plugin architecture internals](/plugins/architecture-internals)
|
||||
80
docs/plugins/install-overrides.md
Normal file
80
docs/plugins/install-overrides.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
summary: "Test packaged plugin overrides with setup-time install flows"
|
||||
read_when:
|
||||
- Testing onboarding or setup flows against a locally packed plugin
|
||||
- Verifying a plugin package before publishing it
|
||||
- Replacing an automatic plugin install with a test artifact
|
||||
title: "Plugin install overrides"
|
||||
sidebarTitle: "Install overrides"
|
||||
---
|
||||
|
||||
Plugin install overrides let maintainers point setup-time plugin installs at
|
||||
a specific npm package or local npm-pack tarball instead of the catalog,
|
||||
bundled, or default npm source. They exist for E2E and package validation
|
||||
only; normal users install plugins with
|
||||
[`openclaw plugins install`](/cli/plugins).
|
||||
|
||||
<Warning>
|
||||
Overrides execute plugin code from the source you provide. Use them only in an
|
||||
isolated state directory or disposable test machine.
|
||||
</Warning>
|
||||
|
||||
## Environment
|
||||
|
||||
Overrides are disabled unless both variables are set:
|
||||
|
||||
```bash
|
||||
export OPENCLAW_ALLOW_PLUGIN_INSTALL_OVERRIDES=1
|
||||
export OPENCLAW_PLUGIN_INSTALL_OVERRIDES='{
|
||||
"codex": "npm-pack:/tmp/openclaw-codex-2026.5.8.tgz",
|
||||
"openclaw-web-search": "npm:@openclaw/web-search@2026.5.8"
|
||||
}'
|
||||
```
|
||||
|
||||
The override map is JSON keyed by plugin id. Values support:
|
||||
|
||||
| Prefix | Source |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `npm:<registry-spec>` | Registry packages, exact versions, or tags |
|
||||
| `npm-pack:<path.tgz>` | Local tarballs produced by `npm pack`; relative paths resolve from the current working directory |
|
||||
|
||||
## Behavior
|
||||
|
||||
When a setup-time flow installs a plugin whose id appears in the map, OpenClaw
|
||||
uses the override source instead of the catalog, bundled, or default npm
|
||||
source. This applies to onboarding and any other flow using the shared
|
||||
setup-time plugin installer.
|
||||
|
||||
- Overrides still enforce the expected plugin id: a tarball mapped to `codex`
|
||||
must install a plugin whose manifest id is `codex`.
|
||||
- Overrides do not inherit official trusted-source status. Even when the
|
||||
catalog entry normally represents an OpenClaw-owned package, an override is
|
||||
treated as operator-supplied test input.
|
||||
- Workspace `.env` files cannot enable install overrides; both env vars are on
|
||||
the blocked workspace dotenv list. Set them in the trusted shell, CI job, or
|
||||
remote test command that launches OpenClaw.
|
||||
|
||||
## Package E2E
|
||||
|
||||
Use an isolated state directory so package installs and install records do not
|
||||
touch your normal OpenClaw state:
|
||||
|
||||
```bash
|
||||
npm pack extensions/codex --pack-destination /tmp
|
||||
|
||||
OPENCLAW_STATE_DIR="$(mktemp -d)" \
|
||||
OPENCLAW_ALLOW_PLUGIN_INSTALL_OVERRIDES=1 \
|
||||
OPENCLAW_PLUGIN_INSTALL_OVERRIDES='{"codex":"npm-pack:/tmp/openclaw-codex-2026.5.8.tgz"}' \
|
||||
pnpm openclaw onboard --mode local
|
||||
```
|
||||
|
||||
Verify the installed package under the state directory:
|
||||
|
||||
```bash
|
||||
find "$OPENCLAW_STATE_DIR/npm/projects" -path '*/node_modules/@openclaw/codex/package.json' -print
|
||||
grep -R '"@openclaw/codex"' "$OPENCLAW_STATE_DIR/npm/projects"/*/package-lock.json
|
||||
```
|
||||
|
||||
For live provider E2E, source the real API key from a trusted shell or CI
|
||||
secret before launching the test command. Do not print keys; report only the
|
||||
source and whether the key was present.
|
||||
71
docs/plugins/llama-cpp.md
Normal file
71
docs/plugins/llama-cpp.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
summary: "Install the official llama.cpp provider for local GGUF memory embeddings"
|
||||
read_when:
|
||||
- You want memory search embeddings from a local GGUF model
|
||||
- You are configuring memorySearch.provider = "local"
|
||||
- You need the OpenClaw plugin that owns the node-llama-cpp runtime
|
||||
title: "llama.cpp Provider"
|
||||
sidebarTitle: "llama.cpp Provider"
|
||||
---
|
||||
|
||||
`llama-cpp` is the official external provider plugin for local GGUF
|
||||
embeddings. It registers embedding provider id `local` and owns the
|
||||
`node-llama-cpp` runtime dependency used by `memorySearch.provider: "local"`.
|
||||
|
||||
Install it before using local memory embeddings:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/llama-cpp-provider
|
||||
```
|
||||
|
||||
The main `openclaw` npm package does not include `node-llama-cpp`. Keeping the
|
||||
native dependency in this plugin prevents normal OpenClaw npm updates from
|
||||
deleting a manually installed runtime inside the OpenClaw package directory.
|
||||
|
||||
## Configuration
|
||||
|
||||
Set `memorySearch.provider` to `local`:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
memorySearch: {
|
||||
provider: "local",
|
||||
local: {
|
||||
modelPath: "hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`local.modelPath` defaults to the `hf:` URI shown above (`embeddinggemma-300m-qat-Q8_0.gguf`).
|
||||
Point it at a different `hf:` URI or a local `.gguf` file to use another
|
||||
model. `local.modelCacheDir` overrides where downloaded models are cached
|
||||
(default: `~/.node-llama-cpp/models`), and `local.contextSize` accepts an
|
||||
integer or `"auto"`.
|
||||
|
||||
## Native Runtime
|
||||
|
||||
Use Node 24 for the smoothest native install path. Source checkouts using
|
||||
pnpm may need to approve and rebuild the native dependency:
|
||||
|
||||
```bash
|
||||
pnpm approve-builds
|
||||
pnpm rebuild node-llama-cpp
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If `node-llama-cpp` is missing or fails to load, OpenClaw reports the failure
|
||||
with:
|
||||
|
||||
1. Install the plugin: `openclaw plugins install @openclaw/llama-cpp-provider`.
|
||||
2. Use Node 24 for native installs/updates.
|
||||
3. From a pnpm source checkout: `pnpm approve-builds`, then `pnpm rebuild node-llama-cpp`.
|
||||
|
||||
For lower-friction local embeddings without the native build step, set
|
||||
`memorySearch.provider` to a remote embedding provider such as `lmstudio`,
|
||||
`ollama`, `openai`, or `voyage` instead.
|
||||
231
docs/plugins/manage-plugins.md
Normal file
231
docs/plugins/manage-plugins.md
Normal file
@@ -0,0 +1,231 @@
|
||||
---
|
||||
summary: "Quick examples for listing, installing, updating, inspecting, and uninstalling OpenClaw plugins"
|
||||
read_when:
|
||||
- You want quick plugin list, install, update, inspect, or uninstall examples
|
||||
- You want to choose a plugin install source
|
||||
- You want the right reference for publishing plugin packages
|
||||
title: "Manage plugins"
|
||||
sidebarTitle: "Manage plugins"
|
||||
doc-schema-version: 1
|
||||
---
|
||||
|
||||
Common plugin management commands. For the full command contract, flags,
|
||||
source-selection rules, and edge cases, see [`openclaw plugins`](/cli/plugins).
|
||||
|
||||
Typical workflow: find a package, install it from ClawHub, npm, git, or a
|
||||
local path, let the managed Gateway auto-restart (or restart it manually),
|
||||
then verify the plugin's runtime registrations.
|
||||
|
||||
## List and search plugins
|
||||
|
||||
```bash
|
||||
openclaw plugins list
|
||||
openclaw plugins list --enabled
|
||||
openclaw plugins list --verbose
|
||||
openclaw plugins list --json
|
||||
openclaw plugins search "calendar"
|
||||
```
|
||||
|
||||
`--json` for scripts:
|
||||
|
||||
```bash
|
||||
openclaw plugins list --json \
|
||||
| jq '.plugins[] | {id, enabled, format, source, dependencyStatus}'
|
||||
```
|
||||
|
||||
`plugins list` is a cold inventory check: what OpenClaw can discover from
|
||||
config, manifests, and the persisted plugin registry. It does not prove an
|
||||
already-running Gateway imported the plugin runtime. JSON output includes
|
||||
registry diagnostics and each plugin's `dependencyStatus` (whether declared
|
||||
`dependencies`/`optionalDependencies` resolve on disk).
|
||||
|
||||
`plugins search` queries ClawHub for installable plugin packages and prints
|
||||
an install hint (`openclaw plugins install clawhub:<package>`) per result.
|
||||
|
||||
## Enable and disable plugins
|
||||
|
||||
```bash
|
||||
openclaw plugins enable <plugin-id>
|
||||
openclaw plugins disable <plugin-id>
|
||||
```
|
||||
|
||||
Toggles a plugin's config entry without touching installed files. Some
|
||||
bundled plugins (bundled model/speech providers, the bundled browser plugin)
|
||||
are enabled by default; others require `enable` after install.
|
||||
|
||||
## Install plugins
|
||||
|
||||
```bash
|
||||
# Search ClawHub for plugin packages.
|
||||
openclaw plugins search "calendar"
|
||||
|
||||
# Install from ClawHub.
|
||||
openclaw plugins install clawhub:<package>
|
||||
openclaw plugins install clawhub:<package>@1.2.3
|
||||
openclaw plugins install clawhub:<package>@beta
|
||||
|
||||
# Install from npm.
|
||||
openclaw plugins install npm:<package>
|
||||
openclaw plugins install npm:@scope/openclaw-plugin@1.2.3
|
||||
openclaw plugins install npm:@openclaw/codex
|
||||
|
||||
# Install from a local npm-pack artifact.
|
||||
openclaw plugins install npm-pack:<path.tgz>
|
||||
|
||||
# Install from git or a local development checkout.
|
||||
openclaw plugins install git:github.com/acme/openclaw-plugin@v1.0.0
|
||||
openclaw plugins install ./my-plugin
|
||||
openclaw plugins install --link ./my-plugin
|
||||
```
|
||||
|
||||
Bare package specs install from npm during the launch cutover, unless the
|
||||
name matches a bundled or official plugin id, in which case OpenClaw uses
|
||||
that local/official copy instead. Use `clawhub:`, `npm:`, `git:`, or
|
||||
`npm-pack:` for deterministic source selection.
|
||||
|
||||
Use `--force` only to overwrite an existing install target from a different
|
||||
source. For routine upgrades of a tracked npm, ClawHub, or hook-pack install,
|
||||
use `openclaw plugins update` instead; `--force` is not supported with
|
||||
`--link`.
|
||||
|
||||
## Restart and inspect
|
||||
|
||||
A running managed Gateway with config reload enabled restarts automatically
|
||||
after installing, updating, or uninstalling plugin code. If the Gateway is
|
||||
unmanaged or reload is disabled, restart it yourself before checking live
|
||||
runtime surfaces:
|
||||
|
||||
```bash
|
||||
openclaw gateway restart
|
||||
openclaw plugins inspect <plugin-id> --runtime --json
|
||||
```
|
||||
|
||||
`inspect --runtime` loads the plugin module and proves it registered runtime
|
||||
surfaces (tools, hooks, services, Gateway methods, HTTP routes, plugin-owned
|
||||
CLI commands). Plain `inspect` and `list` are cold manifest/config/registry
|
||||
checks only.
|
||||
|
||||
## Update plugins
|
||||
|
||||
```bash
|
||||
openclaw plugins update <plugin-id>
|
||||
openclaw plugins update <npm-package-or-spec>
|
||||
openclaw plugins update --all
|
||||
openclaw plugins update <plugin-id> --dry-run
|
||||
```
|
||||
|
||||
Passing a plugin id reuses its tracked install spec: stored dist-tags
|
||||
(`@beta`) and exact pinned versions carry over to later `update <plugin-id>`
|
||||
runs.
|
||||
|
||||
`openclaw plugins update --all` is the bulk maintenance path. It still
|
||||
respects ordinary tracked install specs, but trusted official OpenClaw
|
||||
plugin records sync to the current official catalog target instead of
|
||||
staying pinned to a stale exact official package; when `update.channel` is
|
||||
`beta`, that sync prefers the beta release line. Use a targeted
|
||||
`update <plugin-id>` to keep an exact or tagged official spec untouched.
|
||||
|
||||
For npm installs, pass an explicit package spec to switch the tracked
|
||||
record:
|
||||
|
||||
```bash
|
||||
openclaw plugins update @scope/openclaw-plugin@beta
|
||||
openclaw plugins update @scope/openclaw-plugin
|
||||
```
|
||||
|
||||
The second command moves a plugin back to the registry's default release
|
||||
line when it was previously pinned to an exact version or tag.
|
||||
|
||||
See [`openclaw plugins`](/cli/plugins#update) for the exact fallback and
|
||||
pinning rules.
|
||||
|
||||
## Uninstall plugins
|
||||
|
||||
```bash
|
||||
openclaw plugins uninstall <plugin-id> --dry-run
|
||||
openclaw plugins uninstall <plugin-id>
|
||||
openclaw plugins uninstall <plugin-id> --keep-files
|
||||
```
|
||||
|
||||
Uninstall removes the plugin's config entry, persisted plugin index record,
|
||||
allow/deny list entries, and linked `plugins.load.paths` entries when
|
||||
applicable. The managed install directory is removed unless you pass
|
||||
`--keep-files`. A running managed Gateway restarts automatically when the
|
||||
uninstall changes plugin source.
|
||||
|
||||
In Nix mode (`OPENCLAW_NIX_MODE=1`), plugin install, update, uninstall,
|
||||
enable, and disable are all disabled; manage those choices in the Nix source
|
||||
for the install instead.
|
||||
|
||||
## Choose a source
|
||||
|
||||
| Source | Use when | Example |
|
||||
| ----------- | --------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
||||
| ClawHub | You want OpenClaw-native discovery, scan summaries, versions, and hints | `openclaw plugins install clawhub:<package>` |
|
||||
| git | You want a branch, tag, or commit from a repository | `openclaw plugins install git:github.com/<owner>/<repo>@<ref>` |
|
||||
| local path | You are developing or testing a plugin on the same machine | `openclaw plugins install --link ./my-plugin` |
|
||||
| marketplace | You are installing a Claude-compatible marketplace plugin | `openclaw plugins install <plugin> --marketplace <source>` |
|
||||
| npm pack | You are proving a local package artifact through npm install semantics | `openclaw plugins install npm-pack:<path.tgz>` |
|
||||
| npmjs.com | You already ship JavaScript packages or need npm dist-tags/private registry | `openclaw plugins install npm:@acme/openclaw-plugin` |
|
||||
|
||||
Managed local path installs must be plugin directories or archives. Put
|
||||
standalone plugin files in `plugins.load.paths` instead of installing them
|
||||
with `plugins install`.
|
||||
|
||||
## Publish plugins
|
||||
|
||||
ClawHub is the primary public discovery surface for OpenClaw plugins. Publish
|
||||
there when you want users to find plugin metadata, version history, registry
|
||||
scan results, and install hints before they install.
|
||||
|
||||
```bash
|
||||
npm i -g clawhub
|
||||
clawhub login
|
||||
clawhub package publish your-org/your-plugin --dry-run
|
||||
clawhub package publish your-org/your-plugin
|
||||
clawhub package publish your-org/your-plugin@v1.0.0
|
||||
```
|
||||
|
||||
Native npm plugins must ship a plugin manifest (`openclaw.plugin.json`) plus
|
||||
`package.json` metadata before publishing:
|
||||
|
||||
```json package.json
|
||||
{
|
||||
"name": "@acme/openclaw-plugin",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": ["./dist/index.js"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
npm publish --access public
|
||||
openclaw plugins install npm:@acme/openclaw-plugin
|
||||
openclaw plugins install npm:@acme/openclaw-plugin@beta
|
||||
openclaw plugins install npm:@acme/openclaw-plugin@1.0.0
|
||||
```
|
||||
|
||||
Use these pages for the full publishing contract instead of treating this
|
||||
page as the publishing reference:
|
||||
|
||||
- [ClawHub publishing](/clawhub/publishing) explains owners, scopes,
|
||||
releases, review, package validation, and package transfer.
|
||||
- [Building plugins](/plugins/building-plugins) shows the full plugin
|
||||
package shape (including `openclaw.plugin.json`) and first publish
|
||||
workflow.
|
||||
- [Plugin manifest](/plugins/manifest) defines native plugin manifest
|
||||
fields.
|
||||
|
||||
If the same package is available on both ClawHub and npm, use the explicit
|
||||
`clawhub:` or `npm:` prefix to force one source.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugins](/tools/plugin) - install, configure, restart, and troubleshoot
|
||||
- [`openclaw plugins`](/cli/plugins) - full CLI reference
|
||||
- [Community plugins](/plugins/community) - public discovery and ClawHub publishing
|
||||
- [ClawHub](/clawhub/cli) - registry CLI operations
|
||||
- [Building plugins](/plugins/building-plugins) - create a plugin package
|
||||
- [Plugin manifest](/plugins/manifest) - manifest and package metadata
|
||||
1251
docs/plugins/manifest.md
Normal file
1251
docs/plugins/manifest.md
Normal file
File diff suppressed because it is too large
Load Diff
364
docs/plugins/memory-lancedb.md
Normal file
364
docs/plugins/memory-lancedb.md
Normal file
@@ -0,0 +1,364 @@
|
||||
---
|
||||
summary: "Configure the official external LanceDB memory plugin, including local Ollama-compatible embeddings"
|
||||
read_when:
|
||||
- You are configuring the memory-lancedb plugin
|
||||
- You want LanceDB-backed long-term memory with auto-recall or auto-capture
|
||||
- You are using local OpenAI-compatible embeddings such as Ollama
|
||||
title: "Memory LanceDB"
|
||||
sidebarTitle: "Memory LanceDB"
|
||||
---
|
||||
|
||||
`memory-lancedb` is an official external plugin that stores long-term memory in
|
||||
LanceDB with vector search. It can auto-recall relevant memories before a model
|
||||
turn and auto-capture important facts after a response.
|
||||
|
||||
Use it for a local vector database, an OpenAI-compatible embedding endpoint, or
|
||||
a memory store outside the default built-in memory backend.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/memory-lancedb
|
||||
```
|
||||
|
||||
The plugin is published to npm; it is not bundled into the OpenClaw runtime
|
||||
image. Installing it writes the plugin entry, enables it, and switches
|
||||
`plugins.slots.memory` to `memory-lancedb`. If another plugin currently owns
|
||||
the memory slot, that plugin is disabled with a warning.
|
||||
|
||||
<Note>
|
||||
Companion plugins such as `memory-wiki` can run alongside `memory-lancedb`,
|
||||
but only one plugin owns the active memory slot at a time.
|
||||
</Note>
|
||||
|
||||
## Quick start
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
slots: {
|
||||
memory: "memory-lancedb",
|
||||
},
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
embedding: {
|
||||
provider: "openai",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
autoRecall: true,
|
||||
autoCapture: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Restart the Gateway after changing plugin config, then verify it loaded:
|
||||
|
||||
```bash
|
||||
openclaw gateway restart
|
||||
openclaw plugins list
|
||||
```
|
||||
|
||||
## Embedding config
|
||||
|
||||
`embedding` is required and must include at least one field. `provider`
|
||||
defaults to `openai`; `model` defaults to `text-embedding-3-small`.
|
||||
|
||||
| Field | Type | Notes |
|
||||
| ---------------------- | ------------- | ------------------------------------------------------------------------ |
|
||||
| `embedding.provider` | string | Adapter id, e.g. `openai`, `github-copilot`, `ollama`. Default `openai`. |
|
||||
| `embedding.model` | string | Default `text-embedding-3-small`. |
|
||||
| `embedding.apiKey` | string | Optional; supports `${ENV_VAR}` expansion. |
|
||||
| `embedding.baseUrl` | string | Optional; supports `${ENV_VAR}` expansion. |
|
||||
| `embedding.dimensions` | integer (>=1) | Required for models not in the built-in table (see below). |
|
||||
|
||||
Two request paths exist:
|
||||
|
||||
- **Provider adapter path** (default): set `embedding.provider` and omit
|
||||
`embedding.apiKey`/`embedding.baseUrl`. The plugin resolves the provider's
|
||||
configured auth profile, environment variable, or
|
||||
`models.providers.<provider>.apiKey` through the same memory embedding
|
||||
adapters `memory-core` uses. This is the path for `github-copilot`, `ollama`,
|
||||
and any other bundled provider with embedding support.
|
||||
- **Direct OpenAI-compatible client path**: leave `embedding.provider` unset
|
||||
(or `"openai"`) and set `embedding.apiKey` plus `embedding.baseUrl`. Use this
|
||||
for a raw OpenAI-compatible embeddings endpoint that has no bundled provider
|
||||
adapter.
|
||||
|
||||
OpenAI Codex / ChatGPT OAuth is not an OpenAI Platform embeddings credential.
|
||||
For OpenAI embeddings use an OpenAI API key auth profile, `OPENAI_API_KEY`, or
|
||||
`models.providers.openai.apiKey`. OAuth-only users should pick another
|
||||
embedding-capable provider such as `github-copilot` or `ollama`.
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
embedding: {
|
||||
provider: "github-copilot",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Some OpenAI-compatible embedding endpoints reject the `encoding_format`
|
||||
parameter; others ignore it and always return `number[]`. `memory-lancedb`
|
||||
omits `encoding_format` on requests and accepts either float-array or
|
||||
base64-encoded float32 responses, so both response shapes work without config.
|
||||
|
||||
### Dimensions
|
||||
|
||||
OpenClaw has a built-in dimension for `text-embedding-3-small` (1536) and
|
||||
`text-embedding-3-large` (3072) only. Any other model needs an explicit
|
||||
`embedding.dimensions` so LanceDB can create the vector column, for example
|
||||
ZhiPu `embedding-3` at 2048 dimensions:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
embedding: {
|
||||
apiKey: "${ZHIPU_API_KEY}",
|
||||
baseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
||||
model: "embedding-3",
|
||||
dimensions: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Ollama embeddings
|
||||
|
||||
Use the bundled Ollama provider adapter path (`embedding.provider: "ollama"`).
|
||||
It calls Ollama's native `/api/embed` endpoint and follows the same auth/base
|
||||
URL rules as the [Ollama](/providers/ollama) provider.
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
slots: {
|
||||
memory: "memory-lancedb",
|
||||
},
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
embedding: {
|
||||
provider: "ollama",
|
||||
baseUrl: "http://127.0.0.1:11434",
|
||||
model: "mxbai-embed-large",
|
||||
dimensions: 1024,
|
||||
},
|
||||
recallMaxChars: 400,
|
||||
autoRecall: true,
|
||||
autoCapture: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`mxbai-embed-large` is not in the built-in dimension table, so `dimensions` is
|
||||
required. For small local embedding models, lower `recallMaxChars` if the
|
||||
local server returns context-length errors.
|
||||
|
||||
## Recall and capture limits
|
||||
|
||||
| Setting | Default | Range | Applies to |
|
||||
| ----------------- | ------- | ---------------------------- | ---------------------------------------------------------- |
|
||||
| `recallMaxChars` | `1000` | 100-10000 | Text sent to the embedding API for recall. |
|
||||
| `captureMaxChars` | `500` | 100-10000 | Message length eligible for auto-capture. |
|
||||
| `customTriggers` | `[]` | 0-50 items, each <=100 chars | Literal phrases that make auto-capture consider a message. |
|
||||
|
||||
`recallMaxChars` bounds the `before_prompt_build` auto-recall query, the
|
||||
`memory_recall` tool, the `memory_forget` query path, and `openclaw ltm
|
||||
search`. Auto-recall embeds the latest user message from the turn and falls
|
||||
back to the full prompt only when no user message is present, keeping channel
|
||||
metadata and large prompt blocks out of the embedding request.
|
||||
|
||||
`captureMaxChars` gates whether a user message from the turn's `agent_end`
|
||||
event is short enough to be considered for auto-capture; it does not affect
|
||||
recall queries.
|
||||
|
||||
`customTriggers` adds literal auto-capture phrases without regex. Built-in
|
||||
triggers cover common English, Czech, Chinese, Japanese, and Korean memory
|
||||
phrases (`remember`, `prefer`, `记住`, `覚えて`, `기억해`, and similar).
|
||||
|
||||
Auto-capture also rejects text that looks like envelope/transport metadata,
|
||||
prompt-injection payloads, or already-injected `<relevant-memories>` context,
|
||||
and caps at 3 captured memories per agent turn.
|
||||
|
||||
## Commands
|
||||
|
||||
`memory-lancedb` registers the `ltm` CLI namespace whenever it is installed
|
||||
(not only when it owns the active memory slot):
|
||||
|
||||
```bash
|
||||
openclaw ltm list [--limit <n>] [--order-by-created-at]
|
||||
openclaw ltm search <query> [--limit <n>]
|
||||
openclaw ltm stats
|
||||
```
|
||||
|
||||
`ltm query` runs a non-vector query directly against the LanceDB table:
|
||||
|
||||
```bash
|
||||
openclaw ltm query --cols id,text,createdAt --limit 20
|
||||
openclaw ltm query --filter "category = 'preference'" --order-by createdAt:desc
|
||||
```
|
||||
|
||||
| Flag | Default | Notes |
|
||||
| --------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--cols <columns>` | `id,text,importance,category,createdAt` | Comma-separated column allowlist. |
|
||||
| `--filter <condition>` | none | SQL-style WHERE clause. Max 200 chars; only alphanumerics, `_-`, whitespace, and `='"<>!.,()%*` are allowed. |
|
||||
| `--limit <n>` | `10` | Positive integer. |
|
||||
| `--order-by <column>:<asc\|desc>` | none | Sorted in memory after the filter runs; the sort column is auto-added to the projection and stripped from output if it was not requested. |
|
||||
|
||||
Agents get three tools from the active memory plugin:
|
||||
|
||||
- `memory_recall`: vector search over stored memories.
|
||||
- `memory_store`: save a fact, preference, decision, or entity (rejects text
|
||||
that looks like a prompt-injection payload; skips near-duplicate stores).
|
||||
- `memory_forget`: delete by `memoryId`, or by `query` (auto-deletes a single
|
||||
match above 90% score, otherwise lists candidate IDs to disambiguate).
|
||||
|
||||
## Storage
|
||||
|
||||
LanceDB data defaults to `~/.openclaw/memory/lancedb`. Override with `dbPath`:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
dbPath: "~/.openclaw/memory/lancedb",
|
||||
embedding: {
|
||||
apiKey: "${OPENAI_API_KEY}",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`storageOptions` accepts string key/value pairs for LanceDB storage backends
|
||||
(e.g. S3-compatible object storage) and supports `${ENV_VAR}` expansion:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
enabled: true,
|
||||
config: {
|
||||
dbPath: "s3://memory-bucket/openclaw",
|
||||
storageOptions: {
|
||||
access_key: "${AWS_ACCESS_KEY_ID}",
|
||||
secret_key: "${AWS_SECRET_ACCESS_KEY}",
|
||||
endpoint: "${AWS_ENDPOINT_URL}",
|
||||
},
|
||||
embedding: {
|
||||
apiKey: "${OPENAI_API_KEY}",
|
||||
model: "text-embedding-3-small",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Runtime dependencies and platform support
|
||||
|
||||
`memory-lancedb` depends on the native `@lancedb/lancedb` package, owned by the
|
||||
plugin package (not the OpenClaw core dist). Gateway startup does not repair
|
||||
plugin dependencies; if the native dependency is missing or fails to load,
|
||||
reinstall or update the plugin package and restart the Gateway.
|
||||
|
||||
`@lancedb/lancedb` does not publish a native build for `darwin-x64` (Intel
|
||||
Mac). On that platform the plugin logs that LanceDB is unavailable at load
|
||||
time; use the default memory backend, run the Gateway on a supported
|
||||
platform/architecture, or disable `memory-lancedb`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Input length exceeds the context length
|
||||
|
||||
The embedding model rejected the recall query:
|
||||
|
||||
```text
|
||||
memory-lancedb: recall failed: Error: 400 the input length exceeds the context length
|
||||
```
|
||||
|
||||
Lower `recallMaxChars`, then restart the Gateway:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-lancedb": {
|
||||
config: {
|
||||
recallMaxChars: 400,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
For Ollama, also verify the embedding server is reachable from the Gateway
|
||||
host using its native embed endpoint:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:11434/api/embed \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"mxbai-embed-large","input":"hello"}'
|
||||
```
|
||||
|
||||
### Unsupported embedding model
|
||||
|
||||
Without `embedding.dimensions`, only the built-in OpenAI embedding dimensions
|
||||
are known (`text-embedding-3-small`, `text-embedding-3-large`). For any other
|
||||
model, set `embedding.dimensions` to the vector size that model reports.
|
||||
|
||||
### Plugin loads but no memories appear
|
||||
|
||||
Confirm `plugins.slots.memory` points at `memory-lancedb`, then run:
|
||||
|
||||
```bash
|
||||
openclaw ltm stats
|
||||
openclaw ltm search "recent preference"
|
||||
```
|
||||
|
||||
If `autoCapture` is disabled, the plugin still recalls existing memories but
|
||||
does not store new ones automatically. Use the `memory_store` tool, or enable
|
||||
`autoCapture`.
|
||||
|
||||
## Related
|
||||
|
||||
- [Memory overview](/concepts/memory)
|
||||
- [Active memory](/concepts/active-memory)
|
||||
- [Memory search](/concepts/memory-search)
|
||||
- [Memory Wiki](/plugins/memory-wiki)
|
||||
- [Ollama](/providers/ollama)
|
||||
442
docs/plugins/memory-wiki.md
Normal file
442
docs/plugins/memory-wiki.md
Normal file
@@ -0,0 +1,442 @@
|
||||
---
|
||||
summary: "memory-wiki: compiled knowledge vault with provenance, claims, dashboards, and bridge mode"
|
||||
read_when:
|
||||
- You want persistent knowledge beyond plain MEMORY.md notes
|
||||
- You are configuring the bundled memory-wiki plugin
|
||||
- You want to understand wiki_search, wiki_get, or bridge mode
|
||||
title: "Memory wiki"
|
||||
---
|
||||
|
||||
`memory-wiki` is a bundled plugin that compiles durable knowledge into a
|
||||
navigable wiki: deterministic pages, structured claims with evidence,
|
||||
provenance, dashboards, and machine-readable digests.
|
||||
|
||||
It does not replace the active memory plugin. Recall, promotion, indexing, and
|
||||
dreaming stay owned by whichever memory backend is configured
|
||||
(`memory-core`, QMD, Honcho, etc.). `memory-wiki` sits beside it and compiles
|
||||
knowledge into a maintained wiki layer.
|
||||
|
||||
| Layer | Owns |
|
||||
| -------------------- | --------------------------------------------------------------------------------- |
|
||||
| Active memory plugin | Recall, semantic search, promotion, dreaming, memory runtime |
|
||||
| `memory-wiki` | Compiled wiki pages, provenance-rich syntheses, dashboards, wiki search/get/apply |
|
||||
|
||||
Practical rule:
|
||||
|
||||
- `memory_search` for one broad recall pass across whatever corpora are configured
|
||||
- `wiki_search` / `wiki_get` when you want wiki-specific ranking, provenance, or page-level belief structure
|
||||
- `memory_search corpus=all` to span both layers in one call, when the active memory plugin supports corpus selection
|
||||
|
||||
A common local-first setup: QMD as the active memory backend for recall, and
|
||||
`memory-wiki` in `bridge` mode for durable synthesized pages. See the
|
||||
QMD + bridge mode example under [Configuration](#configuration).
|
||||
|
||||
If bridge mode reports zero exported artifacts, the active memory plugin is
|
||||
not currently exposing public bridge inputs. Run `openclaw wiki doctor` first,
|
||||
then confirm the active memory plugin supports public artifacts.
|
||||
|
||||
## Vault modes
|
||||
|
||||
- `isolated` (default): own vault, own sources, no dependency on the active memory plugin. Use this for a self-contained curated knowledge store.
|
||||
- `bridge`: reads public memory artifacts and event logs from the active memory plugin through public plugin SDK seams. Use this to compile the memory plugin's exported artifacts without reaching into private plugin internals.
|
||||
- `unsafe-local`: explicit same-machine escape hatch for local private paths. Intentionally experimental and non-portable; use only when you understand the trust boundary and specifically need local filesystem access bridge mode cannot provide.
|
||||
|
||||
Bridge mode can index, per `bridge.*` config toggle:
|
||||
|
||||
- exported memory artifacts (`indexMemoryRoot`)
|
||||
- daily notes (`indexDailyNotes`)
|
||||
- dream reports (`indexDreamReports`)
|
||||
- memory event logs (`followMemoryEvents`)
|
||||
|
||||
When bridge mode is active and `bridge.readMemoryArtifacts` is enabled,
|
||||
`openclaw wiki status`, `openclaw wiki doctor`, and `openclaw wiki bridge
|
||||
import` route through the running Gateway so they see the same active memory
|
||||
plugin context as agent/runtime memory. If bridge is disabled or artifact
|
||||
reads are off, those commands keep local/offline behavior.
|
||||
|
||||
## Vault layout
|
||||
|
||||
```text
|
||||
<vault>/
|
||||
AGENTS.md
|
||||
WIKI.md
|
||||
index.md
|
||||
inbox.md
|
||||
entities/
|
||||
concepts/
|
||||
syntheses/
|
||||
sources/
|
||||
reports/
|
||||
_attachments/
|
||||
_views/
|
||||
.openclaw-wiki/
|
||||
```
|
||||
|
||||
Managed content stays inside generated blocks; human note blocks are
|
||||
preserved across regeneration.
|
||||
|
||||
- `sources/`: imported raw material and bridge/unsafe-local-backed pages
|
||||
- `entities/`: durable things, people, systems, projects, objects
|
||||
- `concepts/`: ideas, abstractions, patterns, policies (also the landing spot for OKF imports)
|
||||
- `syntheses/`: compiled summaries and maintained rollups
|
||||
- `reports/`: generated dashboards
|
||||
|
||||
## Open Knowledge Format imports
|
||||
|
||||
```bash
|
||||
openclaw wiki okf import ./bundles/ga4
|
||||
```
|
||||
|
||||
Import an unpacked Open Knowledge Format bundle into wiki concept pages. Good
|
||||
fit when a data catalog, documentation crawler, or enrichment agent already
|
||||
produces OKF: keep OKF as the portable exchange artifact, let `memory-wiki`
|
||||
turn it into OpenClaw-native concept pages and compiled digests.
|
||||
|
||||
- non-reserved `.md` files are concept documents
|
||||
- each imported concept requires a non-empty `type` frontmatter field; missing `type` produces a `missing-type` warning and the file is skipped
|
||||
- unknown `type` values are accepted as generic concepts
|
||||
- `index.md` and `log.md` are reserved and never imported as concepts
|
||||
- broken or external markdown links are left unchanged
|
||||
|
||||
Imported pages flatten under `concepts/` so existing compile, search, get, and
|
||||
dashboard flows see them without a second wiki tree. Each page keeps the
|
||||
original OKF concept ID, source path, `type`, `resource`, `tags`, timestamp,
|
||||
and full producer frontmatter. Internal OKF links rewrite to the generated
|
||||
wiki concept pages and also emit structured `relationships` entries with
|
||||
`kind: okf-link`.
|
||||
|
||||
## Structured claims and evidence
|
||||
|
||||
Pages carry structured `claims` frontmatter, not just freeform text. Each
|
||||
claim can include `id`, `text`, `status`, `confidence`, `evidence[]`, and
|
||||
`updatedAt`. Each evidence entry can include `kind`, `sourceId`, `path`,
|
||||
`lines`, `weight`, `confidence`, `privacyTier`, `note`, and `updatedAt`.
|
||||
|
||||
This makes the wiki behave like a belief layer, not a passive note dump.
|
||||
Claims can be tracked, scored, contested, and resolved back to sources.
|
||||
|
||||
## Agent-facing entity metadata
|
||||
|
||||
Entity pages carry generic routing metadata usable for people, teams,
|
||||
systems, projects, or any other entity type:
|
||||
|
||||
- `entityType`: for example `person`, `team`, `system`, `project`
|
||||
- `canonicalId`: stable identity key across aliases and imports
|
||||
- `aliases`: names, handles, or labels that resolve to the same page
|
||||
- `privacyTier`: free-form string; `public` is treated as no-review, any other value (for example `local-private`, `sensitive`, `confirm-before-use`) is flagged in `reports/privacy-review.md`
|
||||
- `bestUsedFor` / `notEnoughFor`: compact routing hints
|
||||
- `lastRefreshedAt`: source-refresh timestamp, separate from page edit time
|
||||
- `personCard`: optional person-specific routing card (handles, socials, emails, timezone, lane, ask-for, avoid-asking-for, confidence, privacy tier)
|
||||
- `relationships`: typed edges to related pages (target, kind, weight, confidence, evidence kind, privacy tier, note)
|
||||
|
||||
For a people wiki, start with `reports/person-agent-directory.md`, then open
|
||||
the person page with `wiki_get` before using contact details or inferred
|
||||
facts.
|
||||
|
||||
<Accordion title="Entity page example">
|
||||
```yaml
|
||||
pageType: entity
|
||||
entityType: person
|
||||
id: entity.example-person
|
||||
canonicalId: maintainer.example-person
|
||||
aliases:
|
||||
- Alex
|
||||
- example-handle
|
||||
privacyTier: local-private
|
||||
bestUsedFor:
|
||||
- Example ecosystem routing
|
||||
notEnoughFor:
|
||||
- legal approval
|
||||
lastRefreshedAt: "2026-04-29T00:00:00.000Z"
|
||||
personCard:
|
||||
handles:
|
||||
- "@example-handle"
|
||||
socials:
|
||||
- "https://x.example/example-handle"
|
||||
emails:
|
||||
- alex@example.com
|
||||
timezone: America/Chicago
|
||||
lane: Example ecosystem
|
||||
askFor:
|
||||
- Example rollout questions
|
||||
avoidAskingFor:
|
||||
- unrelated billing decisions
|
||||
confidence: 0.8
|
||||
privacyTier: confirm-before-use
|
||||
relationships:
|
||||
- targetId: entity.other-person
|
||||
targetTitle: Other Person
|
||||
kind: collaborates-with
|
||||
confidence: 0.7
|
||||
evidenceKind: discrawl-stat
|
||||
claims:
|
||||
- id: claim.example.routing
|
||||
text: Alex is useful for example-ecosystem routing.
|
||||
status: supported
|
||||
confidence: 0.9
|
||||
evidence:
|
||||
- kind: maintainer-whois
|
||||
sourceId: source.maintainers
|
||||
privacyTier: local-private
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
## Compile pipeline
|
||||
|
||||
Compile reads wiki pages, normalizes summaries, and emits stable
|
||||
machine-facing artifacts under:
|
||||
|
||||
- `.openclaw-wiki/cache/agent-digest.json`
|
||||
- `.openclaw-wiki/cache/claims.jsonl`
|
||||
|
||||
Agents and runtime code read these digests instead of scraping Markdown.
|
||||
Compiled output also powers first-pass wiki indexing for search/get, claim-id
|
||||
lookup back to owning pages, compact prompt supplements, and report
|
||||
generation.
|
||||
|
||||
## Dashboards and health reports
|
||||
|
||||
When `render.createDashboards` is enabled, compile maintains dashboards under
|
||||
`reports/`:
|
||||
|
||||
| Report | Tracks |
|
||||
| ----------------------------------- | -------------------------------------------------- |
|
||||
| `reports/open-questions.md` | pages with unresolved questions |
|
||||
| `reports/contradictions.md` | contradiction note clusters |
|
||||
| `reports/low-confidence.md` | low-confidence pages and claims |
|
||||
| `reports/claim-health.md` | claims missing structured evidence |
|
||||
| `reports/stale-pages.md` | stale or unknown freshness |
|
||||
| `reports/person-agent-directory.md` | person/entity routing cards |
|
||||
| `reports/relationship-graph.md` | structured relationship edges |
|
||||
| `reports/provenance-coverage.md` | evidence class coverage |
|
||||
| `reports/privacy-review.md` | non-public privacy tiers needing review before use |
|
||||
|
||||
## Search and retrieval
|
||||
|
||||
Two search backends:
|
||||
|
||||
- `shared`: use the shared memory search flow when available
|
||||
- `local`: search the wiki locally
|
||||
|
||||
Three corpora: `wiki`, `memory`, `all`.
|
||||
|
||||
- `wiki_search` / `wiki_get` use compiled digests as a first pass when possible
|
||||
- claim ids resolve back to the owning page
|
||||
- contested/stale/fresh claims influence ranking
|
||||
- provenance labels survive into results
|
||||
|
||||
Search modes (`--mode` / tool `mode` param):
|
||||
|
||||
| Mode | Boosts |
|
||||
| ----------------- | -------------------------------------------------------------- |
|
||||
| `auto` | balanced default |
|
||||
| `find-person` | person-like entities, aliases, handles, socials, canonical IDs |
|
||||
| `route-question` | agent cards, ask-for/best-used-for hints, relationship context |
|
||||
| `source-evidence` | source pages and structured evidence metadata |
|
||||
| `raw-claim` | matching structured claims; returns claim/evidence metadata |
|
||||
|
||||
When a result matches a structured claim, `wiki_search` returns
|
||||
`matchedClaimId`, `matchedClaimStatus`, `matchedClaimConfidence`,
|
||||
`evidenceKinds`, and `evidenceSourceIds` in its details payload. Text output
|
||||
includes compact `Claim:` and `Evidence:` lines when available.
|
||||
|
||||
## Agent tools
|
||||
|
||||
| Tool | Purpose |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `wiki_status` | current vault mode, health, Obsidian CLI availability |
|
||||
| `wiki_search` | search wiki pages and, when configured, the shared memory corpus; accepts `mode` for person lookup, question routing, source evidence, or raw claim drilldown |
|
||||
| `wiki_get` | read a wiki page by id/path, falling back to the shared memory corpus when shared search is enabled and the lookup misses |
|
||||
| `wiki_apply` | narrow synthesis/metadata mutations without freeform page surgery |
|
||||
| `wiki_lint` | structural checks, provenance gaps, contradictions, open questions |
|
||||
|
||||
The plugin also registers a non-exclusive memory corpus supplement, so shared
|
||||
`memory_search` and `memory_get` can reach the wiki when the active memory
|
||||
plugin supports corpus selection.
|
||||
|
||||
## Prompt and context behavior
|
||||
|
||||
When `context.includeCompiledDigestPrompt` is enabled, memory prompt sections
|
||||
append a compact compiled snapshot from `agent-digest.json`: top pages only,
|
||||
top claims only, contradiction count, question count, confidence/freshness
|
||||
qualifiers. This is opt-in because it changes prompt shape; it mainly matters
|
||||
for context engines or prompt assembly that explicitly consume memory
|
||||
supplements.
|
||||
|
||||
## Configuration
|
||||
|
||||
Put config under `plugins.entries.memory-wiki.config`:
|
||||
|
||||
```json5
|
||||
{
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-wiki": {
|
||||
enabled: true,
|
||||
config: {
|
||||
vaultMode: "isolated",
|
||||
vault: {
|
||||
path: "~/.openclaw/wiki/main",
|
||||
renderMode: "obsidian",
|
||||
},
|
||||
obsidian: {
|
||||
enabled: true,
|
||||
useOfficialCli: true,
|
||||
vaultName: "OpenClaw Wiki",
|
||||
openAfterWrites: false,
|
||||
},
|
||||
bridge: {
|
||||
enabled: false,
|
||||
readMemoryArtifacts: true,
|
||||
indexDreamReports: true,
|
||||
indexDailyNotes: true,
|
||||
indexMemoryRoot: true,
|
||||
followMemoryEvents: true,
|
||||
},
|
||||
unsafeLocal: {
|
||||
allowPrivateMemoryCoreAccess: false,
|
||||
paths: [],
|
||||
},
|
||||
ingest: {
|
||||
autoCompile: true,
|
||||
maxConcurrentJobs: 1,
|
||||
allowUrlIngest: true,
|
||||
},
|
||||
search: {
|
||||
backend: "shared",
|
||||
corpus: "wiki",
|
||||
},
|
||||
context: {
|
||||
includeCompiledDigestPrompt: false,
|
||||
},
|
||||
render: {
|
||||
preserveHumanBlocks: true,
|
||||
createBacklinks: true,
|
||||
createDashboards: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Key toggles:
|
||||
|
||||
| Key | Values / default | Notes |
|
||||
| ------------------------------------------ | ---------------------------------------------- | -------------------------------------------------------- |
|
||||
| `vaultMode` | `isolated` (default), `bridge`, `unsafe-local` | |
|
||||
| `vault.path` | default `~/.openclaw/wiki/main` | |
|
||||
| `vault.renderMode` | `native` (default), `obsidian` | |
|
||||
| `bridge.readMemoryArtifacts` | default `true` | import active memory plugin public artifacts |
|
||||
| `bridge.followMemoryEvents` | default `true` | include event logs in bridge mode |
|
||||
| `unsafeLocal.allowPrivateMemoryCoreAccess` | default `false` | required to run `unsafe-local` imports |
|
||||
| `unsafeLocal.paths` | default `[]` | explicit local paths to import in `unsafe-local` mode |
|
||||
| `search.backend` | `shared` (default), `local` | |
|
||||
| `search.corpus` | `wiki` (default), `memory`, `all` | |
|
||||
| `context.includeCompiledDigestPrompt` | default `false` | append compact digest snapshot to memory prompt sections |
|
||||
| `render.createBacklinks` | default `true` | generate deterministic related blocks |
|
||||
| `render.createDashboards` | default `true` | generate dashboard pages |
|
||||
|
||||
### Example: QMD + bridge mode
|
||||
|
||||
Use this when you want QMD for recall and `memory-wiki` for a maintained
|
||||
knowledge layer. Each layer stays focused: QMD keeps raw notes, session
|
||||
exports, and extra collections searchable, while `memory-wiki` compiles
|
||||
stable entities, claims, dashboards, and source pages.
|
||||
|
||||
```json5
|
||||
{
|
||||
memory: {
|
||||
backend: "qmd",
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-wiki": {
|
||||
enabled: true,
|
||||
config: {
|
||||
vaultMode: "bridge",
|
||||
bridge: {
|
||||
enabled: true,
|
||||
readMemoryArtifacts: true,
|
||||
indexDreamReports: true,
|
||||
indexDailyNotes: true,
|
||||
indexMemoryRoot: true,
|
||||
followMemoryEvents: true,
|
||||
},
|
||||
search: {
|
||||
backend: "shared",
|
||||
corpus: "all",
|
||||
},
|
||||
context: {
|
||||
includeCompiledDigestPrompt: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
This keeps QMD in charge of active memory recall, `memory-wiki` focused on
|
||||
compiled pages and dashboards, and prompt shape unchanged until you
|
||||
intentionally enable compiled digest prompts.
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
openclaw wiki status
|
||||
openclaw wiki doctor
|
||||
openclaw wiki init
|
||||
openclaw wiki ingest ./notes/alpha.md
|
||||
openclaw wiki compile
|
||||
openclaw wiki lint
|
||||
openclaw wiki search "alpha"
|
||||
openclaw wiki get entity.alpha
|
||||
openclaw wiki apply synthesis "Alpha Summary" --body "..." --source-id source.alpha
|
||||
openclaw wiki bridge import
|
||||
openclaw wiki obsidian status
|
||||
```
|
||||
|
||||
See [CLI: wiki](/cli/wiki) for the full command reference, including
|
||||
`wiki okf import`, `wiki apply metadata`, `wiki unsafe-local import`,
|
||||
`wiki chatgpt import` / `wiki chatgpt rollback`, and the full `wiki obsidian`
|
||||
subcommand set.
|
||||
|
||||
## Obsidian support
|
||||
|
||||
When `vault.renderMode` is `obsidian`, the plugin writes Obsidian-friendly
|
||||
Markdown and can optionally use the official `obsidian` CLI for status
|
||||
probing, vault search, opening a page, invoking a command, and jumping to the
|
||||
daily note. This is optional; the wiki still works in native mode without
|
||||
Obsidian.
|
||||
|
||||
## Recommended workflow
|
||||
|
||||
<Steps>
|
||||
<Step title="Keep the active memory plugin for recall">
|
||||
Recall, promotion, and dreaming stay owned by the configured memory backend.
|
||||
</Step>
|
||||
<Step title="Enable memory-wiki">
|
||||
Start with `isolated` mode unless you explicitly want bridge mode.
|
||||
</Step>
|
||||
<Step title="Use wiki_search / wiki_get when provenance matters">
|
||||
Prefer these over `memory_search` when you want wiki-specific ranking or page-level belief structure.
|
||||
</Step>
|
||||
<Step title="Use wiki_apply for narrow syntheses or metadata updates">
|
||||
Avoid hand-editing managed generated blocks.
|
||||
</Step>
|
||||
<Step title="Run wiki_lint after meaningful changes">
|
||||
Catches contradictions, open questions, and provenance gaps.
|
||||
</Step>
|
||||
<Step title="Turn on dashboards for stale/contradiction visibility">
|
||||
Set `render.createDashboards: true` (default).
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Related docs
|
||||
|
||||
- [Memory Overview](/concepts/memory)
|
||||
- [CLI: memory](/cli/memory)
|
||||
- [CLI: wiki](/cli/wiki)
|
||||
- [Plugin SDK overview](/plugins/sdk-overview)
|
||||
520
docs/plugins/message-presentation.md
Normal file
520
docs/plugins/message-presentation.md
Normal file
@@ -0,0 +1,520 @@
|
||||
---
|
||||
summary: "Semantic message cards, buttons, selects, fallback text, and delivery hints for channel plugins"
|
||||
title: "Message presentation"
|
||||
read_when:
|
||||
- Adding or modifying message card, button, or select rendering
|
||||
- Building a channel plugin that supports rich outbound messages
|
||||
- Changing message tool presentation or delivery capabilities
|
||||
- Debugging provider-specific card/block/component rendering regressions
|
||||
---
|
||||
|
||||
Message presentation is OpenClaw's shared contract for rich outbound chat UI.
|
||||
It lets agents, CLI commands, approval flows, and plugins describe the message
|
||||
intent once, while each channel plugin renders the best native shape it can.
|
||||
|
||||
Use presentation for portable message UI: text sections, small context/footer
|
||||
text, dividers, buttons, select menus, and card title/tone.
|
||||
|
||||
Do not add new provider-native fields such as Discord `components`, Slack
|
||||
`blocks`, Telegram `buttons`, Teams `card`, or Feishu `card` to the shared
|
||||
message tool. Those are renderer outputs owned by the channel plugin.
|
||||
|
||||
## Contract
|
||||
|
||||
Plugin authors import the public contract from:
|
||||
|
||||
```ts
|
||||
import type {
|
||||
MessagePresentation,
|
||||
ReplyPayloadDelivery,
|
||||
} from "openclaw/plugin-sdk/interactive-runtime";
|
||||
```
|
||||
|
||||
Shape:
|
||||
|
||||
```ts
|
||||
type MessagePresentation = {
|
||||
title?: string;
|
||||
tone?: "neutral" | "info" | "success" | "warning" | "danger";
|
||||
blocks: MessagePresentationBlock[];
|
||||
};
|
||||
|
||||
type MessagePresentationBlock =
|
||||
| { type: "text"; text: string }
|
||||
| { type: "context"; text: string }
|
||||
| { type: "divider" }
|
||||
| { type: "buttons"; buttons: MessagePresentationButton[] }
|
||||
| { type: "select"; placeholder?: string; options: MessagePresentationOption[] };
|
||||
|
||||
type MessagePresentationAction =
|
||||
| { type: "command"; command: string }
|
||||
| { type: "callback"; value: string };
|
||||
|
||||
type MessagePresentationButton = {
|
||||
label: string;
|
||||
action?: MessagePresentationAction;
|
||||
/** Legacy callback value. Prefer action for new controls. */
|
||||
value?: string;
|
||||
url?: string;
|
||||
webApp?: { url: string };
|
||||
/** @deprecated Use webApp. Accepted for legacy JSON payloads only. */
|
||||
web_app?: { url: string };
|
||||
priority?: number;
|
||||
disabled?: boolean;
|
||||
reusable?: boolean;
|
||||
style?: "primary" | "secondary" | "success" | "danger";
|
||||
};
|
||||
|
||||
type MessagePresentationOption = {
|
||||
label: string;
|
||||
action?: MessagePresentationAction;
|
||||
/** Legacy callback value. Prefer action for new controls. */
|
||||
value?: string;
|
||||
};
|
||||
|
||||
type ReplyPayloadDelivery = {
|
||||
pin?:
|
||||
| boolean
|
||||
| {
|
||||
enabled: boolean;
|
||||
notify?: boolean;
|
||||
required?: boolean;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Button semantics:
|
||||
|
||||
- `action.type: "command"` runs a native slash command through core's command
|
||||
path. Use this for built-in command buttons and menus.
|
||||
- `action.type: "callback"` carries opaque plugin data through the channel's
|
||||
interaction path. Channel plugins must not reinterpret callback data as slash
|
||||
commands.
|
||||
- `value` is the legacy opaque callback value. New controls should use `action`
|
||||
so channel plugins can map commands and callbacks without guessing from text.
|
||||
- `url` is a link button. It can exist without `value`.
|
||||
- `webApp` describes a channel-native web app button. Telegram renders this
|
||||
as `web_app` and only supports it in private chats. `web_app` is still
|
||||
accepted in loose JSON payloads for compatibility, but TypeScript producers
|
||||
should use `webApp`.
|
||||
- `label` is required and is also used in text fallback.
|
||||
- `style` is advisory. Renderers should map unsupported styles to a safe
|
||||
default, not fail the send.
|
||||
- `priority` is optional. When a channel advertises action limits and controls
|
||||
must be dropped, core keeps higher-priority buttons first and preserves
|
||||
original order among equal priority buttons. When all controls fit, authored
|
||||
order is preserved.
|
||||
- `disabled` is optional. Channels must opt in with `supportsDisabled`; otherwise
|
||||
core degrades the disabled control to non-interactive fallback text. A
|
||||
disabled button always renders label-only in fallback text, even when it
|
||||
carries a `command` action.
|
||||
- `reusable` is optional. Channels that support reusable native callbacks may
|
||||
keep the action available after a successful interaction. Use it for
|
||||
repeatable or idempotent actions such as refresh, inspect, or more details;
|
||||
leave it unset for normal one-shot approvals and destructive actions.
|
||||
|
||||
Select semantics:
|
||||
|
||||
- `options[].action` has the same command/callback meaning as button `action`.
|
||||
- `options[].value` is the legacy selected application value.
|
||||
- `placeholder` is advisory and may be ignored by channels without native
|
||||
select support.
|
||||
- If a channel does not support selects, fallback text lists the labels.
|
||||
|
||||
## Producer examples
|
||||
|
||||
Simple card:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Deploy approval",
|
||||
"tone": "warning",
|
||||
"blocks": [
|
||||
{ "type": "text", "text": "Canary is ready to promote." },
|
||||
{ "type": "context", "text": "Build 1234, staging passed." },
|
||||
{
|
||||
"type": "buttons",
|
||||
"buttons": [
|
||||
{ "label": "Approve", "value": "deploy:approve", "style": "success" },
|
||||
{ "label": "Decline", "value": "deploy:decline", "style": "danger" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
URL-only link button:
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{ "type": "text", "text": "Release notes are ready." },
|
||||
{
|
||||
"type": "buttons",
|
||||
"buttons": [{ "label": "Open notes", "url": "https://example.com/release" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Telegram Mini App button:
|
||||
|
||||
```json
|
||||
{
|
||||
"blocks": [
|
||||
{
|
||||
"type": "buttons",
|
||||
"buttons": [{ "label": "Launch", "web_app": { "url": "https://example.com/app" } }]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Select menu:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Choose environment",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "select",
|
||||
"placeholder": "Environment",
|
||||
"options": [
|
||||
{ "label": "Canary", "value": "env:canary" },
|
||||
{ "label": "Production", "value": "env:prod" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
CLI send:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel slack \
|
||||
--target channel:C123 \
|
||||
--message "Deploy approval" \
|
||||
--presentation '{"title":"Deploy approval","tone":"warning","blocks":[{"type":"text","text":"Canary is ready."},{"type":"buttons","buttons":[{"label":"Approve","value":"deploy:approve","style":"success"},{"label":"Decline","value":"deploy:decline","style":"danger"}]}]}'
|
||||
```
|
||||
|
||||
Pinned delivery:
|
||||
|
||||
```bash
|
||||
openclaw message send --channel telegram \
|
||||
--target -1001234567890 \
|
||||
--message "Topic opened" \
|
||||
--pin
|
||||
```
|
||||
|
||||
Pinned delivery with explicit JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"pin": {
|
||||
"enabled": true,
|
||||
"notify": true,
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Renderer contract
|
||||
|
||||
Channel plugins declare render support on their outbound adapter:
|
||||
|
||||
```ts
|
||||
const adapter: ChannelOutboundAdapter = {
|
||||
deliveryMode: "direct",
|
||||
presentationCapabilities: {
|
||||
supported: true,
|
||||
buttons: true,
|
||||
selects: true,
|
||||
context: true,
|
||||
divider: true,
|
||||
limits: {
|
||||
actions: {
|
||||
maxActions: 25,
|
||||
maxActionsPerRow: 5,
|
||||
maxRows: 5,
|
||||
maxLabelLength: 80,
|
||||
maxValueBytes: 100,
|
||||
supportsStyles: true,
|
||||
supportsDisabled: false,
|
||||
},
|
||||
selects: {
|
||||
maxOptions: 25,
|
||||
maxLabelLength: 100,
|
||||
maxValueBytes: 100,
|
||||
},
|
||||
text: {
|
||||
maxLength: 2000,
|
||||
encoding: "characters",
|
||||
markdownDialect: "discord-markdown",
|
||||
},
|
||||
},
|
||||
},
|
||||
deliveryCapabilities: {
|
||||
pin: true,
|
||||
},
|
||||
renderPresentation({ payload, presentation, ctx }) {
|
||||
return renderNativePayload(payload, presentation, ctx);
|
||||
},
|
||||
async pinDeliveredMessage({ target, messageId, pin }) {
|
||||
await pinNativeMessage(target, messageId, { notify: pin.notify === true });
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Capability booleans describe what the renderer can make interactive. Optional
|
||||
`limits` describe the generic envelope core can adapt before calling the
|
||||
renderer:
|
||||
|
||||
```ts
|
||||
type ChannelPresentationCapabilities = {
|
||||
supported?: boolean;
|
||||
buttons?: boolean;
|
||||
selects?: boolean;
|
||||
context?: boolean;
|
||||
divider?: boolean;
|
||||
limits?: {
|
||||
actions?: {
|
||||
maxActions?: number;
|
||||
maxActionsPerRow?: number;
|
||||
maxRows?: number;
|
||||
maxLabelLength?: number;
|
||||
maxValueBytes?: number;
|
||||
supportsStyles?: boolean;
|
||||
supportsDisabled?: boolean;
|
||||
supportsLayoutHints?: boolean;
|
||||
};
|
||||
selects?: {
|
||||
maxOptions?: number;
|
||||
maxLabelLength?: number;
|
||||
maxValueBytes?: number;
|
||||
};
|
||||
text?: {
|
||||
maxLength?: number;
|
||||
encoding?: "characters" | "utf8-bytes" | "utf16-units";
|
||||
markdownDialect?: "plain" | "markdown" | "html" | "slack-mrkdwn" | "discord-markdown";
|
||||
supportsEdit?: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Core applies generic limits to semantic controls before rendering. Renderers
|
||||
still own final provider-specific validation and clipping for native block
|
||||
count, card size, URL limits, and provider quirks that cannot be expressed in
|
||||
the generic contract. If limits remove every control from a block, core keeps
|
||||
the labels as non-interactive context text so the delivered message still has a
|
||||
visible fallback.
|
||||
|
||||
## Core render flow
|
||||
|
||||
When a `ReplyPayload` or message action includes `presentation`, core:
|
||||
|
||||
1. Normalizes the presentation payload.
|
||||
2. Resolves the target channel's outbound adapter.
|
||||
3. Reads `presentationCapabilities`.
|
||||
4. Applies generic capability limits such as action count, label length, and
|
||||
select option count when the adapter advertises them.
|
||||
5. Calls `renderPresentation` when the adapter can render the payload.
|
||||
6. Falls back to conservative text when the adapter is absent or cannot render.
|
||||
7. Sends the resulting payload through the normal channel delivery path.
|
||||
8. Applies delivery metadata such as `delivery.pin` after the first successful
|
||||
sent message.
|
||||
|
||||
Core owns fallback behavior so producers can stay channel-agnostic. Channel
|
||||
plugins own native rendering and interaction handling.
|
||||
|
||||
## Degradation rules
|
||||
|
||||
Presentation must be safe to send on limited channels.
|
||||
|
||||
Fallback text includes:
|
||||
|
||||
- `title` as the first line
|
||||
- `text` blocks as normal paragraphs
|
||||
- `context` blocks as compact context lines
|
||||
- `divider` blocks as a visual separator
|
||||
- button labels, including URLs for link buttons
|
||||
- select option labels
|
||||
|
||||
### Button value fallback visibility
|
||||
|
||||
When a channel cannot render interactive controls, button and select values
|
||||
fall back to plain text. The fallback behavior preserves usability while
|
||||
keeping opaque callback data private:
|
||||
|
||||
- **`command`-typed actions** render as `label: \`command\`` so users can
|
||||
copy the command and run it manually in the channel input.
|
||||
- **`callback`-typed actions** and legacy **`value`** fields render as
|
||||
label-only. The opaque callback value is not exposed in fallback text.
|
||||
- **`url` / `webApp`** buttons render the URL text alongside the button
|
||||
label, since the URL is user-facing.
|
||||
- **Select options** render as label-only. The underlying option value is not
|
||||
exposed in fallback text.
|
||||
|
||||
Channel adapters that add manual-command guidance in their fallback UI (e.g.
|
||||
Feishu document-comment instructions) must derive the command-present check
|
||||
from the same presentation blocks that the fallback renderer uses, so the
|
||||
guidance text only appears when a manual command is actually shown.
|
||||
|
||||
Unsupported native controls should degrade rather than fail the whole send.
|
||||
Examples:
|
||||
|
||||
- Telegram with inline buttons disabled sends text fallback.
|
||||
- A channel without select support lists select options as text.
|
||||
- A URL-only button becomes either a native link button or a fallback URL line.
|
||||
- Optional pin failures do not fail the delivered message.
|
||||
|
||||
The main exception is `delivery.pin.required: true`; if pinning is requested as
|
||||
required and the channel cannot pin the sent message, delivery reports failure.
|
||||
|
||||
## Provider mapping
|
||||
|
||||
Current bundled renderers:
|
||||
|
||||
| Channel | Native render target | Notes |
|
||||
| --------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Discord | Components and component containers | Preserves legacy `channelData.discord.components` for existing provider-native payload producers, but new shared sends should use `presentation`. |
|
||||
| Feishu | Interactive cards | Card header can use `title`; body avoids duplicating that title. |
|
||||
| Matrix | Text fallback plus structured event field | Buttons/selects advertise as supported, but every block currently renders as `renderMessagePresentationFallbackText` output carried in a `com.openclaw.presentation` event field, not native interactive widgets. |
|
||||
| Mattermost | Text plus interactive props | Selects and dividers are not supported; those blocks degrade to text. |
|
||||
| Microsoft Teams | Adaptive Cards | Plain `message` text is included with the card when both are provided. Selects, styles, and disabled state are not supported. |
|
||||
| Slack | Block Kit | Preserves legacy `channelData.slack.blocks` for existing provider-native payload producers, but new shared sends should use `presentation`. |
|
||||
| Telegram | Text plus inline keyboards | Buttons/selects require inline button capability for the target surface; otherwise text fallback is used. |
|
||||
| Plain channels | Text fallback | Channels without a renderer still get readable output. |
|
||||
|
||||
Provider-native payload compatibility is a transition affordance for existing
|
||||
reply producers. It is not a reason to add new shared native fields.
|
||||
|
||||
## Presentation vs InteractiveReply
|
||||
|
||||
`InteractiveReply` is the older internal subset used by approval and interaction
|
||||
helpers. It supports:
|
||||
|
||||
- text
|
||||
- buttons
|
||||
- selects
|
||||
|
||||
`MessagePresentation` is the canonical shared send contract. It adds:
|
||||
|
||||
- title
|
||||
- tone
|
||||
- context
|
||||
- divider
|
||||
- URL-only buttons
|
||||
- generic delivery metadata through `ReplyPayload.delivery`
|
||||
|
||||
Use helpers from `openclaw/plugin-sdk/interactive-runtime` when bridging older
|
||||
code:
|
||||
|
||||
```ts
|
||||
import {
|
||||
adaptMessagePresentationForChannel,
|
||||
applyPresentationActionLimits,
|
||||
hasMessagePresentationBlocks,
|
||||
interactiveReplyToPresentation,
|
||||
isMessagePresentationInteractiveBlock,
|
||||
normalizeMessagePresentation,
|
||||
presentationPageSize,
|
||||
presentationToInteractiveControlsReply,
|
||||
presentationToInteractiveReply,
|
||||
renderMessagePresentationFallbackText,
|
||||
resolveMessagePresentationActionValue,
|
||||
resolveMessagePresentationControlValue,
|
||||
} from "openclaw/plugin-sdk/interactive-runtime";
|
||||
```
|
||||
|
||||
New code should accept or produce `MessagePresentation` directly. Existing
|
||||
`interactive` payloads are a deprecated subset of `presentation`; runtime
|
||||
support remains for older producers.
|
||||
|
||||
Non-deprecated helpers worth knowing:
|
||||
|
||||
- `normalizeMessagePresentation(raw)` / `hasMessagePresentationBlocks(value)`
|
||||
validate and coerce an untyped payload (for example, JSON from the CLI
|
||||
`--presentation` flag) into `MessagePresentation`.
|
||||
- `isMessagePresentationInteractiveBlock(block)` narrows a block to the
|
||||
`buttons` | `select` union.
|
||||
- `resolveMessagePresentationActionValue(action)` /
|
||||
`resolveMessagePresentationControlValue(control)` read the effective
|
||||
command/callback value off an `action`, falling back to the legacy `value`
|
||||
field for `resolveMessagePresentationControlValue`.
|
||||
|
||||
The legacy `InteractiveReply*` types and conversion helpers are marked
|
||||
`@deprecated` in the SDK:
|
||||
|
||||
- `InteractiveReply`, `InteractiveReplyBlock`, `InteractiveReplyButton`,
|
||||
`InteractiveReplyOption`, `InteractiveReplySelectBlock`, and
|
||||
`InteractiveReplyTextBlock`
|
||||
- `normalizeInteractiveReply(...)`
|
||||
- `hasInteractiveReplyBlocks(...)`
|
||||
- `interactiveReplyToPresentation(...)`
|
||||
- `presentationToInteractiveReply(...)`
|
||||
- `presentationToInteractiveControlsReply(...)`
|
||||
- `resolveInteractiveTextFallback(...)`
|
||||
- `reduceInteractiveReply(...)`
|
||||
|
||||
`presentationToInteractiveReply(...)` and
|
||||
`presentationToInteractiveControlsReply(...)` remain available as renderer
|
||||
bridges for legacy channel implementations. New producer code should not call
|
||||
them; send `presentation` and let core/channel adaptation handle rendering.
|
||||
|
||||
Approval helpers also have presentation-first replacements:
|
||||
|
||||
- use `buildApprovalPresentationFromActionDescriptors(...)` instead of
|
||||
`buildApprovalInteractiveReplyFromActionDescriptors(...)`
|
||||
- use `buildApprovalPresentation(...)` instead of
|
||||
`buildApprovalInteractiveReply(...)`
|
||||
- use `buildExecApprovalPresentation(...)` instead of
|
||||
`buildExecApprovalInteractiveReply(...)`
|
||||
|
||||
`renderMessagePresentationFallbackText(...)` returns an empty string for
|
||||
presentation blocks that have no text fallback, such as a divider-only
|
||||
presentation. Transports that require a non-empty send body can pass
|
||||
`emptyFallback` to opt into a minimal body without changing the default fallback
|
||||
contract.
|
||||
|
||||
## Delivery pin
|
||||
|
||||
Pinning is delivery behavior, not presentation. Use `delivery.pin` instead of
|
||||
provider-native fields such as `channelData.telegram.pin`.
|
||||
|
||||
Semantics:
|
||||
|
||||
- `pin: true` pins the first successfully delivered message.
|
||||
- `pin.notify` defaults to `false`.
|
||||
- `pin.required` defaults to `false`.
|
||||
- Optional pin failures degrade and leave the sent message intact.
|
||||
- Required pin failures fail delivery.
|
||||
- Chunked messages pin the first delivered chunk, not the tail chunk.
|
||||
|
||||
Manual `pin`, `unpin`, and `pins` message actions still exist for existing
|
||||
messages where the provider supports those operations.
|
||||
|
||||
## Plugin author checklist
|
||||
|
||||
- Declare `presentation` from `describeMessageTool(...)` when the channel can
|
||||
render or safely degrade semantic presentation.
|
||||
- Add `presentationCapabilities` to the runtime outbound adapter.
|
||||
- Implement `renderPresentation` in runtime code, not control-plane plugin
|
||||
setup code.
|
||||
- Keep native UI libraries out of hot setup/catalog paths.
|
||||
- Declare generic capability limits on `presentationCapabilities.limits` when
|
||||
they are known.
|
||||
- Preserve final platform limits in the renderer and tests.
|
||||
- Add fallback tests for unsupported buttons, selects, URL buttons, title/text
|
||||
duplication, and mixed `message` plus `presentation` sends.
|
||||
- Add delivery pin support through `deliveryCapabilities.pin` and
|
||||
`pinDeliveredMessage` only when the provider can pin the sent message id.
|
||||
- Do not expose new provider-native card/block/component/button fields through
|
||||
the shared message action schema.
|
||||
|
||||
## Related docs
|
||||
|
||||
- [Message CLI](/cli/message)
|
||||
- [Plugin SDK Overview](/plugins/sdk-overview)
|
||||
- [Plugin Architecture](/plugins/architecture-internals#message-tool-schemas)
|
||||
- [Channel Presentation Refactor Plan](/plan/ui-channels)
|
||||
168
docs/plugins/oc-path.md
Normal file
168
docs/plugins/oc-path.md
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
summary: "Bundled `oc-path` plugin: ships the `openclaw path` CLI for the `oc://` workspace-file addressing scheme"
|
||||
read_when:
|
||||
- You want to inspect or edit a single leaf inside a workspace file from the terminal
|
||||
- You are scripting against workspace state and need a stable, kind-agnostic addressing scheme
|
||||
- You are deciding whether to enable the optional `oc-path` plugin on a self-hosted Gateway
|
||||
title: "OC Path plugin"
|
||||
---
|
||||
|
||||
The bundled `oc-path` plugin adds the [`openclaw path`](/cli/path) CLI for the
|
||||
`oc://` workspace-file addressing scheme. It ships in the OpenClaw repo under
|
||||
`extensions/oc-path/` but is opt-in: install/build leaves it dormant until you
|
||||
enable it.
|
||||
|
||||
`oc://` addresses point at a single leaf (or a wildcard set of leaves) inside
|
||||
a workspace file. The plugin understands four file kinds:
|
||||
|
||||
- **markdown** (`.md`): frontmatter, sections, items, fields
|
||||
- **jsonc** (`.jsonc`, `.json`): comments and formatting preserved
|
||||
- **jsonl** (`.jsonl`, `.ndjson`): line-oriented records
|
||||
- **yaml** (`.yaml`, `.yml`, `.lobster`): map/sequence/scalar nodes through the
|
||||
`yaml` package's `Document` API
|
||||
|
||||
Self-hosters and editor extensions use the CLI to read or write a single leaf
|
||||
without scripting against the SDK directly; agents and hooks treat it as a
|
||||
deterministic substrate so byte-fidelity round-trips and the redaction
|
||||
sentinel guard apply uniformly across kinds. See the
|
||||
[CLI reference](/cli/path) for the full grammar, verb-by-verb flag list, and
|
||||
worked examples per file kind; this page covers why and how to enable the
|
||||
plugin.
|
||||
|
||||
## Why enable it
|
||||
|
||||
Enable `oc-path` when scripts, hooks, or local agent tooling need to point at
|
||||
a precise piece of workspace state without a bespoke parser per file shape. A
|
||||
single `oc://` address can name a markdown frontmatter key, a section item, a
|
||||
JSONC config leaf, a JSONL event field, or a YAML workflow step.
|
||||
|
||||
That matters for maintainer workflows where the change should stay small,
|
||||
auditable, and repeatable: inspect one value, find matching records, dry-run
|
||||
a write, then apply only that leaf while leaving comments, line endings, and
|
||||
nearby formatting alone.
|
||||
|
||||
Common reasons to enable it:
|
||||
|
||||
- **Local automation**: shell scripts resolve or update one workspace value
|
||||
with `openclaw path … --json` instead of carrying separate markdown, JSONC,
|
||||
JSONL, and YAML parsing code.
|
||||
- **Agent-visible edits**: an agent shows a dry-run diff for one addressed
|
||||
leaf before writing, which is easier to review than a free-form file
|
||||
rewrite.
|
||||
- **Editor integrations**: an editor maps `oc://AGENTS.md/tools/gh` to the
|
||||
exact markdown node and line number without guessing from heading text.
|
||||
- **Diagnostics**: `emit` round-trips a file through the parser and emitter,
|
||||
so you can check whether a file kind is byte-stable before relying on
|
||||
automated edits.
|
||||
|
||||
```bash
|
||||
# Is the GitHub plugin enabled in this config?
|
||||
openclaw path resolve 'oc://config.jsonc/plugins/github/enabled' --json
|
||||
|
||||
# Which tool-call names appear in this session log?
|
||||
openclaw path find 'oc://session.jsonl/[event=tool_call]/name' --json
|
||||
|
||||
# What bytes would this tiny config edit write?
|
||||
openclaw path set 'oc://config.jsonc/plugins/github/enabled' 'true' --dry-run
|
||||
```
|
||||
|
||||
`oc-path` is intentionally not the owner of higher-level semantics. Memory
|
||||
plugins still own memory writes, config commands still own full config
|
||||
management, and last-known-good (LKG) config recovery still owns
|
||||
restore/promotion. `oc-path` is the narrow addressing and byte-preserving
|
||||
file operation layer those higher-level tools can build around.
|
||||
|
||||
## Where it runs
|
||||
|
||||
The plugin runs **in-process inside the `openclaw` CLI** on the host where you
|
||||
invoke the command. It does not need a running Gateway and does not open any
|
||||
network sockets; every verb is a pure transform over a file you point it at.
|
||||
|
||||
Plugin metadata lives in `extensions/oc-path/openclaw.plugin.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "oc-path",
|
||||
"name": "OC Path",
|
||||
"activation": {
|
||||
"onStartup": false,
|
||||
"onCommands": ["path"]
|
||||
},
|
||||
"commandAliases": [{ "name": "path", "kind": "cli" }]
|
||||
}
|
||||
```
|
||||
|
||||
`onStartup: false` keeps the plugin out of the Gateway startup path.
|
||||
`commandAliases` and `activation.onCommands` tell the CLI to load the plugin
|
||||
lazily the first time you run `openclaw path …`, so installs that never use
|
||||
the verb pay no cost.
|
||||
|
||||
## Enable
|
||||
|
||||
```bash
|
||||
openclaw plugins enable oc-path
|
||||
```
|
||||
|
||||
Restart the Gateway (if you run one) so the manifest snapshot picks up the new
|
||||
state. Bare `openclaw path` invocations work immediately on the same host;
|
||||
the CLI loads the plugin on demand.
|
||||
|
||||
Disable with:
|
||||
|
||||
```bash
|
||||
openclaw plugins disable oc-path
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
All parser dependencies are plugin-local; enabling `oc-path` does not pull
|
||||
new packages into the core runtime:
|
||||
|
||||
| Dependency | Purpose |
|
||||
| -------------- | ---------------------------------------------------------------------- |
|
||||
| `commander` | Subcommand wiring for `resolve`, `find`, `set`, `validate`, `emit`. |
|
||||
| `jsonc-parser` | JSONC parse and leaf edits with comments and trailing commas kept. |
|
||||
| `markdown-it` | Markdown tokenization for the section / item / field model. |
|
||||
| `yaml` | YAML `Document` parse / emit / edit with comments and flow style kept. |
|
||||
|
||||
JSONL stays hand-rolled: line-oriented parsing is simpler than any
|
||||
dependency, and the per-line parse already goes through `jsonc-parser`.
|
||||
|
||||
## What it provides
|
||||
|
||||
| Surface | Provided by |
|
||||
| ------------------------------ | ------------------------------------------------------- |
|
||||
| `openclaw path` CLI | `extensions/oc-path/cli-registration.ts` |
|
||||
| `oc://` parser / formatter | `extensions/oc-path/src/oc-path/oc-path.ts` |
|
||||
| Per-kind parse / emit / edit | `extensions/oc-path/src/oc-path/{md,jsonc,jsonl,yaml}` |
|
||||
| Universal resolve / find / set | `extensions/oc-path/src/oc-path/{resolve,find,edit}.ts` |
|
||||
| Redaction-sentinel guard | `extensions/oc-path/src/oc-path/sentinel.ts` |
|
||||
|
||||
The CLI is the only public surface today. The substrate verbs are private to
|
||||
the plugin; consumers use the CLI (or build their own plugin against the
|
||||
SDK).
|
||||
|
||||
## Relationship to other plugins
|
||||
|
||||
- **`memory-*`**: memory writes go through the memory plugins, not
|
||||
`oc-path`. `oc-path` is a generic file substrate; memory plugins layer
|
||||
their own semantics on top.
|
||||
- **LKG**: `path` does not know about last-known-good config restore. If a
|
||||
file you edit through `path` is also LKG-tracked, the next config observe
|
||||
cycle decides whether to promote or recover it; treat a `path` edit the
|
||||
same as any other direct write to that file.
|
||||
|
||||
## Safety
|
||||
|
||||
`set` writes raw bytes through the substrate's emit path, which applies the
|
||||
redaction-sentinel guard automatically. A leaf carrying
|
||||
`__OPENCLAW_REDACTED__` (verbatim or as a substring) is refused at write time
|
||||
with `OC_EMIT_SENTINEL`. The CLI also scrubs the literal sentinel from any
|
||||
human or JSON output it prints, replacing it with `[REDACTED]` so terminal
|
||||
captures and pipelines never leak the marker.
|
||||
|
||||
## Related
|
||||
|
||||
- [`openclaw path` CLI reference](/cli/path)
|
||||
- [Manage plugins](/plugins/manage-plugins)
|
||||
- [Building plugins](/plugins/building-plugins)
|
||||
324
docs/plugins/plugin-inventory.md
Normal file
324
docs/plugins/plugin-inventory.md
Normal file
@@ -0,0 +1,324 @@
|
||||
---
|
||||
summary: "Generated inventory of OpenClaw plugins shipped in core, published externally, or kept source-only"
|
||||
read_when:
|
||||
- You are deciding whether a plugin ships in the core npm package or installs separately
|
||||
- You are updating bundled plugin package metadata or release automation
|
||||
- You need the canonical internal vs external plugin list
|
||||
title: "Plugin inventory"
|
||||
---
|
||||
|
||||
# Plugin inventory
|
||||
|
||||
This page is generated from `extensions/*/package.json`, `openclaw.plugin.json`,
|
||||
and the root npm package `files` exclusions. Regenerate it with:
|
||||
|
||||
```bash
|
||||
pnpm plugins:inventory:gen
|
||||
```
|
||||
|
||||
## Definitions
|
||||
|
||||
- **Core npm package:** built into the `openclaw` npm package and available without a separate plugin install.
|
||||
- **Official external package:** OpenClaw-maintained plugin omitted from the core npm package, kept in this official inventory, and installed on demand through ClawHub and/or npm.
|
||||
- **Source checkout only:** repo-local plugin omitted from published npm artifacts and not advertised as an installable package.
|
||||
|
||||
Source checkouts are different from npm installs: after `pnpm install`, bundled
|
||||
plugins load from `extensions/<id>` so local edits and package-local workspace
|
||||
dependencies are available.
|
||||
|
||||
## Install a plugin
|
||||
|
||||
Use the install route in each entry to decide whether install is needed. Plugins
|
||||
that say `included in OpenClaw` are already present in the core package.
|
||||
Official external packages need one install, then a Gateway restart.
|
||||
|
||||
For example, Discord is an official external package:
|
||||
|
||||
```bash
|
||||
openclaw plugins install @openclaw/discord
|
||||
openclaw gateway restart
|
||||
openclaw plugins inspect discord --runtime --json
|
||||
```
|
||||
|
||||
During the launch cutover, ordinary bare package specs still install from npm.
|
||||
Use `clawhub:@openclaw/discord` or `npm:@openclaw/discord` when you need an
|
||||
explicit source. After install, follow the plugin's setup doc, such as
|
||||
[Discord](/channels/discord), to add credentials and channel config. See
|
||||
[Manage plugins](/plugins/manage-plugins) for update, uninstall, and publishing
|
||||
commands.
|
||||
|
||||
Each entry lists the package, distribution route, and description.
|
||||
|
||||
## Core npm package
|
||||
|
||||
60 plugins
|
||||
|
||||
- **[admin-http-rpc](/plugins/reference/admin-http-rpc)** (`@openclaw/admin-http-rpc`) - included in OpenClaw. OpenClaw admin HTTP RPC endpoint.
|
||||
|
||||
- **[alibaba](/plugins/reference/alibaba)** (`@openclaw/alibaba-provider`) - included in OpenClaw. Adds video generation provider support.
|
||||
|
||||
- **[anthropic](/plugins/reference/anthropic)** (`@openclaw/anthropic-provider`) - included in OpenClaw. Adds Anthropic model provider support to OpenClaw.
|
||||
|
||||
- **[azure-speech](/plugins/reference/azure-speech)** (`@openclaw/azure-speech`) - included in OpenClaw. Azure AI Speech text-to-speech (MP3, native Ogg/Opus voice notes, PCM telephony).
|
||||
|
||||
- **[bonjour](/plugins/reference/bonjour)** (`@openclaw/bonjour`) - included in OpenClaw. Advertise the local OpenClaw gateway over Bonjour/mDNS.
|
||||
|
||||
- **[browser](/plugins/reference/browser)** (`@openclaw/browser-plugin`) - included in OpenClaw. Adds agent-callable tools.
|
||||
|
||||
- **[byteplus](/plugins/reference/byteplus)** (`@openclaw/byteplus-provider`) - included in OpenClaw. Adds BytePlus, BytePlus Plan model provider support to OpenClaw.
|
||||
|
||||
- **[canvas](/plugins/reference/canvas)** (`@openclaw/canvas-plugin`) - included in OpenClaw. Experimental Canvas control and A2UI rendering surfaces for paired nodes.
|
||||
|
||||
- **[clawrouter](/plugins/reference/clawrouter)** (`@openclaw/clawrouter`) - included in OpenClaw. Adds ClawRouter model provider support to OpenClaw.
|
||||
|
||||
- **[codex-supervisor](/plugins/reference/codex-supervisor)** (`@openclaw/codex-supervisor`) - included in OpenClaw. Supervise Codex app-server sessions from OpenClaw.
|
||||
|
||||
- **[cohere](/plugins/reference/cohere)** (`@openclaw/cohere-provider`) - included in OpenClaw; npm; ClawHub: `clawhub:@openclaw/cohere-provider`. OpenClaw Cohere provider plugin.
|
||||
|
||||
- **[comfy](/plugins/reference/comfy)** (`@openclaw/comfy-provider`) - included in OpenClaw. Adds ComfyUI model provider support to OpenClaw.
|
||||
|
||||
- **[copilot-proxy](/plugins/reference/copilot-proxy)** (`@openclaw/copilot-proxy`) - included in OpenClaw. Adds Copilot Proxy model provider support to OpenClaw.
|
||||
|
||||
- **[deepgram](/plugins/reference/deepgram)** (`@openclaw/deepgram-provider`) - included in OpenClaw. Adds media understanding provider support. Adds realtime transcription provider support.
|
||||
|
||||
- **[document-extract](/plugins/reference/document-extract)** (`@openclaw/document-extract-plugin`) - included in OpenClaw. Extract text and fallback page images from local document attachments.
|
||||
|
||||
- **[duckduckgo](/plugins/reference/duckduckgo)** (`@openclaw/duckduckgo-plugin`) - included in OpenClaw. Adds web search provider support.
|
||||
|
||||
- **[elevenlabs](/plugins/reference/elevenlabs)** (`@openclaw/elevenlabs-speech`) - included in OpenClaw. Adds media understanding provider support. Adds realtime transcription provider support. Adds text-to-speech provider support.
|
||||
|
||||
- **[fal](/plugins/reference/fal)** (`@openclaw/fal-provider`) - included in OpenClaw. Adds fal model provider support to OpenClaw.
|
||||
|
||||
- **[file-transfer](/plugins/reference/file-transfer)** (`@openclaw/file-transfer`) - included in OpenClaw. Fetch, list, and write files on paired nodes via dedicated node commands. Bypasses bash stdout truncation by using base64 over node.invoke for binaries up to 16 MB.
|
||||
|
||||
- **[github-copilot](/plugins/reference/github-copilot)** (`@openclaw/github-copilot-provider`) - included in OpenClaw. Adds GitHub Copilot model provider support to OpenClaw.
|
||||
|
||||
- **[google](/plugins/reference/google)** (`@openclaw/google-plugin`) - included in OpenClaw. Adds Google, Google Gemini CLI, Google Vertex model provider support to OpenClaw.
|
||||
|
||||
- **[huggingface](/plugins/reference/huggingface)** (`@openclaw/huggingface-provider`) - included in OpenClaw. Adds Hugging Face model provider support to OpenClaw.
|
||||
|
||||
- **[imessage](/plugins/reference/imessage)** (`@openclaw/imessage`) - included in OpenClaw. Adds the iMessage channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[litellm](/plugins/reference/litellm)** (`@openclaw/litellm-provider`) - included in OpenClaw. Adds LiteLLM model provider support to OpenClaw.
|
||||
|
||||
- **[llm-task](/plugins/reference/llm-task)** (`@openclaw/llm-task`) - included in OpenClaw. Generic JSON-only LLM tool for structured tasks callable from workflows.
|
||||
|
||||
- **[lmstudio](/plugins/reference/lmstudio)** (`@openclaw/lmstudio-provider`) - included in OpenClaw. Adds LM Studio model provider support to OpenClaw.
|
||||
|
||||
- **[memory-core](/plugins/reference/memory-core)** (`@openclaw/memory-core`) - included in OpenClaw. Adds agent-callable tools.
|
||||
|
||||
- **[memory-wiki](/plugins/reference/memory-wiki)** (`@openclaw/memory-wiki`) - included in OpenClaw. Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw.
|
||||
|
||||
- **[microsoft](/plugins/reference/microsoft)** (`@openclaw/microsoft-speech`) - included in OpenClaw. Adds text-to-speech provider support.
|
||||
|
||||
- **[microsoft-foundry](/plugins/reference/microsoft-foundry)** (`@openclaw/microsoft-foundry`) - included in OpenClaw. Adds Microsoft Foundry model provider support to OpenClaw.
|
||||
|
||||
- **[migrate-claude](/plugins/reference/migrate-claude)** (`@openclaw/migrate-claude`) - included in OpenClaw. Imports Claude Code and Claude Desktop instructions, MCP servers, skills, and safe configuration into OpenClaw.
|
||||
|
||||
- **[migrate-hermes](/plugins/reference/migrate-hermes)** (`@openclaw/migrate-hermes`) - included in OpenClaw. Imports Hermes configuration, memories, skills, and supported credentials into OpenClaw.
|
||||
|
||||
- **[minimax](/plugins/reference/minimax)** (`@openclaw/minimax-provider`) - included in OpenClaw. Adds MiniMax, MiniMax Portal model provider support to OpenClaw.
|
||||
|
||||
- **[mistral](/plugins/reference/mistral)** (`@openclaw/mistral-provider`) - included in OpenClaw. Adds Mistral model provider support to OpenClaw.
|
||||
|
||||
- **[novita](/plugins/reference/novita)** (`@openclaw/novita-provider`) - included in OpenClaw. Adds Novita, Novita AI, Novitaai model provider support to OpenClaw.
|
||||
|
||||
- **[nvidia](/plugins/reference/nvidia)** (`@openclaw/nvidia-provider`) - included in OpenClaw. Adds NVIDIA model provider support to OpenClaw.
|
||||
|
||||
- **[oc-path](/plugins/reference/oc-path)** (`@openclaw/oc-path`) - included in OpenClaw. Adds the openclaw path CLI for oc:// workspace file addressing.
|
||||
|
||||
- **[ollama](/plugins/reference/ollama)** (`@openclaw/ollama-provider`) - included in OpenClaw. Adds Ollama, Ollama Cloud model provider support to OpenClaw.
|
||||
|
||||
- **[open-prose](/plugins/reference/open-prose)** (`@openclaw/open-prose`) - included in OpenClaw. OpenProse VM skill pack with a /prose slash command.
|
||||
|
||||
- **[openai](/plugins/reference/openai)** (`@openclaw/openai-provider`) - included in OpenClaw. Adds OpenAI model provider support to OpenClaw.
|
||||
|
||||
- **[opencode](/plugins/reference/opencode)** (`@openclaw/opencode-provider`) - included in OpenClaw. Adds OpenCode model provider support to OpenClaw.
|
||||
|
||||
- **[opencode-go](/plugins/reference/opencode-go)** (`@openclaw/opencode-go-provider`) - included in OpenClaw. Adds OpenCode Go model provider support to OpenClaw.
|
||||
|
||||
- **[openrouter](/plugins/reference/openrouter)** (`@openclaw/openrouter-provider`) - included in OpenClaw. Adds OpenRouter model provider support to OpenClaw.
|
||||
|
||||
- **[policy](/plugins/reference/policy)** (`@openclaw/policy`) - included in OpenClaw. Adds policy-backed doctor checks for workspace conformance.
|
||||
|
||||
- **[runway](/plugins/reference/runway)** (`@openclaw/runway-provider`) - included in OpenClaw. Adds video generation provider support.
|
||||
|
||||
- **[senseaudio](/plugins/reference/senseaudio)** (`@openclaw/senseaudio-provider`) - included in OpenClaw. Adds media understanding provider support.
|
||||
|
||||
- **[sglang](/plugins/reference/sglang)** (`@openclaw/sglang-provider`) - included in OpenClaw. Adds SGLang model provider support to OpenClaw.
|
||||
|
||||
- **[synthetic](/plugins/reference/synthetic)** (`@openclaw/synthetic-provider`) - included in OpenClaw. Adds Synthetic model provider support to OpenClaw.
|
||||
|
||||
- **[telegram](/plugins/reference/telegram)** (`@openclaw/telegram`) - included in OpenClaw. Adds the Telegram channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[together](/plugins/reference/together)** (`@openclaw/together-provider`) - included in OpenClaw. Adds Together model provider support to OpenClaw.
|
||||
|
||||
- **[tts-local-cli](/plugins/reference/tts-local-cli)** (`@openclaw/tts-local-cli`) - included in OpenClaw. Adds text-to-speech provider support.
|
||||
|
||||
- **[vllm](/plugins/reference/vllm)** (`@openclaw/vllm-provider`) - included in OpenClaw. Adds vLLM model provider support to OpenClaw.
|
||||
|
||||
- **[volcengine](/plugins/reference/volcengine)** (`@openclaw/volcengine-provider`) - included in OpenClaw. Adds Volcengine, Volcengine Plan model provider support to OpenClaw.
|
||||
|
||||
- **[voyage](/plugins/reference/voyage)** (`@openclaw/voyage-provider`) - included in OpenClaw. Adds memory embedding provider support.
|
||||
|
||||
- **[vydra](/plugins/reference/vydra)** (`@openclaw/vydra-provider`) - included in OpenClaw. Adds Vydra model provider support to OpenClaw.
|
||||
|
||||
- **[web-readability](/plugins/reference/web-readability)** (`@openclaw/web-readability-plugin`) - included in OpenClaw. Extract readable article content from local HTML web fetch responses.
|
||||
|
||||
- **[webhooks](/plugins/reference/webhooks)** (`@openclaw/webhooks`) - included in OpenClaw. Authenticated inbound webhooks that bind external automation to OpenClaw TaskFlows.
|
||||
|
||||
- **[workboard](/plugins/reference/workboard)** (`@openclaw/workboard`) - included in OpenClaw. Dashboard workboard for agent-owned issues and sessions.
|
||||
|
||||
- **[xai](/plugins/reference/xai)** (`@openclaw/xai-plugin`) - included in OpenClaw. Adds xAI model provider support to OpenClaw.
|
||||
|
||||
- **[xiaomi](/plugins/reference/xiaomi)** (`@openclaw/xiaomi-provider`) - included in OpenClaw. Adds Xiaomi, Xiaomi Token Plan model provider support to OpenClaw.
|
||||
|
||||
## Official external packages
|
||||
|
||||
68 plugins
|
||||
|
||||
- **[acpx](/plugins/reference/acpx)** (`@openclaw/acpx`) - npm; ClawHub. OpenClaw ACP runtime backend with plugin-owned session and transport management.
|
||||
|
||||
- **[amazon-bedrock](/plugins/reference/amazon-bedrock)** (`@openclaw/amazon-bedrock-provider`) - npm; ClawHub. OpenClaw Amazon Bedrock provider plugin with model discovery, embeddings, and guardrail support.
|
||||
|
||||
- **[amazon-bedrock-mantle](/plugins/reference/amazon-bedrock-mantle)** (`@openclaw/amazon-bedrock-mantle-provider`) - npm; ClawHub. OpenClaw Amazon Bedrock Mantle provider plugin for OpenAI-compatible model routing.
|
||||
|
||||
- **[anthropic-vertex](/plugins/reference/anthropic-vertex)** (`@openclaw/anthropic-vertex-provider`) - npm; ClawHub. OpenClaw Anthropic Vertex provider plugin for Claude models on Google Vertex AI.
|
||||
|
||||
- **[arcee](/plugins/reference/arcee)** (`@openclaw/arcee-provider`) - npm; ClawHub: `clawhub:@openclaw/arcee-provider`. Adds Arcee model provider support to OpenClaw.
|
||||
|
||||
- **[brave](/plugins/reference/brave)** (`@openclaw/brave-plugin`) - npm; ClawHub. OpenClaw Brave Search provider plugin for web search.
|
||||
|
||||
- **[cerebras](/plugins/reference/cerebras)** (`@openclaw/cerebras-provider`) - npm; ClawHub: `clawhub:@openclaw/cerebras-provider`. Adds Cerebras model provider support to OpenClaw.
|
||||
|
||||
- **[chutes](/plugins/reference/chutes)** (`@openclaw/chutes-provider`) - npm; ClawHub: `clawhub:@openclaw/chutes-provider`. Adds Chutes model provider support to OpenClaw.
|
||||
|
||||
- **[clickclack](/plugins/reference/clickclack)** (`@openclaw/clickclack`) - npm; ClawHub: `clawhub:@openclaw/clickclack`. Adds the Clickclack channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[cloudflare-ai-gateway](/plugins/reference/cloudflare-ai-gateway)** (`@openclaw/cloudflare-ai-gateway-provider`) - npm; ClawHub: `clawhub:@openclaw/cloudflare-ai-gateway-provider`. Adds Cloudflare AI Gateway model provider support to OpenClaw.
|
||||
|
||||
- **[codex](/plugins/reference/codex)** (`@openclaw/codex`) - npm; ClawHub. OpenClaw Codex app-server harness and model provider plugin with a Codex-managed GPT catalog.
|
||||
|
||||
- **[copilot](/plugins/reference/copilot)** (`@openclaw/copilot`) - npm; ClawHub: `clawhub:@openclaw/copilot`. Registers the GitHub Copilot agent runtime.
|
||||
|
||||
- **[deepinfra](/plugins/reference/deepinfra)** (`@openclaw/deepinfra-provider`) - npm; ClawHub: `clawhub:@openclaw/deepinfra-provider`. Adds DeepInfra model provider support to OpenClaw.
|
||||
|
||||
- **[deepseek](/plugins/reference/deepseek)** (`@openclaw/deepseek-provider`) - npm; ClawHub: `clawhub:@openclaw/deepseek-provider`. Adds DeepSeek model provider support to OpenClaw.
|
||||
|
||||
- **[diagnostics-otel](/plugins/reference/diagnostics-otel)** (`@openclaw/diagnostics-otel`) - npm; ClawHub: `clawhub:@openclaw/diagnostics-otel`. OpenClaw diagnostics OpenTelemetry exporter for metrics, traces, and logs.
|
||||
|
||||
- **[diagnostics-prometheus](/plugins/reference/diagnostics-prometheus)** (`@openclaw/diagnostics-prometheus`) - npm; ClawHub: `clawhub:@openclaw/diagnostics-prometheus`. OpenClaw diagnostics Prometheus exporter for runtime metrics.
|
||||
|
||||
- **[diffs](/plugins/reference/diffs)** (`@openclaw/diffs`) - npm; ClawHub. OpenClaw read-only diff viewer plugin and file renderer for agents.
|
||||
|
||||
- **[diffs-language-pack](/plugins/reference/diffs-language-pack)** (`@openclaw/diffs-language-pack`) - npm; ClawHub: `clawhub:@openclaw/diffs-language-pack`. Adds syntax highlighting for languages outside the default diffs viewer set.
|
||||
|
||||
- **[discord](/plugins/reference/discord)** (`@openclaw/discord`) - npm; ClawHub. OpenClaw Discord channel plugin for channels, DMs, commands, and app events.
|
||||
|
||||
- **[exa](/plugins/reference/exa)** (`@openclaw/exa-plugin`) - npm; ClawHub: `clawhub:@openclaw/exa-plugin`. Adds web search provider support.
|
||||
|
||||
- **[feishu](/plugins/reference/feishu)** (`@openclaw/feishu`) - npm; ClawHub. OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).
|
||||
|
||||
- **[firecrawl](/plugins/reference/firecrawl)** (`@openclaw/firecrawl-plugin`) - npm; ClawHub: `clawhub:@openclaw/firecrawl-plugin`. Adds agent-callable tools. Adds web fetch provider support. Adds web search provider support.
|
||||
|
||||
- **[fireworks](/plugins/reference/fireworks)** (`@openclaw/fireworks-provider`) - npm; ClawHub: `clawhub:@openclaw/fireworks-provider`. Adds Fireworks model provider support to OpenClaw.
|
||||
|
||||
- **[gmi](/plugins/reference/gmi)** (`@openclaw/gmi-provider`) - npm; ClawHub: `clawhub:@openclaw/gmi-provider`. OpenClaw GMI Cloud provider plugin.
|
||||
|
||||
- **[google-meet](/plugins/reference/google-meet)** (`@openclaw/google-meet`) - npm; ClawHub. OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.
|
||||
|
||||
- **[googlechat](/plugins/reference/googlechat)** (`@openclaw/googlechat`) - npm; ClawHub. OpenClaw Google Chat channel plugin for spaces and direct messages.
|
||||
|
||||
- **[gradium](/plugins/reference/gradium)** (`@openclaw/gradium-speech`) - npm; ClawHub: `clawhub:@openclaw/gradium-speech`. Adds text-to-speech provider support.
|
||||
|
||||
- **[groq](/plugins/reference/groq)** (`@openclaw/groq-provider`) - npm; ClawHub: `clawhub:@openclaw/groq-provider`. Adds Groq model provider support to OpenClaw.
|
||||
|
||||
- **[inworld](/plugins/reference/inworld)** (`@openclaw/inworld-speech`) - npm; ClawHub: `clawhub:@openclaw/inworld-speech`. Inworld streaming text-to-speech (MP3, OGG_OPUS, PCM telephony).
|
||||
|
||||
- **[irc](/plugins/reference/irc)** (`@openclaw/irc`) - npm; ClawHub: `clawhub:@openclaw/irc`. Adds the IRC channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[kilocode](/plugins/reference/kilocode)** (`@openclaw/kilocode-provider`) - npm; ClawHub: `clawhub:@openclaw/kilocode-provider`. Adds Kilocode model provider support to OpenClaw.
|
||||
|
||||
- **[kimi](/plugins/reference/kimi)** (`@openclaw/kimi-provider`) - npm; ClawHub: `clawhub:@openclaw/kimi-provider`. Adds Kimi, Kimi Coding model provider support to OpenClaw.
|
||||
|
||||
- **[line](/plugins/reference/line)** (`@openclaw/line`) - npm; ClawHub. OpenClaw LINE channel plugin for LINE Bot API chats.
|
||||
|
||||
- **[llama-cpp](/plugins/reference/llama-cpp)** (`@openclaw/llama-cpp-provider`) - npm; ClawHub. Local GGUF embeddings through node-llama-cpp.
|
||||
|
||||
- **[lobster](/plugins/reference/lobster)** (`@openclaw/lobster`) - npm; ClawHub. Lobster workflow tool plugin for typed pipelines and resumable approvals.
|
||||
|
||||
- **[matrix](/plugins/reference/matrix)** (`@openclaw/matrix`) - ClawHub: `clawhub:@openclaw/matrix`; npm. OpenClaw Matrix channel plugin for rooms and direct messages.
|
||||
|
||||
- **[mattermost](/plugins/reference/mattermost)** (`@openclaw/mattermost`) - npm; ClawHub: `clawhub:@openclaw/mattermost`. Adds the Mattermost channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[memory-lancedb](/plugins/reference/memory-lancedb)** (`@openclaw/memory-lancedb`) - npm; ClawHub. OpenClaw LanceDB-backed long-term memory plugin with auto-recall, auto-capture, and vector search.
|
||||
|
||||
- **[moonshot](/plugins/reference/moonshot)** (`@openclaw/moonshot-provider`) - npm; ClawHub: `clawhub:@openclaw/moonshot-provider`. Adds Moonshot model provider support to OpenClaw.
|
||||
|
||||
- **[msteams](/plugins/reference/msteams)** (`@openclaw/msteams`) - npm; ClawHub. OpenClaw Microsoft Teams channel plugin for bot conversations.
|
||||
|
||||
- **[nextcloud-talk](/plugins/reference/nextcloud-talk)** (`@openclaw/nextcloud-talk`) - npm; ClawHub. OpenClaw Nextcloud Talk channel plugin for conversations.
|
||||
|
||||
- **[nostr](/plugins/reference/nostr)** (`@openclaw/nostr`) - npm; ClawHub. OpenClaw Nostr channel plugin for NIP-04 encrypted direct messages.
|
||||
|
||||
- **[openshell](/plugins/reference/openshell)** (`@openclaw/openshell-sandbox`) - npm; ClawHub. OpenClaw sandbox backend for the NVIDIA OpenShell CLI with mirrored local workspaces and SSH command execution.
|
||||
|
||||
- **[parallel](/tools/parallel-search)** (`@openclaw/parallel-plugin`) - npm; ClawHub: `clawhub:@openclaw/parallel-plugin`. Adds web search provider support.
|
||||
|
||||
- **[perplexity](/plugins/reference/perplexity)** (`@openclaw/perplexity-plugin`) - npm; ClawHub: `clawhub:@openclaw/perplexity-plugin`. Adds web search provider support.
|
||||
|
||||
- **[pixverse](/plugins/reference/pixverse)** (`@openclaw/pixverse-provider`) - npm; ClawHub: `clawhub:@openclaw/pixverse-provider`. OpenClaw PixVerse video generation provider plugin.
|
||||
|
||||
- **[qianfan](/plugins/reference/qianfan)** (`@openclaw/qianfan-provider`) - npm; ClawHub: `clawhub:@openclaw/qianfan-provider`. Adds Qianfan model provider support to OpenClaw.
|
||||
|
||||
- **[qqbot](/plugins/reference/qqbot)** (`@openclaw/qqbot`) - npm; ClawHub. OpenClaw QQ Bot channel plugin for group and direct-message workflows.
|
||||
|
||||
- **[qwen](/plugins/reference/qwen)** (`@openclaw/qwen-provider`) - npm; ClawHub: `clawhub:@openclaw/qwen-provider`. Adds Qwen, Qwen Cloud, Model Studio, DashScope, Qwen Oauth, Qwen Portal, Qwen CLI model provider support to OpenClaw.
|
||||
|
||||
- **[raft](/plugins/reference/raft)** (`@openclaw/raft`) - npm; ClawHub. OpenClaw Raft channel plugin for secure CLI wake bridges.
|
||||
|
||||
- **[searxng](/plugins/reference/searxng)** (`@openclaw/searxng-plugin`) - npm; ClawHub: `clawhub:@openclaw/searxng-plugin`. Adds web search provider support.
|
||||
|
||||
- **[signal](/plugins/reference/signal)** (`@openclaw/signal`) - npm; ClawHub: `clawhub:@openclaw/signal`. Adds the Signal channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[slack](/plugins/reference/slack)** (`@openclaw/slack`) - npm; ClawHub. OpenClaw Slack channel plugin for channels, DMs, commands, and app events.
|
||||
|
||||
- **[sms](/plugins/reference/sms)** (`@openclaw/sms`) - npm; ClawHub: `clawhub:@openclaw/sms`. Twilio SMS channel plugin for OpenClaw text messages.
|
||||
|
||||
- **[stepfun](/plugins/reference/stepfun)** (`@openclaw/stepfun-provider`) - npm; ClawHub: `clawhub:@openclaw/stepfun-provider`. Adds StepFun, StepFun Plan model provider support to OpenClaw.
|
||||
|
||||
- **[synology-chat](/plugins/reference/synology-chat)** (`@openclaw/synology-chat`) - npm; ClawHub. Synology Chat channel plugin for OpenClaw channels and direct messages.
|
||||
|
||||
- **[tavily](/plugins/reference/tavily)** (`@openclaw/tavily-plugin`) - npm; ClawHub: `clawhub:@openclaw/tavily-plugin`. Adds agent-callable tools. Adds web search provider support.
|
||||
|
||||
- **[tencent](/plugins/reference/tencent)** (`@openclaw/tencent-provider`) - npm; ClawHub: `clawhub:@openclaw/tencent-provider`. Adds Tencent TokenHub model provider support to OpenClaw.
|
||||
|
||||
- **[tlon](/plugins/reference/tlon)** (`@openclaw/tlon`) - npm; ClawHub. OpenClaw Tlon/Urbit channel plugin for chat workflows.
|
||||
|
||||
- **[tokenjuice](/plugins/reference/tokenjuice)** (`@openclaw/tokenjuice`) - npm; ClawHub: `clawhub:@openclaw/tokenjuice`. Compacts exec and bash tool results with tokenjuice reducers.
|
||||
|
||||
- **[twitch](/plugins/reference/twitch)** (`@openclaw/twitch`) - npm; ClawHub. OpenClaw Twitch channel plugin for chat and moderation workflows.
|
||||
|
||||
- **[venice](/plugins/reference/venice)** (`@openclaw/venice-provider`) - npm; ClawHub: `clawhub:@openclaw/venice-provider`. Adds Venice model provider support to OpenClaw.
|
||||
|
||||
- **[vercel-ai-gateway](/plugins/reference/vercel-ai-gateway)** (`@openclaw/vercel-ai-gateway-provider`) - npm; ClawHub: `clawhub:@openclaw/vercel-ai-gateway-provider`. Adds Vercel AI Gateway model provider support to OpenClaw.
|
||||
|
||||
- **[voice-call](/plugins/reference/voice-call)** (`@openclaw/voice-call`) - npm; ClawHub. OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.
|
||||
|
||||
- **[whatsapp](/plugins/reference/whatsapp)** (`@openclaw/whatsapp`) - ClawHub: `clawhub:@openclaw/whatsapp`; npm. OpenClaw WhatsApp channel plugin for WhatsApp Web chats.
|
||||
|
||||
- **[zai](/plugins/reference/zai)** (`@openclaw/zai-provider`) - npm; ClawHub: `clawhub:@openclaw/zai-provider`. Adds Z.AI model provider support to OpenClaw.
|
||||
|
||||
- **[zalo](/plugins/reference/zalo)** (`@openclaw/zalo`) - npm; ClawHub. OpenClaw Zalo channel plugin for bot and webhook chats.
|
||||
|
||||
- **[zalouser](/plugins/reference/zalouser)** (`@openclaw/zalouser`) - npm; ClawHub. OpenClaw Zalo Personal Account plugin via native zca-js integration.
|
||||
|
||||
## Source checkout only
|
||||
|
||||
3 plugins
|
||||
|
||||
- **[qa-channel](/plugins/reference/qa-channel)** (`@openclaw/qa-channel`) - source checkout only. Adds the QA Channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
- **[qa-lab](/plugins/reference/qa-lab)** (`@openclaw/qa-lab`) - source checkout only. OpenClaw QA lab plugin with private debugger UI and scenario runner.
|
||||
|
||||
- **[qa-matrix](/plugins/reference/qa-matrix)** (`@openclaw/qa-matrix`) - source checkout only. Matrix QA transport runner and substrate.
|
||||
195
docs/plugins/plugin-permission-requests.md
Normal file
195
docs/plugins/plugin-permission-requests.md
Normal file
@@ -0,0 +1,195 @@
|
||||
---
|
||||
summary: "Ask users to approve plugin tool calls and plugin-owned permission prompts"
|
||||
title: "Plugin permission requests"
|
||||
sidebarTitle: "Permission requests"
|
||||
read_when:
|
||||
- You need a plugin hook or tool to ask before a side effect runs
|
||||
- You need to configure where plugin approval prompts are delivered
|
||||
- You are deciding between optional tools, exec approvals, and plugin approvals
|
||||
---
|
||||
|
||||
Plugin permission requests let plugin code pause a tool call or plugin-owned
|
||||
operation until a user approves or denies it. They use the Gateway
|
||||
`plugin.approval.*` flow and the same approval UI surfaces that handle chat
|
||||
approval buttons and `/approve` commands.
|
||||
|
||||
Use plugin permission requests for plugin/app permissions. They do not replace
|
||||
host exec approvals, optional tool allowlists, or Codex's native permission
|
||||
review.
|
||||
|
||||
## Choose the right gate
|
||||
|
||||
Pick the gate that matches the decision point you need:
|
||||
|
||||
| Gate | Use it when | What it controls |
|
||||
| -------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| Optional tools | A tool should not be visible to the model until the user opts in. | Tool exposure through `tools.allow`. |
|
||||
| Plugin permission requests | A plugin hook or plugin-owned operation must ask before one action runs. | Runtime approval through `plugin.approval.*`. |
|
||||
| Exec approvals | A host command or shell-like tool needs operator approval. | Host exec policy and durable exec allowlists. |
|
||||
| Codex native permission requests | Codex asks before native shell, file, MCP, or app-server actions. | Codex app-server or native hook approval handling, routed through plugin approvals when OpenClaw owns the prompt. |
|
||||
| MCP approval elicitations | A Codex MCP server requests approval for a tool call. | MCP approval responses bridged through OpenClaw plugin approvals. |
|
||||
|
||||
Optional tools are a discovery-time gate. Plugin permission requests are a
|
||||
per-call gate. Use both when a sensitive tool should require explicit opt-in
|
||||
before the model can see it and approval before the action runs.
|
||||
|
||||
## Request approval before a tool call
|
||||
|
||||
Most plugin-authored prompts should start in a `before_tool_call` hook. The hook
|
||||
runs after the model selects a tool and before OpenClaw executes it:
|
||||
|
||||
```typescript
|
||||
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
export default definePluginEntry({
|
||||
id: "deploy-policy",
|
||||
name: "Deploy Policy",
|
||||
register(api) {
|
||||
api.on("before_tool_call", async (event) => {
|
||||
if (event.toolName !== "deploy_service") {
|
||||
return;
|
||||
}
|
||||
|
||||
const environment =
|
||||
typeof event.params.environment === "string" ? event.params.environment : "unknown";
|
||||
|
||||
return {
|
||||
requireApproval: {
|
||||
title: "Deploy service",
|
||||
description: `Deploy service to ${environment}.`,
|
||||
severity: environment === "production" ? "critical" : "warning",
|
||||
allowedDecisions:
|
||||
environment === "production"
|
||||
? ["allow-once", "deny"]
|
||||
: ["allow-once", "allow-always", "deny"],
|
||||
timeoutMs: 120_000,
|
||||
timeoutBehavior: "deny",
|
||||
onResolution(decision) {
|
||||
console.log(`deploy approval resolved: ${decision}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Write prompt text for the person who will approve the action:
|
||||
|
||||
- Keep `title` short and action-focused; the Gateway caps it at 80 characters.
|
||||
- Keep `description` specific and bounded; the Gateway caps it at 256
|
||||
characters.
|
||||
- Include the action, target, and risk. Do not include secrets, tokens, or
|
||||
private payloads that should not appear in chat approval surfaces.
|
||||
- `severity` defaults to `"warning"` when omitted. Use `"critical"` only for
|
||||
actions where the wrong decision could cause production damage or data loss.
|
||||
- `allowedDecisions` defaults to `["allow-once", "allow-always", "deny"]` when
|
||||
omitted. Pass `["allow-once", "deny"]` when persistent trust is unsafe for
|
||||
that action.
|
||||
- `timeoutMs` defaults to 120000 (2 minutes) and is capped at 600000 (10
|
||||
minutes) regardless of the requested value.
|
||||
|
||||
## Decision behavior
|
||||
|
||||
OpenClaw creates a pending approval with a `plugin:` ID, delivers it to the
|
||||
available approval surfaces, and waits for a decision.
|
||||
|
||||
| Decision | Result |
|
||||
| ----------------- | ------------------------------------------------------------------------- |
|
||||
| `allow-once` | The current call continues. |
|
||||
| `allow-always` | The current call continues and the decision is passed to the plugin. |
|
||||
| `deny` | The call is blocked with a denied tool result. |
|
||||
| Timeout | The call is blocked unless `timeoutBehavior` is `"allow"`. |
|
||||
| Cancellation | The call is blocked when the run is aborted. |
|
||||
| No approval route | The call is blocked because no connected approval surface can resolve it. |
|
||||
|
||||
`allow-always` is only durable when the requesting plugin or runtime implements
|
||||
that persistence. For ordinary `before_tool_call.requireApproval` hooks,
|
||||
OpenClaw treats `allow-once` and `allow-always` as approval decisions for the
|
||||
current call and passes the resolved value to `onResolution`. If your plugin
|
||||
offers `allow-always`, document and implement exactly what future calls it
|
||||
trusts.
|
||||
|
||||
If the hook also returns `params`, OpenClaw applies those parameter changes only
|
||||
after the approval succeeds. A lower-priority hook can still block after a
|
||||
higher-priority hook requested approval.
|
||||
|
||||
`allowedDecisions` limits the buttons and commands shown to the user. The
|
||||
Gateway rejects a resolve attempt for any decision the request did not offer.
|
||||
|
||||
## Route approval prompts
|
||||
|
||||
Approval prompts can resolve in local UI surfaces or in chat channels that
|
||||
support approval handling. To forward plugin approval prompts to explicit chat
|
||||
targets, configure `approvals.plugin`:
|
||||
|
||||
```json5
|
||||
{
|
||||
approvals: {
|
||||
plugin: {
|
||||
enabled: true,
|
||||
mode: "targets",
|
||||
agentFilter: ["main"],
|
||||
targets: [{ channel: "slack", to: "U12345678" }],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
`approvals.plugin` is independent from `approvals.exec`. Enabling exec approval
|
||||
forwarding does not route plugin approval prompts, and enabling plugin approval
|
||||
forwarding does not change host exec policy.
|
||||
|
||||
When a prompt includes manual approval text, resolve it with one of the offered
|
||||
decisions:
|
||||
|
||||
```text
|
||||
/approve <id> allow-once
|
||||
/approve <id> allow-always
|
||||
/approve <id> deny
|
||||
```
|
||||
|
||||
See [Advanced exec approvals](/tools/exec-approvals-advanced#plugin-approval-forwarding)
|
||||
for the full forwarding model, same-chat approval behavior, native channel
|
||||
delivery, and channel-specific approver rules.
|
||||
|
||||
## Codex native permissions
|
||||
|
||||
Codex native permission prompts can also travel through plugin approvals, but
|
||||
they have different ownership than plugin-authored hooks.
|
||||
|
||||
- Codex app-server approval requests route through OpenClaw after Codex review.
|
||||
- The native hook `permission_request` relay can ask through
|
||||
`plugin.approval.request` when that relay is enabled.
|
||||
- MCP tool approval elicitations route through plugin approvals when Codex marks
|
||||
`_meta.codex_approval_kind` as `"mcp_tool_call"`.
|
||||
|
||||
See [Codex harness runtime](/plugins/codex-harness-runtime#native-permissions-and-mcp-elicitations)
|
||||
for the Codex-specific behavior and fallback rules.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**The tool says plugin approvals are unavailable.** No approval UI or configured
|
||||
approval route accepted the request. Connect an approval-capable client, use a
|
||||
channel that supports same-chat `/approve`, or configure `approvals.plugin`.
|
||||
|
||||
**`allow-always` appears but the next call prompts again.** The generic plugin
|
||||
approval flow does not automatically persist trust for arbitrary hooks. Persist
|
||||
plugin-owned trust in your plugin after `onResolution("allow-always")`, or
|
||||
offer only `allow-once` and `deny`.
|
||||
|
||||
**`/approve` rejects the decision.** The request restricted
|
||||
`allowedDecisions`. Use one of the decisions printed in the prompt.
|
||||
|
||||
**A Discord, Matrix, Slack, or Telegram prompt routes differently from exec
|
||||
approvals.** Plugin approvals and exec approvals use separate config and may use
|
||||
different authorization checks. Verify `approvals.plugin` and the channel's
|
||||
plugin approval support instead of only checking `approvals.exec`.
|
||||
|
||||
## Related
|
||||
|
||||
- [Plugin hooks](/plugins/hooks#tool-call-policy)
|
||||
- [Building plugins](/plugins/building-plugins#registering-tools)
|
||||
- [Advanced exec approvals](/tools/exec-approvals-advanced#plugin-approval-forwarding)
|
||||
- [Gateway protocol](/gateway/protocol)
|
||||
- [Codex harness runtime](/plugins/codex-harness-runtime#native-permissions-and-mcp-elicitations)
|
||||
19
docs/plugins/reference.md
Normal file
19
docs/plugins/reference.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Generated index of OpenClaw plugin reference pages"
|
||||
read_when:
|
||||
- You need a reference page for a specific OpenClaw plugin
|
||||
- You are auditing plugin docs coverage
|
||||
title: "Plugin reference"
|
||||
---
|
||||
|
||||
# Plugin reference
|
||||
|
||||
This page is generated from `extensions/*/package.json` and
|
||||
`openclaw.plugin.json`. Regenerate it with:
|
||||
|
||||
```bash
|
||||
pnpm plugins:inventory:gen
|
||||
```
|
||||
|
||||
Use [Plugin inventory](/plugins/plugin-inventory) to browse all 130
|
||||
generated plugin reference pages by distribution, package, and description.
|
||||
23
docs/plugins/reference/acpx.md
Normal file
23
docs/plugins/reference/acpx.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw ACP runtime backend with plugin-owned session and transport management."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the acpx plugin
|
||||
title: "ACPx plugin"
|
||||
---
|
||||
|
||||
# ACPx plugin
|
||||
|
||||
OpenClaw ACP runtime backend with plugin-owned session and transport management.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/acpx`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
skills
|
||||
|
||||
## Related docs
|
||||
|
||||
- [acpx](/tools/acp-agents-setup)
|
||||
23
docs/plugins/reference/admin-http-rpc.md
Normal file
23
docs/plugins/reference/admin-http-rpc.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw admin HTTP RPC endpoint."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the admin-http-rpc plugin
|
||||
title: "Admin Http Rpc plugin"
|
||||
---
|
||||
|
||||
# Admin Http Rpc plugin
|
||||
|
||||
OpenClaw admin HTTP RPC endpoint.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/admin-http-rpc`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: gatewayMethodDispatch
|
||||
|
||||
## Related docs
|
||||
|
||||
- [admin-http-rpc](/plugins/admin-http-rpc)
|
||||
23
docs/plugins/reference/alibaba.md
Normal file
23
docs/plugins/reference/alibaba.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds video generation provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the alibaba plugin
|
||||
title: "Alibaba plugin"
|
||||
---
|
||||
|
||||
# Alibaba plugin
|
||||
|
||||
Adds video generation provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/alibaba-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: videoGenerationProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [alibaba](/providers/alibaba)
|
||||
23
docs/plugins/reference/amazon-bedrock-mantle.md
Normal file
23
docs/plugins/reference/amazon-bedrock-mantle.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Amazon Bedrock Mantle provider plugin for OpenAI-compatible model routing."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the amazon-bedrock-mantle plugin
|
||||
title: "Amazon Bedrock Mantle plugin"
|
||||
---
|
||||
|
||||
# Amazon Bedrock Mantle plugin
|
||||
|
||||
OpenClaw Amazon Bedrock Mantle provider plugin for OpenAI-compatible model routing.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/amazon-bedrock-mantle-provider`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
providers: amazon-bedrock-mantle
|
||||
|
||||
## Related docs
|
||||
|
||||
- [amazon-bedrock-mantle](/providers/bedrock-mantle)
|
||||
23
docs/plugins/reference/amazon-bedrock.md
Normal file
23
docs/plugins/reference/amazon-bedrock.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Amazon Bedrock provider plugin with model discovery, embeddings, and guardrail support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the amazon-bedrock plugin
|
||||
title: "Amazon Bedrock plugin"
|
||||
---
|
||||
|
||||
# Amazon Bedrock plugin
|
||||
|
||||
OpenClaw Amazon Bedrock provider plugin with model discovery, embeddings, and guardrail support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/amazon-bedrock-provider`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
providers: amazon-bedrock; contracts: memoryEmbeddingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [amazon-bedrock](/providers/bedrock)
|
||||
29
docs/plugins/reference/anthropic-vertex.md
Normal file
29
docs/plugins/reference/anthropic-vertex.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
summary: "OpenClaw Anthropic Vertex provider plugin for Claude models on Google Vertex AI."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the anthropic-vertex plugin
|
||||
title: "Anthropic Vertex plugin"
|
||||
---
|
||||
|
||||
# Anthropic Vertex plugin
|
||||
|
||||
OpenClaw Anthropic Vertex provider plugin for Claude models on Google Vertex AI.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/anthropic-vertex-provider`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
providers: anthropic-vertex
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-start -->
|
||||
|
||||
## Claude Fable 5
|
||||
|
||||
Use `anthropic-vertex/claude-fable-5` where the model is available in your Google Cloud region.
|
||||
Fable 5 always uses adaptive thinking and defaults to `high` effort. `/think off` and
|
||||
`/think minimal` use `low` effort because the model does not support disabling thinking.
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-end -->
|
||||
23
docs/plugins/reference/anthropic.md
Normal file
23
docs/plugins/reference/anthropic.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Anthropic model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the anthropic plugin
|
||||
title: "Anthropic plugin"
|
||||
---
|
||||
|
||||
# Anthropic plugin
|
||||
|
||||
Adds Anthropic model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/anthropic-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: anthropic; contracts: mediaUnderstandingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [anthropic](/providers/anthropic)
|
||||
23
docs/plugins/reference/arcee.md
Normal file
23
docs/plugins/reference/arcee.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Arcee model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the arcee plugin
|
||||
title: "Arcee plugin"
|
||||
---
|
||||
|
||||
# Arcee plugin
|
||||
|
||||
Adds Arcee model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/arcee-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/arcee-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: arcee
|
||||
|
||||
## Related docs
|
||||
|
||||
- [arcee](/providers/arcee)
|
||||
23
docs/plugins/reference/azure-speech.md
Normal file
23
docs/plugins/reference/azure-speech.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Azure AI Speech text-to-speech (MP3, native Ogg/Opus voice notes, PCM telephony)."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the azure-speech plugin
|
||||
title: "Azure Speech plugin"
|
||||
---
|
||||
|
||||
# Azure Speech plugin
|
||||
|
||||
Azure AI Speech text-to-speech (MP3, native Ogg/Opus voice notes, PCM telephony).
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/azure-speech`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: speechProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [azure-speech](/providers/azure-speech)
|
||||
19
docs/plugins/reference/bonjour.md
Normal file
19
docs/plugins/reference/bonjour.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Advertise the local OpenClaw gateway over Bonjour/mDNS."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the bonjour plugin
|
||||
title: "Bonjour plugin"
|
||||
---
|
||||
|
||||
# Bonjour plugin
|
||||
|
||||
Advertise the local OpenClaw gateway over Bonjour/mDNS.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/bonjour`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
plugin
|
||||
23
docs/plugins/reference/brave.md
Normal file
23
docs/plugins/reference/brave.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Brave Search provider plugin for web search."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the brave plugin
|
||||
title: "Brave plugin"
|
||||
---
|
||||
|
||||
# Brave plugin
|
||||
|
||||
OpenClaw Brave Search provider plugin for web search.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/brave-plugin`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [brave](/tools/brave-search)
|
||||
23
docs/plugins/reference/browser.md
Normal file
23
docs/plugins/reference/browser.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds agent-callable tools."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the browser plugin
|
||||
title: "Browser plugin"
|
||||
---
|
||||
|
||||
# Browser plugin
|
||||
|
||||
Adds agent-callable tools.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/browser-plugin`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools; skills
|
||||
|
||||
## Related docs
|
||||
|
||||
- [browser](/tools/browser)
|
||||
19
docs/plugins/reference/byteplus.md
Normal file
19
docs/plugins/reference/byteplus.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Adds BytePlus, BytePlus Plan model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the byteplus plugin
|
||||
title: "BytePlus plugin"
|
||||
---
|
||||
|
||||
# BytePlus plugin
|
||||
|
||||
Adds BytePlus, BytePlus Plan model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/byteplus-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: byteplus, byteplus-plan; contracts: videoGenerationProviders
|
||||
19
docs/plugins/reference/canvas.md
Normal file
19
docs/plugins/reference/canvas.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Experimental Canvas control and A2UI rendering surfaces for paired nodes."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the canvas plugin
|
||||
title: "Canvas plugin"
|
||||
---
|
||||
|
||||
# Canvas plugin
|
||||
|
||||
Experimental Canvas control and A2UI rendering surfaces for paired nodes.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/canvas-plugin`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools; skills
|
||||
23
docs/plugins/reference/cerebras.md
Normal file
23
docs/plugins/reference/cerebras.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Cerebras model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the cerebras plugin
|
||||
title: "Cerebras plugin"
|
||||
---
|
||||
|
||||
# Cerebras plugin
|
||||
|
||||
Adds Cerebras model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/cerebras-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/cerebras-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: cerebras
|
||||
|
||||
## Related docs
|
||||
|
||||
- [cerebras](/providers/cerebras)
|
||||
23
docs/plugins/reference/chutes.md
Normal file
23
docs/plugins/reference/chutes.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Chutes model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the chutes plugin
|
||||
title: "Chutes plugin"
|
||||
---
|
||||
|
||||
# Chutes plugin
|
||||
|
||||
Adds Chutes model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/chutes-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/chutes-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: chutes
|
||||
|
||||
## Related docs
|
||||
|
||||
- [chutes](/providers/chutes)
|
||||
23
docs/plugins/reference/clawrouter.md
Normal file
23
docs/plugins/reference/clawrouter.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds ClawRouter model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the clawrouter plugin
|
||||
title: "ClawRouter plugin"
|
||||
---
|
||||
|
||||
# ClawRouter plugin
|
||||
|
||||
Adds ClawRouter model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/clawrouter`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: clawrouter
|
||||
|
||||
## Related docs
|
||||
|
||||
- [clawrouter](/providers/clawrouter)
|
||||
23
docs/plugins/reference/clickclack.md
Normal file
23
docs/plugins/reference/clickclack.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds the Clickclack channel surface for sending and receiving OpenClaw messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the clickclack plugin
|
||||
title: "Clickclack plugin"
|
||||
---
|
||||
|
||||
# Clickclack plugin
|
||||
|
||||
Adds the Clickclack channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/clickclack`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/clickclack`
|
||||
|
||||
## Surface
|
||||
|
||||
channels: clickclack
|
||||
|
||||
## Related docs
|
||||
|
||||
- [clickclack](/channels/clickclack)
|
||||
23
docs/plugins/reference/cloudflare-ai-gateway.md
Normal file
23
docs/plugins/reference/cloudflare-ai-gateway.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Cloudflare AI Gateway model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the cloudflare-ai-gateway plugin
|
||||
title: "Cloudflare AI Gateway plugin"
|
||||
---
|
||||
|
||||
# Cloudflare AI Gateway plugin
|
||||
|
||||
Adds Cloudflare AI Gateway model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/cloudflare-ai-gateway-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/cloudflare-ai-gateway-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: cloudflare-ai-gateway
|
||||
|
||||
## Related docs
|
||||
|
||||
- [cloudflare-ai-gateway](/providers/cloudflare-ai-gateway)
|
||||
27
docs/plugins/reference/codex-supervisor.md
Normal file
27
docs/plugins/reference/codex-supervisor.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
summary: "Supervise Codex app-server sessions from OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the codex-supervisor plugin
|
||||
title: "Codex Supervisor plugin"
|
||||
---
|
||||
|
||||
# Codex Supervisor plugin
|
||||
|
||||
Supervise Codex app-server sessions from OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/codex-supervisor`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-start -->
|
||||
|
||||
## Session Listing
|
||||
|
||||
`codex_sessions_list` defaults to loaded Codex sessions only. Set `include_stored` to include stored history; the plugin uses Codex app-server's state-DB-only listing path and caps stored results at 200 by default. Pass `max_stored_sessions` to lower or raise that cap, up to 1000.
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-end -->
|
||||
23
docs/plugins/reference/codex.md
Normal file
23
docs/plugins/reference/codex.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Codex app-server harness and model provider plugin with a Codex-managed GPT catalog."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the codex plugin
|
||||
title: "Codex plugin"
|
||||
---
|
||||
|
||||
# Codex plugin
|
||||
|
||||
OpenClaw Codex app-server harness and model provider plugin with a Codex-managed GPT catalog.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/codex`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
providers: codex; contracts: mediaUnderstandingProviders, migrationProviders, tools, webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [codex](/plugins/codex-harness)
|
||||
23
docs/plugins/reference/cohere.md
Normal file
23
docs/plugins/reference/cohere.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Cohere provider plugin."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the cohere plugin
|
||||
title: "Cohere plugin"
|
||||
---
|
||||
|
||||
# Cohere plugin
|
||||
|
||||
OpenClaw Cohere provider plugin.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/cohere-provider`
|
||||
- Install route: included in OpenClaw; npm; ClawHub: `clawhub:@openclaw/cohere-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: cohere
|
||||
|
||||
## Related docs
|
||||
|
||||
- [cohere](/providers/cohere)
|
||||
23
docs/plugins/reference/comfy.md
Normal file
23
docs/plugins/reference/comfy.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds ComfyUI model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the comfy plugin
|
||||
title: "ComfyUI plugin"
|
||||
---
|
||||
|
||||
# ComfyUI plugin
|
||||
|
||||
Adds ComfyUI model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/comfy-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: comfy; contracts: imageGenerationProviders, musicGenerationProviders, videoGenerationProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [comfy](/providers/comfy)
|
||||
19
docs/plugins/reference/copilot-proxy.md
Normal file
19
docs/plugins/reference/copilot-proxy.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Adds Copilot Proxy model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the copilot-proxy plugin
|
||||
title: "Copilot Proxy plugin"
|
||||
---
|
||||
|
||||
# Copilot Proxy plugin
|
||||
|
||||
Adds Copilot Proxy model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/copilot-proxy`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: copilot-proxy
|
||||
23
docs/plugins/reference/copilot.md
Normal file
23
docs/plugins/reference/copilot.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Registers the GitHub Copilot agent runtime."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the copilot plugin
|
||||
title: "Copilot plugin"
|
||||
---
|
||||
|
||||
# Copilot plugin
|
||||
|
||||
Registers the GitHub Copilot agent runtime.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/copilot`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/copilot`
|
||||
|
||||
## Surface
|
||||
|
||||
plugin
|
||||
|
||||
## Related docs
|
||||
|
||||
- [copilot](/plugins/copilot)
|
||||
23
docs/plugins/reference/deepgram.md
Normal file
23
docs/plugins/reference/deepgram.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds media understanding provider support. Adds realtime transcription provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the deepgram plugin
|
||||
title: "Deepgram plugin"
|
||||
---
|
||||
|
||||
# Deepgram plugin
|
||||
|
||||
Adds media understanding provider support. Adds realtime transcription provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/deepgram-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: mediaUnderstandingProviders, realtimeTranscriptionProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [deepgram](/providers/deepgram)
|
||||
23
docs/plugins/reference/deepinfra.md
Normal file
23
docs/plugins/reference/deepinfra.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds DeepInfra model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the deepinfra plugin
|
||||
title: "DeepInfra plugin"
|
||||
---
|
||||
|
||||
# DeepInfra plugin
|
||||
|
||||
Adds DeepInfra model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/deepinfra-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/deepinfra-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: deepinfra; contracts: imageGenerationProviders, mediaUnderstandingProviders, memoryEmbeddingProviders, speechProviders, videoGenerationProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [deepinfra](/providers/deepinfra)
|
||||
23
docs/plugins/reference/deepseek.md
Normal file
23
docs/plugins/reference/deepseek.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds DeepSeek model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the deepseek plugin
|
||||
title: "DeepSeek plugin"
|
||||
---
|
||||
|
||||
# DeepSeek plugin
|
||||
|
||||
Adds DeepSeek model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/deepseek-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/deepseek-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: deepseek
|
||||
|
||||
## Related docs
|
||||
|
||||
- [deepseek](/providers/deepseek)
|
||||
19
docs/plugins/reference/diagnostics-otel.md
Normal file
19
docs/plugins/reference/diagnostics-otel.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "OpenClaw diagnostics OpenTelemetry exporter for metrics, traces, and logs."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the diagnostics-otel plugin
|
||||
title: "Diagnostics OpenTelemetry plugin"
|
||||
---
|
||||
|
||||
# Diagnostics OpenTelemetry plugin
|
||||
|
||||
OpenClaw diagnostics OpenTelemetry exporter for metrics, traces, and logs.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/diagnostics-otel`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/diagnostics-otel`
|
||||
|
||||
## Surface
|
||||
|
||||
plugin
|
||||
19
docs/plugins/reference/diagnostics-prometheus.md
Normal file
19
docs/plugins/reference/diagnostics-prometheus.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "OpenClaw diagnostics Prometheus exporter for runtime metrics."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the diagnostics-prometheus plugin
|
||||
title: "Diagnostics Prometheus plugin"
|
||||
---
|
||||
|
||||
# Diagnostics Prometheus plugin
|
||||
|
||||
OpenClaw diagnostics Prometheus exporter for runtime metrics.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/diagnostics-prometheus`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/diagnostics-prometheus`
|
||||
|
||||
## Surface
|
||||
|
||||
plugin
|
||||
31
docs/plugins/reference/diffs-language-pack.md
Normal file
31
docs/plugins/reference/diffs-language-pack.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
summary: "Adds syntax highlighting for languages outside the default diffs viewer set."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the diffs-language-pack plugin
|
||||
title: "Diffs Language Pack plugin"
|
||||
---
|
||||
|
||||
# Diffs Language Pack plugin
|
||||
|
||||
Adds syntax highlighting for languages outside the default diffs viewer set.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/diffs-language-pack`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/diffs-language-pack`
|
||||
|
||||
## Surface
|
||||
|
||||
plugin
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-start -->
|
||||
|
||||
## Added languages
|
||||
|
||||
The base `diffs` plugin already highlights the common languages documented in [Diffs](/tools/diffs). Install this language pack when you want syntax highlighting for a broader set of Shiki-supported languages. If the pack is not installed, those files still render as readable plain text.
|
||||
|
||||
Examples include Astro, Vue, Svelte, MDX, GraphQL, Terraform/HCL, Nix, Clojure, Elixir, Haskell, OCaml, Scala, Zig, Solidity, Verilog/VHDL, Fortran, MATLAB, LaTeX, Mermaid, Sass/Less/SCSS, Nginx, Apache, CSV, dotenv, INI, and diff files.
|
||||
|
||||
See [Shiki languages](https://shiki.style/languages) for Shiki's upstream language and alias catalog.
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-end -->
|
||||
19
docs/plugins/reference/diffs.md
Normal file
19
docs/plugins/reference/diffs.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "OpenClaw read-only diff viewer plugin and file renderer for agents."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the diffs plugin
|
||||
title: "Diffs plugin"
|
||||
---
|
||||
|
||||
# Diffs plugin
|
||||
|
||||
OpenClaw read-only diff viewer plugin and file renderer for agents.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/diffs`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools; skills
|
||||
23
docs/plugins/reference/discord.md
Normal file
23
docs/plugins/reference/discord.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Discord channel plugin for channels, DMs, commands, and app events."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the discord plugin
|
||||
title: "Discord plugin"
|
||||
---
|
||||
|
||||
# Discord plugin
|
||||
|
||||
OpenClaw Discord channel plugin for channels, DMs, commands, and app events.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/discord`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: discord; contracts: transcriptSourceProviders; skills
|
||||
|
||||
## Related docs
|
||||
|
||||
- [discord](/channels/discord)
|
||||
23
docs/plugins/reference/document-extract.md
Normal file
23
docs/plugins/reference/document-extract.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Extract text and fallback page images from local document attachments."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the document-extract plugin
|
||||
title: "Document Extract plugin"
|
||||
---
|
||||
|
||||
# Document Extract plugin
|
||||
|
||||
Extract text and fallback page images from local document attachments.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/document-extract-plugin`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: documentExtractors
|
||||
|
||||
## Related docs
|
||||
|
||||
- [document-extract](/tools/pdf)
|
||||
23
docs/plugins/reference/duckduckgo.md
Normal file
23
docs/plugins/reference/duckduckgo.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds web search provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the duckduckgo plugin
|
||||
title: "DuckDuckGo plugin"
|
||||
---
|
||||
|
||||
# DuckDuckGo plugin
|
||||
|
||||
Adds web search provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/duckduckgo-plugin`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [duckduckgo](/tools/duckduckgo-search)
|
||||
23
docs/plugins/reference/elevenlabs.md
Normal file
23
docs/plugins/reference/elevenlabs.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds media understanding provider support. Adds realtime transcription provider support. Adds text-to-speech provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the elevenlabs plugin
|
||||
title: "Elevenlabs plugin"
|
||||
---
|
||||
|
||||
# Elevenlabs plugin
|
||||
|
||||
Adds media understanding provider support. Adds realtime transcription provider support. Adds text-to-speech provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/elevenlabs-speech`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: mediaUnderstandingProviders, realtimeTranscriptionProviders, speechProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [elevenlabs](/providers/elevenlabs)
|
||||
23
docs/plugins/reference/exa.md
Normal file
23
docs/plugins/reference/exa.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds web search provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the exa plugin
|
||||
title: "Exa plugin"
|
||||
---
|
||||
|
||||
# Exa plugin
|
||||
|
||||
Adds web search provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/exa-plugin`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/exa-plugin`
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [exa](/tools/exa-search)
|
||||
23
docs/plugins/reference/fal.md
Normal file
23
docs/plugins/reference/fal.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds fal model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the fal plugin
|
||||
title: "fal plugin"
|
||||
---
|
||||
|
||||
# fal plugin
|
||||
|
||||
Adds fal model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/fal-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: fal; contracts: imageGenerationProviders, musicGenerationProviders, videoGenerationProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [fal](/providers/fal)
|
||||
23
docs/plugins/reference/feishu.md
Normal file
23
docs/plugins/reference/feishu.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng)."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the feishu plugin
|
||||
title: "Feishu plugin"
|
||||
---
|
||||
|
||||
# Feishu plugin
|
||||
|
||||
OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/feishu`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: feishu; contracts: tools; skills
|
||||
|
||||
## Related docs
|
||||
|
||||
- [feishu](/channels/feishu)
|
||||
19
docs/plugins/reference/file-transfer.md
Normal file
19
docs/plugins/reference/file-transfer.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Fetch, list, and write files on paired nodes via dedicated node commands. Bypasses bash stdout truncation by using base64 over node.invoke for binaries up to 16 MB."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the file-transfer plugin
|
||||
title: "File Transfer plugin"
|
||||
---
|
||||
|
||||
# File Transfer plugin
|
||||
|
||||
Fetch, list, and write files on paired nodes via dedicated node commands. Bypasses bash stdout truncation by using base64 over node.invoke for binaries up to 16 MB.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/file-transfer`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
23
docs/plugins/reference/firecrawl.md
Normal file
23
docs/plugins/reference/firecrawl.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds agent-callable tools. Adds web fetch provider support. Adds web search provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the firecrawl plugin
|
||||
title: "Firecrawl plugin"
|
||||
---
|
||||
|
||||
# Firecrawl plugin
|
||||
|
||||
Adds agent-callable tools. Adds web fetch provider support. Adds web search provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/firecrawl-plugin`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/firecrawl-plugin`
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools, webFetchProviders, webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [firecrawl](/tools/firecrawl)
|
||||
23
docs/plugins/reference/fireworks.md
Normal file
23
docs/plugins/reference/fireworks.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Fireworks model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the fireworks plugin
|
||||
title: "Fireworks plugin"
|
||||
---
|
||||
|
||||
# Fireworks plugin
|
||||
|
||||
Adds Fireworks model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/fireworks-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/fireworks-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: fireworks
|
||||
|
||||
## Related docs
|
||||
|
||||
- [fireworks](/providers/fireworks)
|
||||
23
docs/plugins/reference/github-copilot.md
Normal file
23
docs/plugins/reference/github-copilot.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds GitHub Copilot model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the github-copilot plugin
|
||||
title: "GitHub Copilot plugin"
|
||||
---
|
||||
|
||||
# GitHub Copilot plugin
|
||||
|
||||
Adds GitHub Copilot model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/github-copilot-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: github-copilot; contracts: memoryEmbeddingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [github-copilot](/providers/github-copilot)
|
||||
23
docs/plugins/reference/gmi.md
Normal file
23
docs/plugins/reference/gmi.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw GMI Cloud provider plugin."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the gmi plugin
|
||||
title: "Gmi plugin"
|
||||
---
|
||||
|
||||
# Gmi plugin
|
||||
|
||||
OpenClaw GMI Cloud provider plugin.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/gmi-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/gmi-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: gmi, gmi-cloud, gmicloud
|
||||
|
||||
## Related docs
|
||||
|
||||
- [gmi](/providers/gmi)
|
||||
23
docs/plugins/reference/google-meet.md
Normal file
23
docs/plugins/reference/google-meet.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the google-meet plugin
|
||||
title: "Google Meet plugin"
|
||||
---
|
||||
|
||||
# Google Meet plugin
|
||||
|
||||
OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/google-meet`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
|
||||
## Related docs
|
||||
|
||||
- [google-meet](/plugins/google-meet)
|
||||
23
docs/plugins/reference/google.md
Normal file
23
docs/plugins/reference/google.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Google, Google Gemini CLI, Google Vertex model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the google plugin
|
||||
title: "Google plugin"
|
||||
---
|
||||
|
||||
# Google plugin
|
||||
|
||||
Adds Google, Google Gemini CLI, Google Vertex model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/google-plugin`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: google, google-gemini-cli, google-vertex; contracts: imageGenerationProviders, mediaUnderstandingProviders, memoryEmbeddingProviders, musicGenerationProviders, realtimeVoiceProviders, speechProviders, videoGenerationProviders, webSearchProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [google](/providers/google)
|
||||
23
docs/plugins/reference/googlechat.md
Normal file
23
docs/plugins/reference/googlechat.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Google Chat channel plugin for spaces and direct messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the googlechat plugin
|
||||
title: "Google Chat plugin"
|
||||
---
|
||||
|
||||
# Google Chat plugin
|
||||
|
||||
OpenClaw Google Chat channel plugin for spaces and direct messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/googlechat`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: googlechat
|
||||
|
||||
## Related docs
|
||||
|
||||
- [googlechat](/channels/googlechat)
|
||||
23
docs/plugins/reference/gradium.md
Normal file
23
docs/plugins/reference/gradium.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds text-to-speech provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the gradium plugin
|
||||
title: "Gradium plugin"
|
||||
---
|
||||
|
||||
# Gradium plugin
|
||||
|
||||
Adds text-to-speech provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/gradium-speech`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/gradium-speech`
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: speechProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [gradium](/providers/gradium)
|
||||
23
docs/plugins/reference/groq.md
Normal file
23
docs/plugins/reference/groq.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Groq model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the groq plugin
|
||||
title: "Groq plugin"
|
||||
---
|
||||
|
||||
# Groq plugin
|
||||
|
||||
Adds Groq model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/groq-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/groq-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: groq; contracts: mediaUnderstandingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [groq](/providers/groq)
|
||||
23
docs/plugins/reference/huggingface.md
Normal file
23
docs/plugins/reference/huggingface.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Hugging Face model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the huggingface plugin
|
||||
title: "Hugging Face plugin"
|
||||
---
|
||||
|
||||
# Hugging Face plugin
|
||||
|
||||
Adds Hugging Face model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/huggingface-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: huggingface
|
||||
|
||||
## Related docs
|
||||
|
||||
- [huggingface](/providers/huggingface)
|
||||
23
docs/plugins/reference/imessage.md
Normal file
23
docs/plugins/reference/imessage.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds the iMessage channel surface for sending and receiving OpenClaw messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the imessage plugin
|
||||
title: "iMessage plugin"
|
||||
---
|
||||
|
||||
# iMessage plugin
|
||||
|
||||
Adds the iMessage channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/imessage`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
channels: imessage
|
||||
|
||||
## Related docs
|
||||
|
||||
- [imessage](/channels/imessage)
|
||||
23
docs/plugins/reference/inworld.md
Normal file
23
docs/plugins/reference/inworld.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Inworld streaming text-to-speech (MP3, OGG_OPUS, PCM telephony)."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the inworld plugin
|
||||
title: "Inworld plugin"
|
||||
---
|
||||
|
||||
# Inworld plugin
|
||||
|
||||
Inworld streaming text-to-speech (MP3, OGG_OPUS, PCM telephony).
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/inworld-speech`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/inworld-speech`
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: speechProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [inworld](/providers/inworld)
|
||||
23
docs/plugins/reference/irc.md
Normal file
23
docs/plugins/reference/irc.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds the IRC channel surface for sending and receiving OpenClaw messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the irc plugin
|
||||
title: "IRC plugin"
|
||||
---
|
||||
|
||||
# IRC plugin
|
||||
|
||||
Adds the IRC channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/irc`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/irc`
|
||||
|
||||
## Surface
|
||||
|
||||
channels: irc
|
||||
|
||||
## Related docs
|
||||
|
||||
- [irc](/channels/irc)
|
||||
23
docs/plugins/reference/kilocode.md
Normal file
23
docs/plugins/reference/kilocode.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Kilocode model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the kilocode plugin
|
||||
title: "Kilocode plugin"
|
||||
---
|
||||
|
||||
# Kilocode plugin
|
||||
|
||||
Adds Kilocode model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/kilocode-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/kilocode-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: kilocode
|
||||
|
||||
## Related docs
|
||||
|
||||
- [kilocode](/providers/kilocode)
|
||||
23
docs/plugins/reference/kimi.md
Normal file
23
docs/plugins/reference/kimi.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds Kimi, Kimi Coding model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the kimi plugin
|
||||
title: "Kimi plugin"
|
||||
---
|
||||
|
||||
# Kimi plugin
|
||||
|
||||
Adds Kimi, Kimi Coding model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/kimi-provider`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/kimi-provider`
|
||||
|
||||
## Surface
|
||||
|
||||
providers: kimi, kimi-coding
|
||||
|
||||
## Related docs
|
||||
|
||||
- [kimi](/providers/moonshot)
|
||||
23
docs/plugins/reference/line.md
Normal file
23
docs/plugins/reference/line.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw LINE channel plugin for LINE Bot API chats."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the line plugin
|
||||
title: "LINE plugin"
|
||||
---
|
||||
|
||||
# LINE plugin
|
||||
|
||||
OpenClaw LINE channel plugin for LINE Bot API chats.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/line`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
channels: line
|
||||
|
||||
## Related docs
|
||||
|
||||
- [line](/channels/line)
|
||||
23
docs/plugins/reference/litellm.md
Normal file
23
docs/plugins/reference/litellm.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds LiteLLM model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the litellm plugin
|
||||
title: "LiteLLM plugin"
|
||||
---
|
||||
|
||||
# LiteLLM plugin
|
||||
|
||||
Adds LiteLLM model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/litellm-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: litellm; contracts: imageGenerationProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [litellm](/providers/litellm)
|
||||
23
docs/plugins/reference/llama-cpp.md
Normal file
23
docs/plugins/reference/llama-cpp.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Local GGUF embeddings through node-llama-cpp."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the llama-cpp plugin
|
||||
title: "Llama Cpp plugin"
|
||||
---
|
||||
|
||||
# Llama Cpp plugin
|
||||
|
||||
Local GGUF embeddings through node-llama-cpp.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/llama-cpp-provider`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: embeddingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [llama-cpp](/plugins/llama-cpp)
|
||||
19
docs/plugins/reference/llm-task.md
Normal file
19
docs/plugins/reference/llm-task.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Generic JSON-only LLM tool for structured tasks callable from workflows."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the llm-task plugin
|
||||
title: "LLM Task plugin"
|
||||
---
|
||||
|
||||
# LLM Task plugin
|
||||
|
||||
Generic JSON-only LLM tool for structured tasks callable from workflows.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/llm-task`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
23
docs/plugins/reference/lmstudio.md
Normal file
23
docs/plugins/reference/lmstudio.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds LM Studio model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the lmstudio plugin
|
||||
title: "LM Studio plugin"
|
||||
---
|
||||
|
||||
# LM Studio plugin
|
||||
|
||||
Adds LM Studio model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/lmstudio-provider`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: lmstudio; contracts: memoryEmbeddingProviders
|
||||
|
||||
## Related docs
|
||||
|
||||
- [lmstudio](/providers/lmstudio)
|
||||
19
docs/plugins/reference/lobster.md
Normal file
19
docs/plugins/reference/lobster.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Lobster workflow tool plugin for typed pipelines and resumable approvals."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the lobster plugin
|
||||
title: "Lobster plugin"
|
||||
---
|
||||
|
||||
# Lobster plugin
|
||||
|
||||
Lobster workflow tool plugin for typed pipelines and resumable approvals.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/lobster`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
23
docs/plugins/reference/matrix.md
Normal file
23
docs/plugins/reference/matrix.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw Matrix channel plugin for rooms and direct messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the matrix plugin
|
||||
title: "Matrix plugin"
|
||||
---
|
||||
|
||||
# Matrix plugin
|
||||
|
||||
OpenClaw Matrix channel plugin for rooms and direct messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/matrix`
|
||||
- Install route: ClawHub: `clawhub:@openclaw/matrix`; npm
|
||||
|
||||
## Surface
|
||||
|
||||
channels: matrix
|
||||
|
||||
## Related docs
|
||||
|
||||
- [matrix](/channels/matrix)
|
||||
23
docs/plugins/reference/mattermost.md
Normal file
23
docs/plugins/reference/mattermost.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Adds the Mattermost channel surface for sending and receiving OpenClaw messages."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the mattermost plugin
|
||||
title: "Mattermost plugin"
|
||||
---
|
||||
|
||||
# Mattermost plugin
|
||||
|
||||
Adds the Mattermost channel surface for sending and receiving OpenClaw messages.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/mattermost`
|
||||
- Install route: npm; ClawHub: `clawhub:@openclaw/mattermost`
|
||||
|
||||
## Surface
|
||||
|
||||
channels: mattermost
|
||||
|
||||
## Related docs
|
||||
|
||||
- [mattermost](/channels/mattermost)
|
||||
19
docs/plugins/reference/memory-core.md
Normal file
19
docs/plugins/reference/memory-core.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Adds agent-callable tools."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the memory-core plugin
|
||||
title: "Memory Core plugin"
|
||||
---
|
||||
|
||||
# Memory Core plugin
|
||||
|
||||
Adds agent-callable tools.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/memory-core`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
23
docs/plugins/reference/memory-lancedb.md
Normal file
23
docs/plugins/reference/memory-lancedb.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "OpenClaw LanceDB-backed long-term memory plugin with auto-recall, auto-capture, and vector search."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the memory-lancedb plugin
|
||||
title: "Memory Lancedb plugin"
|
||||
---
|
||||
|
||||
# Memory Lancedb plugin
|
||||
|
||||
OpenClaw LanceDB-backed long-term memory plugin with auto-recall, auto-capture, and vector search.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/memory-lancedb`
|
||||
- Install route: npm; ClawHub
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools
|
||||
|
||||
## Related docs
|
||||
|
||||
- [memory-lancedb](/plugins/memory-lancedb)
|
||||
23
docs/plugins/reference/memory-wiki.md
Normal file
23
docs/plugins/reference/memory-wiki.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
summary: "Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the memory-wiki plugin
|
||||
title: "Memory Wiki plugin"
|
||||
---
|
||||
|
||||
# Memory Wiki plugin
|
||||
|
||||
Persistent wiki compiler and Obsidian-friendly knowledge vault for OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/memory-wiki`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: tools; skills
|
||||
|
||||
## Related docs
|
||||
|
||||
- [memory-wiki](/plugins/memory-wiki)
|
||||
113
docs/plugins/reference/microsoft-foundry.md
Normal file
113
docs/plugins/reference/microsoft-foundry.md
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
summary: "Adds Microsoft Foundry model provider support to OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the microsoft-foundry plugin
|
||||
title: "Microsoft Foundry plugin"
|
||||
---
|
||||
|
||||
# Microsoft Foundry plugin
|
||||
|
||||
Adds Microsoft Foundry model provider support to OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/microsoft-foundry`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
providers: microsoft-foundry; contracts: imageGenerationProviders
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-start -->
|
||||
|
||||
- Image-generation provider: `microsoft-foundry`
|
||||
|
||||
## Requirements
|
||||
|
||||
- A Microsoft Foundry or Azure AI Foundry resource with deployments.
|
||||
- API-key auth through `AZURE_OPENAI_API_KEY` or a configured provider API key.
|
||||
- For Entra ID auth, install the Azure CLI and run `az login` before
|
||||
onboarding. OpenClaw refreshes Microsoft Foundry runtime tokens through
|
||||
`az account get-access-token`.
|
||||
|
||||
## Chat models
|
||||
|
||||
Microsoft Foundry chat deployments use the provider model ref
|
||||
`microsoft-foundry/<deployment-name>`. Onboarding discovers Foundry resources
|
||||
and deployments with the Azure CLI, then writes the selected deployment name to
|
||||
the model config.
|
||||
|
||||
OpenClaw uses the Foundry `/openai/v1` endpoint for supported OpenAI-compatible
|
||||
chat APIs:
|
||||
|
||||
- GPT, `o*`, `computer-use-preview`, and DeepSeek-V4 model families default to
|
||||
`openai-responses`.
|
||||
- MAI-DS-R1 and other chat-completion deployments use `openai-completions`
|
||||
unless an explicit supported API is configured.
|
||||
- MAI-DS-R1 is recorded as reasoning-capable through reasoning content, not
|
||||
through `reasoning_effort`. Its context and output token metadata are
|
||||
163,840 tokens.
|
||||
|
||||
Anthropic Claude deployments in Microsoft Foundry use the Anthropic Messages
|
||||
API shape, not the OpenAI-compatible `/openai/v1` shape. Configure those as a
|
||||
custom `anthropic-messages` provider until the Microsoft Foundry plugin grows a
|
||||
native Anthropic runtime. When the Foundry deployment name differs from the
|
||||
Claude model ID, set `params.canonicalModelId` on the model entry so OpenClaw
|
||||
can apply model-specific wire contracts, map `/think off` correctly, and
|
||||
preserve signed thinking safely.
|
||||
|
||||
## MAI image generation
|
||||
|
||||
The plugin registers `microsoft-foundry` for `image_generate` with the current
|
||||
Microsoft AI image models:
|
||||
|
||||
- `MAI-Image-2.5-Flash`
|
||||
- `MAI-Image-2.5`
|
||||
- `MAI-Image-2e`
|
||||
- `MAI-Image-2`
|
||||
|
||||
Use a deployed MAI image deployment name as the model ref. The provider does
|
||||
not declare a default image model because the MAI API requires your deployment
|
||||
name in the request `model` field:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
imageGenerationModel: {
|
||||
primary: "microsoft-foundry/<deployment-name>",
|
||||
timeoutMs: 600000,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Prompt-only generation calls Microsoft Foundry's MAI generations endpoint:
|
||||
`/mai/v1/images/generations`. Reference-image edits call
|
||||
`/mai/v1/images/edits` and are limited to `MAI-Image-2.5-Flash` and
|
||||
`MAI-Image-2.5` deployments.
|
||||
|
||||
Prompt-only generation can use a custom deployment name with just the Foundry
|
||||
endpoint configured. For image edits with a custom deployment name, select the
|
||||
deployment through onboarding or include model metadata so OpenClaw can verify
|
||||
that the deployment is backed by `MAI-Image-2.5-Flash` or `MAI-Image-2.5`.
|
||||
|
||||
MAI image constraints:
|
||||
|
||||
- Output: one PNG image per request.
|
||||
- Size: default `1024x1024`; both width and height must be at least 768 px.
|
||||
- Total pixels: width × height must be at most 1,048,576.
|
||||
- Edits: one PNG or JPEG input image.
|
||||
- Unsupported shared hints such as `aspectRatio`, `resolution`, `quality`,
|
||||
`background`, and non-PNG `outputFormat` are not sent to Microsoft Foundry.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `az: command not found`: install the Azure CLI or use API-key auth.
|
||||
- `Microsoft Foundry endpoint missing for MAI image generation`: select a
|
||||
Foundry deployment through onboarding or add `models.providers.microsoft-foundry.baseUrl`.
|
||||
- `supports MAI image deployments only`: the selected image model points at a
|
||||
non-MAI deployment. Use a deployed MAI image model for `image_generate`.
|
||||
|
||||
<!-- openclaw-plugin-reference:manual-end -->
|
||||
19
docs/plugins/reference/microsoft.md
Normal file
19
docs/plugins/reference/microsoft.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Adds text-to-speech provider support."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the microsoft plugin
|
||||
title: "Microsoft plugin"
|
||||
---
|
||||
|
||||
# Microsoft plugin
|
||||
|
||||
Adds text-to-speech provider support.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/microsoft-speech`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: speechProviders
|
||||
19
docs/plugins/reference/migrate-claude.md
Normal file
19
docs/plugins/reference/migrate-claude.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
summary: "Imports Claude Code and Claude Desktop instructions, MCP servers, skills, and safe configuration into OpenClaw."
|
||||
read_when:
|
||||
- You are installing, configuring, or auditing the migrate-claude plugin
|
||||
title: "Migrate Claude plugin"
|
||||
---
|
||||
|
||||
# Migrate Claude plugin
|
||||
|
||||
Imports Claude Code and Claude Desktop instructions, MCP servers, skills, and safe configuration into OpenClaw.
|
||||
|
||||
## Distribution
|
||||
|
||||
- Package: `@openclaw/migrate-claude`
|
||||
- Install route: included in OpenClaw
|
||||
|
||||
## Surface
|
||||
|
||||
contracts: migrationProviders
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user