mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:50:42 +00:00
docs: typography hygiene + drop one in-body H1 across 5 pages
Replaced 98 typography characters (curly quotes, apostrophes, em/en dashes, non-breaking hyphens) with ASCII equivalents per docs/CLAUDE.md heading and content hygiene rules. - docs/plugins/sdk-migration.md: 20 chars - docs/help/testing.md: 20 chars - docs/automation/tasks.md: 20 chars - docs/plugins/sdk-channel-plugins.md: 19 chars - docs/channels/yuanbao.md: 19 chars; removed the duplicate '# Yuanbao' H1 (Mintlify renders title from frontmatter).
This commit is contained in:
@@ -14,7 +14,7 @@ Looking for scheduling? See [Automation and tasks](/automation) for choosing the
|
||||
|
||||
Background tasks track work that runs **outside your main conversation session**: ACP runs, subagent spawns, isolated cron job executions, and CLI-initiated operations.
|
||||
|
||||
Tasks do **not** replace sessions, cron jobs, or heartbeats — they are the **activity ledger** that records what detached work happened, when, and whether it succeeded.
|
||||
Tasks do **not** replace sessions, cron jobs, or heartbeats - they are the **activity ledger** that records what detached work happened, when, and whether it succeeded.
|
||||
|
||||
<Note>
|
||||
Not every agent run creates a task. Heartbeat turns and normal interactive chat do not. All cron executions, ACP spawns, subagent spawns, and CLI agent commands do.
|
||||
@@ -22,7 +22,7 @@ Not every agent run creates a task. Heartbeat turns and normal interactive chat
|
||||
|
||||
## TL;DR
|
||||
|
||||
- Tasks are **records**, not schedulers — cron and heartbeat decide _when_ work runs, tasks track _what happened_.
|
||||
- Tasks are **records**, not schedulers - cron and heartbeat decide _when_ work runs, tasks track _what happened_.
|
||||
- ACP, subagents, all cron jobs, and CLI operations create tasks. Heartbeat turns do not.
|
||||
- Each task moves through `queued → running → terminal` (succeeded, failed, timed_out, cancelled, or lost).
|
||||
- Cron tasks stay live while the cron runtime still owns the job; if the
|
||||
@@ -100,7 +100,7 @@ Not every agent run creates a task. Heartbeat turns and normal interactive chat
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Notify defaults for cron and media">
|
||||
Main-session cron tasks use `silent` notify policy by default — they create records for tracking but do not generate notifications. Isolated cron tasks also default to `silent` but are more visible because they run in their own session.
|
||||
Main-session cron tasks use `silent` notify policy by default - they create records for tracking but do not generate notifications. Isolated cron tasks also default to `silent` but are more visible because they run in their own session.
|
||||
|
||||
Session-backed `music_generate` and `video_generate` runs also use `silent` notify policy. They still create task records, but completion is handed back to the original agent session as an internal wake so the agent can write the follow-up message and attach the finished media itself. Group/channel completions follow the normal visible-reply policy, so the agent uses the message tool when source delivery requires it. If the completion agent fails to produce message-tool delivery evidence in a tool-only route, OpenClaw sends the completion fallback directly to the original channel instead of leaving the media private.
|
||||
|
||||
@@ -109,7 +109,7 @@ Not every agent run creates a task. Heartbeat turns and normal interactive chat
|
||||
While a session-backed `video_generate` task is still active, the tool also acts as a guardrail: repeated `video_generate` calls in that same session return the active task status instead of starting a second concurrent generation. Use `action: "status"` when you want an explicit progress/status lookup from the agent side.
|
||||
</Accordion>
|
||||
<Accordion title="What does not create tasks">
|
||||
- Heartbeat turns — main-session; see [Heartbeat](/gateway/heartbeat)
|
||||
- Heartbeat turns - main-session; see [Heartbeat](/gateway/heartbeat)
|
||||
- Normal interactive chat turns
|
||||
- Direct `/command` responses
|
||||
|
||||
@@ -140,7 +140,7 @@ stateDiagram-v2
|
||||
| `cancelled` | Stopped by the operator via `openclaw tasks cancel` |
|
||||
| `lost` | The runtime lost authoritative backing state after a 5-minute grace period |
|
||||
|
||||
Transitions happen automatically — when the associated agent run ends, the task status updates to match.
|
||||
Transitions happen automatically - when the associated agent run ends, the task status updates to match.
|
||||
|
||||
Agent run completion is authoritative for active task records. A successful detached run finalizes as `succeeded`, ordinary run errors finalize as `failed`, and timeout or abort outcomes finalize as `timed_out`. If an operator already cancelled the task, or the runtime already recorded a stronger terminal state such as `failed`, `timed_out`, or `lost`, a later success signal does not downgrade that terminal status.
|
||||
|
||||
@@ -161,12 +161,12 @@ Agent run completion is authoritative for active task records. A successful deta
|
||||
|
||||
When a task reaches a terminal state, OpenClaw notifies you. There are two delivery paths:
|
||||
|
||||
**Direct delivery** — if the task has a channel target (the `requesterOrigin`), the completion message goes straight to that channel (Telegram, Discord, Slack, etc.). For subagent completions, OpenClaw also preserves bound thread/topic routing when available and can fill a missing `to` / account from the requester session's stored route (`lastChannel` / `lastTo` / `lastAccountId`) before giving up on direct delivery.
|
||||
**Direct delivery** - if the task has a channel target (the `requesterOrigin`), the completion message goes straight to that channel (Telegram, Discord, Slack, etc.). For subagent completions, OpenClaw also preserves bound thread/topic routing when available and can fill a missing `to` / account from the requester session's stored route (`lastChannel` / `lastTo` / `lastAccountId`) before giving up on direct delivery.
|
||||
|
||||
**Session-queued delivery** — if direct delivery fails or no origin is set, the update is queued as a system event in the requester's session and surfaces on the next heartbeat.
|
||||
**Session-queued delivery** - if direct delivery fails or no origin is set, the update is queued as a system event in the requester's session and surfaces on the next heartbeat.
|
||||
|
||||
<Tip>
|
||||
Task completion triggers an immediate heartbeat wake so you see the result quickly — you do not have to wait for the next scheduled heartbeat tick.
|
||||
Task completion triggers an immediate heartbeat wake so you see the result quickly - you do not have to wait for the next scheduled heartbeat tick.
|
||||
</Tip>
|
||||
|
||||
That means the usual workflow is push-based: start detached work once, then let the runtime wake or notify you on completion. Poll task state only when you need debugging, intervention, or an explicit audit.
|
||||
@@ -177,7 +177,7 @@ Control how much you hear about each task:
|
||||
|
||||
| Policy | What is delivered |
|
||||
| --------------------- | ----------------------------------------------------------------------- |
|
||||
| `done_only` (default) | Only terminal state (succeeded, failed, etc.) — **this is the default** |
|
||||
| `done_only` (default) | Only terminal state (succeeded, failed, etc.) - **this is the default** |
|
||||
| `state_changes` | Every state transition and progress update |
|
||||
| `silent` | Nothing at all |
|
||||
|
||||
@@ -290,9 +290,9 @@ Tasks: 3 queued · 2 running · 1 issues
|
||||
|
||||
The summary reports:
|
||||
|
||||
- **active** — count of `queued` + `running`
|
||||
- **failures** — count of `failed` + `timed_out` + `lost`
|
||||
- **byRuntime** — breakdown by `acp`, `subagent`, `cron`, `cli`
|
||||
- **active** - count of `queued` + `running`
|
||||
- **failures** - count of `failed` + `timed_out` + `lost`
|
||||
- **byRuntime** - breakdown by `acp`, `subagent`, `cron`, `cli`
|
||||
|
||||
Both `/status` and the `session_status` tool use a cleanup-aware task snapshot: active tasks are preferred, stale completed rows are hidden, and recent failures only surface when no active work remains. This keeps the status card focused on what matters right now.
|
||||
|
||||
@@ -343,13 +343,13 @@ A sweeper runs every **60 seconds** and handles four things:
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Tasks and cron">
|
||||
A cron job **definition** lives in `~/.openclaw/cron/jobs.json`; runtime execution state lives beside it in `~/.openclaw/cron/jobs-state.json`. **Every** cron execution creates a task record — both main-session and isolated. Main-session cron tasks default to `silent` notify policy so they track without generating notifications.
|
||||
A cron job **definition** lives in `~/.openclaw/cron/jobs.json`; runtime execution state lives beside it in `~/.openclaw/cron/jobs-state.json`. **Every** cron execution creates a task record - both main-session and isolated. Main-session cron tasks default to `silent` notify policy so they track without generating notifications.
|
||||
|
||||
See [Cron Jobs](/automation/cron-jobs).
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Tasks and heartbeat">
|
||||
Heartbeat runs are main-session turns — they do not create task records. When a task completes, it can trigger a heartbeat wake so you see the result promptly.
|
||||
Heartbeat runs are main-session turns - they do not create task records. When a task completes, it can trigger a heartbeat wake so you see the result promptly.
|
||||
|
||||
See [Heartbeat](/gateway/heartbeat).
|
||||
|
||||
@@ -358,14 +358,14 @@ A sweeper runs every **60 seconds** and handles four things:
|
||||
A task may reference a `childSessionKey` (where work runs) and a `requesterSessionKey` (who started it). Sessions are conversation context; tasks are activity tracking on top of that.
|
||||
</Accordion>
|
||||
<Accordion title="Tasks and agent runs">
|
||||
A task's `runId` links to the agent run doing the work. Agent lifecycle events (start, end, error) automatically update the task status — you do not need to manage the lifecycle manually.
|
||||
A task's `runId` links to the agent run doing the work. Agent lifecycle events (start, end, error) automatically update the task status - you do not need to manage the lifecycle manually.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Related
|
||||
|
||||
- [Automation & Tasks](/automation) — all automation mechanisms at a glance
|
||||
- [CLI: Tasks](/cli/tasks) — CLI command reference
|
||||
- [Heartbeat](/gateway/heartbeat) — periodic main-session turns
|
||||
- [Scheduled Tasks](/automation/cron-jobs) — scheduling background work
|
||||
- [Task Flow](/automation/taskflow) — flow orchestration above tasks
|
||||
- [Automation & Tasks](/automation) - all automation mechanisms at a glance
|
||||
- [CLI: Tasks](/cli/tasks) - CLI command reference
|
||||
- [Heartbeat](/gateway/heartbeat) - periodic main-session turns
|
||||
- [Scheduled Tasks](/automation/cron-jobs) - scheduling background work
|
||||
- [Task Flow](/automation/taskflow) - flow orchestration above tasks
|
||||
|
||||
@@ -6,8 +6,6 @@ read_when:
|
||||
title: Yuanbao
|
||||
---
|
||||
|
||||
# Yuanbao
|
||||
|
||||
Tencent Yuanbao is Tencent's AI assistant platform. The OpenClaw channel plugin
|
||||
connects Yuanbao bots to OpenClaw over WebSocket so they can interact with users
|
||||
through direct messages and group chats.
|
||||
@@ -53,10 +51,10 @@ Follow the prompts to enter your App ID and App Secret.
|
||||
|
||||
Configure `dmPolicy` to control who can DM the bot:
|
||||
|
||||
- `"pairing"` — unknown users receive a pairing code; approve via CLI
|
||||
- `"allowlist"` — only users listed in `allowFrom` can chat
|
||||
- `"open"` — allow all users (default)
|
||||
- `"disabled"` — disable all DMs
|
||||
- `"pairing"` - unknown users receive a pairing code; approve via CLI
|
||||
- `"allowlist"` - only users listed in `allowFrom` can chat
|
||||
- `"open"` - allow all users (default)
|
||||
- `"disabled"` - disable all DMs
|
||||
|
||||
**Approve a pairing request:**
|
||||
|
||||
@@ -69,8 +67,8 @@ openclaw pairing approve yuanbao <CODE>
|
||||
|
||||
**Mention requirement** (`channels.yuanbao.requireMention`):
|
||||
|
||||
- `true` — require @mention (default)
|
||||
- `false` — respond without @mention
|
||||
- `true` - require @mention (default)
|
||||
- `false` - respond without @mention
|
||||
|
||||
Replying to the bot's message in a group chat is treated as an implicit mention.
|
||||
|
||||
@@ -228,9 +226,9 @@ Replying to the bot's message in a group chat is treated as an implicit mention.
|
||||
|
||||
### Message limits
|
||||
|
||||
- `maxChars` — single message max character count (default: `3000` chars)
|
||||
- `mediaMaxMb` — media upload/download limit (default: `20` MB)
|
||||
- `overflowPolicy` — behavior when message exceeds limit: `"split"` (default) or `"stop"`
|
||||
- `maxChars` - single message max character count (default: `3000` chars)
|
||||
- `mediaMaxMb` - media upload/download limit (default: `20` MB)
|
||||
- `overflowPolicy` - behavior when message exceeds limit: `"split"` (default) or `"stop"`
|
||||
|
||||
### Streaming
|
||||
|
||||
@@ -358,13 +356,13 @@ Full configuration: [Gateway configuration](/gateway/configuration)
|
||||
| ------------------------------------------ | ------------------------------------------------- | -------------------------------------- |
|
||||
| `channels.yuanbao.enabled` | Enable/disable the channel | `true` |
|
||||
| `channels.yuanbao.defaultAccount` | Default account for outbound routing | `default` |
|
||||
| `channels.yuanbao.accounts.<id>.appKey` | App Key (used for signing and ticket generation) | — |
|
||||
| `channels.yuanbao.accounts.<id>.appSecret` | App Secret (used for signing) | — |
|
||||
| `channels.yuanbao.accounts.<id>.token` | Pre-signed token (skips automatic ticket signing) | — |
|
||||
| `channels.yuanbao.accounts.<id>.name` | Account display name | — |
|
||||
| `channels.yuanbao.accounts.<id>.appKey` | App Key (used for signing and ticket generation) | - |
|
||||
| `channels.yuanbao.accounts.<id>.appSecret` | App Secret (used for signing) | - |
|
||||
| `channels.yuanbao.accounts.<id>.token` | Pre-signed token (skips automatic ticket signing) | - |
|
||||
| `channels.yuanbao.accounts.<id>.name` | Account display name | - |
|
||||
| `channels.yuanbao.accounts.<id>.enabled` | Enable/disable a specific account | `true` |
|
||||
| `channels.yuanbao.dm.policy` | DM policy | `open` |
|
||||
| `channels.yuanbao.dm.allowFrom` | DM allowlist (user ID list) | — |
|
||||
| `channels.yuanbao.dm.allowFrom` | DM allowlist (user ID list) | - |
|
||||
| `channels.yuanbao.requireMention` | Require @mention in groups | `true` |
|
||||
| `channels.yuanbao.overflowPolicy` | Long message handling (`split` or `stop`) | `split` |
|
||||
| `channels.yuanbao.replyToMode` | Group reply-to strategy (`off`, `first`, `all`) | `first` |
|
||||
@@ -411,8 +409,8 @@ Full configuration: [Gateway configuration](/gateway/configuration)
|
||||
|
||||
## Related
|
||||
|
||||
- [Channels Overview](/channels) — all supported channels
|
||||
- [Pairing](/channels/pairing) — DM authentication and pairing flow
|
||||
- [Groups](/channels/groups) — group chat behavior and mention gating
|
||||
- [Channel Routing](/channels/channel-routing) — session routing for messages
|
||||
- [Security](/gateway/security) — access model and hardening
|
||||
- [Channels Overview](/channels) - all supported channels
|
||||
- [Pairing](/channels/pairing) - DM authentication and pairing flow
|
||||
- [Groups](/channels/groups) - group chat behavior and mention gating
|
||||
- [Channel Routing](/channels/channel-routing) - session routing for messages
|
||||
- [Security](/gateway/security) - access model and hardening
|
||||
|
||||
@@ -18,9 +18,9 @@ of Docker runners. This doc is a "how we test" guide:
|
||||
<Note>
|
||||
**QA stack (qa-lab, qa-channel, live transport lanes)** is documented separately:
|
||||
|
||||
- [QA overview](/concepts/qa-e2e-automation) — architecture, command surface, scenario authoring.
|
||||
- [Matrix QA](/concepts/qa-matrix) — reference for `pnpm openclaw qa matrix`.
|
||||
- [QA channel](/channels/qa-channel) — the synthetic transport plugin used by repo-backed scenarios.
|
||||
- [QA overview](/concepts/qa-e2e-automation) - architecture, command surface, scenario authoring.
|
||||
- [Matrix QA](/concepts/qa-matrix) - reference for `pnpm openclaw qa matrix`.
|
||||
- [QA channel](/channels/qa-channel) - the synthetic transport plugin used by repo-backed scenarios.
|
||||
|
||||
This page covers running the regular test suites and Docker/Parallels runners. The QA-specific runners section below ([QA-specific runners](#qa-specific-runners)) lists the concrete `qa` invocations and points back at the references above.
|
||||
</Note>
|
||||
@@ -301,7 +301,7 @@ gh workflow run package-acceptance.yml --ref main \
|
||||
- Starts only the local AIMock provider server for direct protocol smoke
|
||||
testing.
|
||||
- `pnpm openclaw qa matrix`
|
||||
- Runs the Matrix live QA lane against a disposable Docker-backed Tuwunel homeserver. Source-checkout only — packaged installs do not ship `qa-lab`.
|
||||
- Runs the Matrix live QA lane against a disposable Docker-backed Tuwunel homeserver. Source-checkout only - packaged installs do not ship `qa-lab`.
|
||||
- Full CLI, profile/scenario catalog, env vars, and artifact layout: [Matrix QA](/concepts/qa-matrix).
|
||||
- `pnpm openclaw qa telegram`
|
||||
- Runs the Telegram live QA lane against a real private group using the driver and SUT bot tokens from env.
|
||||
@@ -399,7 +399,7 @@ The architecture and scenario-helper names for new channel adapters live in [QA
|
||||
|
||||
## Test suites (what runs where)
|
||||
|
||||
Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
Think of the suites as "increasing realism" (and increasing flakiness/cost):
|
||||
|
||||
### Unit / integration (default)
|
||||
|
||||
@@ -578,12 +578,12 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
||||
- Files: `src/**/*.live.test.ts`, `test/**/*.live.test.ts`, and bundled-plugin live tests under `extensions/`
|
||||
- Default: **enabled** by `pnpm test:live` (sets `OPENCLAW_LIVE_TEST=1`)
|
||||
- Scope:
|
||||
- “Does this provider/model actually work _today_ with real creds?”
|
||||
- "Does this provider/model actually work _today_ with real creds?"
|
||||
- Catch provider format changes, tool-calling quirks, auth issues, and rate limit behavior
|
||||
- Expectations:
|
||||
- Not CI-stable by design (real networks, real provider policies, quotas, outages)
|
||||
- Costs money / uses rate limits
|
||||
- Prefer running narrowed subsets instead of “everything”
|
||||
- Prefer running narrowed subsets instead of "everything"
|
||||
- Live runs source `~/.profile` to pick up missing API keys.
|
||||
- By default, live runs still isolate `HOME` and copy config/auth material into a temp test home so unit fixtures cannot mutate your real `~/.openclaw`.
|
||||
- Set `OPENCLAW_LIVE_USE_REAL_HOME=1` only when you intentionally need live tests to use your real home directory.
|
||||
@@ -601,13 +601,13 @@ Use this decision table:
|
||||
|
||||
- Editing logic/tests: run `pnpm test` (and `pnpm test:coverage` if you changed a lot)
|
||||
- Touching gateway networking / WS protocol / pairing: add `pnpm test:e2e`
|
||||
- Debugging “my bot is down” / provider-specific failures / tool calling: run a narrowed `pnpm test:live`
|
||||
- Debugging "my bot is down" / provider-specific failures / tool calling: run a narrowed `pnpm test:live`
|
||||
|
||||
## Live (network-touching) tests
|
||||
|
||||
For the live model matrix, CLI backend smokes, ACP smokes, Codex app-server
|
||||
harness, and all media-provider live tests (Deepgram, BytePlus, ComfyUI, image,
|
||||
music, video, media harness) — plus credential handling for live runs — see
|
||||
music, video, media harness) - plus credential handling for live runs - see
|
||||
[Testing live suites](/help/testing-live). For the dedicated update and
|
||||
plugin validation checklist, see
|
||||
[Testing updates and plugins](/help/testing-updates-plugins).
|
||||
@@ -744,19 +744,19 @@ Run full Mintlify anchor validation when you need in-page heading checks too: `p
|
||||
|
||||
## Offline regression (CI-safe)
|
||||
|
||||
These are “real pipeline” regressions without real providers:
|
||||
These are "real pipeline" regressions without real providers:
|
||||
|
||||
- Gateway tool calling (mock OpenAI, real gateway + agent loop): `src/gateway/gateway.test.ts` (case: "runs a mock OpenAI tool call end-to-end via gateway agent loop")
|
||||
- Gateway wizard (WS `wizard.start`/`wizard.next`, writes config + auth enforced): `src/gateway/gateway.test.ts` (case: "runs wizard over ws and writes auth token config")
|
||||
|
||||
## Agent reliability evals (skills)
|
||||
|
||||
We already have a few CI-safe tests that behave like “agent reliability evals”:
|
||||
We already have a few CI-safe tests that behave like "agent reliability evals":
|
||||
|
||||
- Mock tool-calling through the real gateway + agent loop (`src/gateway/gateway.test.ts`).
|
||||
- End-to-end wizard flows that validate session wiring and config effects (`src/gateway/gateway.test.ts`).
|
||||
|
||||
What’s still missing for skills (see [Skills](/tools/skills)):
|
||||
What's still missing for skills (see [Skills](/tools/skills)):
|
||||
|
||||
- **Decisioning:** when skills are listed in the prompt, does the agent pick the right skill (or avoid irrelevant ones)?
|
||||
- **Compliance:** does the agent read `SKILL.md` before use and follow required steps/args?
|
||||
@@ -829,7 +829,7 @@ Contract tests run in CI and do not require real API keys.
|
||||
When you fix a provider/model issue discovered in live:
|
||||
|
||||
- Add a CI-safe regression if possible (mock/stub provider, or capture the exact request-shape transformation)
|
||||
- If it’s inherently live-only (rate limits, auth policies), keep the live test narrow and opt-in via env vars
|
||||
- If it's inherently live-only (rate limits, auth policies), keep the live test narrow and opt-in via env vars
|
||||
- Prefer targeting the smallest layer that catches the bug:
|
||||
- provider request conversion/replay bug → direct models test
|
||||
- gateway session/history/tool pipeline bug → gateway live smoke or CI-safe gateway mock test
|
||||
|
||||
@@ -23,13 +23,13 @@ pairing, reply threading, and outbound messaging.
|
||||
Channel plugins do not need their own send/edit/react tools. OpenClaw keeps one
|
||||
shared `message` tool in core. Your plugin owns:
|
||||
|
||||
- **Config** — account resolution and setup wizard
|
||||
- **Security** — DM policy and allowlists
|
||||
- **Pairing** — DM approval flow
|
||||
- **Session grammar** — how provider-specific conversation ids map to base chats, thread ids, and parent fallbacks
|
||||
- **Outbound** — sending text, media, and polls to the platform
|
||||
- **Threading** — how replies are threaded
|
||||
- **Heartbeat typing** — optional typing/busy signals for heartbeat delivery targets
|
||||
- **Config** - account resolution and setup wizard
|
||||
- **Security** - DM policy and allowlists
|
||||
- **Pairing** - DM approval flow
|
||||
- **Session grammar** - how provider-specific conversation ids map to base chats, thread ids, and parent fallbacks
|
||||
- **Outbound** - sending text, media, and polls to the platform
|
||||
- **Threading** - how replies are threaded
|
||||
- **Heartbeat typing** - optional typing/busy signals for heartbeat delivery targets
|
||||
|
||||
Core owns the shared message tool, prompt wiring, the outer session-key shape,
|
||||
generic `:thread:` bookkeeping, and dispatch.
|
||||
@@ -145,11 +145,11 @@ Most channel plugins do not need approval-specific code.
|
||||
- If a channel needs native approval delivery, keep channel code focused on target normalization plus transport/presentation facts. Use `createChannelExecApprovalProfile`, `createChannelNativeOriginTargetResolver`, `createChannelApproverDmTargetResolver`, and `createApproverRestrictedNativeApprovalCapability` from `openclaw/plugin-sdk/approval-runtime`. Put the channel-specific facts behind `approvalCapability.nativeRuntime`, ideally via `createChannelApprovalNativeRuntimeAdapter(...)` or `createLazyChannelApprovalNativeRuntimeAdapter(...)`, so core can assemble the handler and own request filtering, routing, dedupe, expiry, gateway subscription, and routed-elsewhere notices. `nativeRuntime` is split into a few smaller seams:
|
||||
- `createChannelNativeOriginTargetResolver` uses the shared channel-route matcher by default for `{ to, accountId, threadId }` targets. Pass `targetsMatch` only when a channel has provider-specific equivalence rules, such as Slack timestamp prefix matching.
|
||||
- Pass `normalizeTargetForMatch` to `createChannelNativeOriginTargetResolver` when the channel needs to canonicalize provider ids before the default route matcher or a custom `targetsMatch` callback runs, while preserving the original target for delivery. Use `normalizeTarget` only when the resolved delivery target itself should be canonicalized.
|
||||
- `availability` — whether the account is configured and whether a request should be handled
|
||||
- `presentation` — map the shared approval view model into pending/resolved/expired native payloads or final actions
|
||||
- `transport` — prepare targets plus send/update/delete native approval messages
|
||||
- `interactions` — optional bind/unbind/clear-action hooks for native buttons or reactions
|
||||
- `observe` — optional delivery diagnostics hooks
|
||||
- `availability` - whether the account is configured and whether a request should be handled
|
||||
- `presentation` - map the shared approval view model into pending/resolved/expired native payloads or final actions
|
||||
- `transport` - prepare targets plus send/update/delete native approval messages
|
||||
- `interactions` - optional bind/unbind/clear-action hooks for native buttons or reactions
|
||||
- `observe` - optional delivery diagnostics hooks
|
||||
- If the channel needs runtime-owned objects such as a client, token, Bolt app, or webhook receiver, register them through `openclaw/plugin-sdk/channel-runtime-context`. The generic runtime-context registry lets core bootstrap capability-driven handlers from channel startup state without adding approval-specific wrapper glue.
|
||||
- Reach for the lower-level `createChannelApprovalHandler` or `createChannelNativeApprovalRuntime` only when the capability-driven seam is not expressive enough yet.
|
||||
- Native approval channels must route both `accountId` and `approvalKind` through those helpers. `accountId` keeps multi-account approval policy scoped to the right bot account, and `approvalKind` keeps exec vs plugin approval behavior available to the channel without hardcoded branches in core.
|
||||
@@ -424,7 +424,7 @@ should use `resolveInboundMentionDecision({ facts, policy })`.
|
||||
|
||||
<Step title="Build the channel plugin object">
|
||||
The `ChannelPlugin` interface has many optional adapter surfaces. Start with
|
||||
the minimum — `id` and `setup` — and add adapters as you need them.
|
||||
the minimum - `id` and `setup` - and add adapters as you need them.
|
||||
|
||||
Create `src/channel.ts`:
|
||||
|
||||
@@ -631,7 +631,7 @@ should use `resolveInboundMentionDecision({ facts, policy })`.
|
||||
const event = parseWebhookPayload(req);
|
||||
|
||||
// Your inbound handler dispatches the message to OpenClaw.
|
||||
// The exact wiring depends on your platform SDK —
|
||||
// The exact wiring depends on your platform SDK -
|
||||
// see a real example in the bundled Microsoft Teams or Google Chat plugin package.
|
||||
await handleAcmeChatInbound(api, event);
|
||||
|
||||
@@ -742,10 +742,10 @@ surface unless you are maintaining that bundled plugin family directly.
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — if your plugin also provides models
|
||||
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
||||
- [SDK Testing](/plugins/sdk-testing) — test utilities and contract tests
|
||||
- [Plugin Manifest](/plugins/manifest) — full manifest schema
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) - if your plugin also provides models
|
||||
- [SDK Overview](/plugins/sdk-overview) - full subpath import reference
|
||||
- [SDK Testing](/plugins/sdk-testing) - test utilities and contract tests
|
||||
- [Plugin Manifest](/plugins/manifest) - full manifest schema
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
@@ -19,18 +19,18 @@ the new architecture, this guide helps you migrate.
|
||||
The old plugin system provided two wide-open surfaces that let plugins import
|
||||
anything they needed from a single entry point:
|
||||
|
||||
- **`openclaw/plugin-sdk/compat`** — a single import that re-exported dozens of
|
||||
- **`openclaw/plugin-sdk/compat`** - a single import that re-exported dozens of
|
||||
helpers. It was introduced to keep older hook-based plugins working while the
|
||||
new plugin architecture was being built.
|
||||
- **`openclaw/plugin-sdk/infra-runtime`** — a broad runtime helper barrel that
|
||||
- **`openclaw/plugin-sdk/infra-runtime`** - a broad runtime helper barrel that
|
||||
mixed system events, heartbeat state, delivery queues, fetch/proxy helpers,
|
||||
file helpers, approval types, and unrelated utilities.
|
||||
- **`openclaw/plugin-sdk/config-runtime`** — a broad config compatibility barrel
|
||||
- **`openclaw/plugin-sdk/config-runtime`** - a broad config compatibility barrel
|
||||
that still carries deprecated direct load/write helpers during the migration
|
||||
window.
|
||||
- **`openclaw/extension-api`** — a bridge that gave plugins direct access to
|
||||
- **`openclaw/extension-api`** - a bridge that gave plugins direct access to
|
||||
host-side helpers like the embedded agent runner.
|
||||
- **`api.registerEmbeddedExtensionFactory(...)`** — a removed Pi-only bundled
|
||||
- **`api.registerEmbeddedExtensionFactory(...)`** - a removed Pi-only bundled
|
||||
extension hook that could observe embedded-runner events such as
|
||||
`tool_result`.
|
||||
|
||||
@@ -55,9 +55,9 @@ registration behavior.
|
||||
|
||||
The old approach caused problems:
|
||||
|
||||
- **Slow startup** — importing one helper loaded dozens of unrelated modules
|
||||
- **Circular dependencies** — broad re-exports made it easy to create import cycles
|
||||
- **Unclear API surface** — no way to tell which exports were stable vs internal
|
||||
- **Slow startup** - importing one helper loaded dozens of unrelated modules
|
||||
- **Circular dependencies** - broad re-exports made it easy to create import cycles
|
||||
- **Unclear API surface** - no way to tell which exports were stable vs internal
|
||||
|
||||
The modern plugin SDK fixes this: each import path (`openclaw/plugin-sdk/\<subpath\>`)
|
||||
is a small, self-contained module with a clear purpose and documented contract.
|
||||
@@ -679,7 +679,7 @@ canonical replacement.
|
||||
`buildCommandsMessagePaginated`, `buildHelpMessage`.
|
||||
|
||||
**New (`openclaw/plugin-sdk/command-status`)**: same signatures, same
|
||||
exports — just imported from the narrower subpath. `command-auth`
|
||||
exports - just imported from the narrower subpath. `command-auth`
|
||||
re-exports them as compat stubs.
|
||||
|
||||
```typescript
|
||||
@@ -698,7 +698,7 @@ canonical replacement.
|
||||
`openclaw/plugin-sdk/channel-inbound` or
|
||||
`openclaw/plugin-sdk/channel-mention-gating`.
|
||||
|
||||
**New**: `resolveInboundMentionDecision({ facts, policy })` — returns a
|
||||
**New**: `resolveInboundMentionDecision({ facts, policy })` - returns a
|
||||
single decision object instead of two split calls.
|
||||
|
||||
Downstream channel plugins (Slack, Discord, Matrix, MS Teams) have already
|
||||
@@ -714,7 +714,7 @@ canonical replacement.
|
||||
|
||||
`channelActions*` helpers in `openclaw/plugin-sdk/channel-actions` are
|
||||
deprecated alongside raw "actions" channel exports. Expose capabilities
|
||||
through the semantic `presentation` surface instead — channel plugins
|
||||
through the semantic `presentation` surface instead - channel plugins
|
||||
declare what they render (cards, buttons, selects) rather than which raw
|
||||
action names they accept.
|
||||
|
||||
@@ -756,7 +756,7 @@ canonical replacement.
|
||||
| `ProviderDiscoveryResult` | `ProviderCatalogResult` |
|
||||
| `ProviderPluginDiscovery` | `ProviderPluginCatalog` |
|
||||
|
||||
Plus the legacy `ProviderCapabilities` static bag — provider plugins
|
||||
Plus the legacy `ProviderCapabilities` static bag - provider plugins
|
||||
should use explicit provider hooks such as `buildReplayPolicy`,
|
||||
`normalizeToolSchemas`, and `wrapStreamFn` rather than a static object.
|
||||
|
||||
@@ -809,12 +809,12 @@ canonical replacement.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Memory plugin registration → registerMemoryCapability">
|
||||
**Old**: three separate calls —
|
||||
**Old**: three separate calls -
|
||||
`api.registerMemoryPromptSection(...)`,
|
||||
`api.registerMemoryFlushPlan(...)`,
|
||||
`api.registerMemoryRuntime(...)`.
|
||||
|
||||
**New**: one call on the memory-state API —
|
||||
**New**: one call on the memory-state API -
|
||||
`registerMemoryCapability(pluginId, { promptBuilder, flushPlanResolver, runtime })`.
|
||||
|
||||
Same slots, single registration call. Additive memory helpers
|
||||
@@ -906,9 +906,9 @@ This is a temporary escape hatch, not a permanent solution.
|
||||
|
||||
## Related
|
||||
|
||||
- [Getting Started](/plugins/building-plugins) — build your first plugin
|
||||
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) — building channel plugins
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) — building provider plugins
|
||||
- [Plugin Internals](/plugins/architecture) — architecture deep dive
|
||||
- [Plugin Manifest](/plugins/manifest) — manifest schema reference
|
||||
- [Getting Started](/plugins/building-plugins) - build your first plugin
|
||||
- [SDK Overview](/plugins/sdk-overview) - full subpath import reference
|
||||
- [Channel Plugins](/plugins/sdk-channel-plugins) - building channel plugins
|
||||
- [Provider Plugins](/plugins/sdk-provider-plugins) - building provider plugins
|
||||
- [Plugin Internals](/plugins/architecture) - architecture deep dive
|
||||
- [Plugin Manifest](/plugins/manifest) - manifest schema reference
|
||||
|
||||
Reference in New Issue
Block a user