![[OpenClaw 文档]工具--扩展](https://minio.imgdata.cn/cnesa/cnesa/2026/05/29/765544625aa111cd7ec16c796667c69f.png)
本文档汇总了 OpenClaw 官方文档站 工具 > 扩展 子模块下的全部 5 篇内容,源自 docs.openclaw.ai/zh-CN。
📄 语音通话插件
原文:https://docs.openclaw.ai/zh-CN/plugins/voice-call
通过插件为 OpenClaw 提供语音通话。支持出站通知、
多轮对话、全双工实时语音、流式
转录,以及带允许列表策略的入站通话。
当前提供商: twilio(Programmable Voice + Media Streams)、
telnyx(Call Control v2)、plivo(Voice API + XML transfer + GetInput
speech)、mock(开发/无网络)。
语音通话插件运行在 Gateway 网关进程内。如果你使用
远程 Gateway 网关,请在运行 Gateway 网关的机器上安装并配置该插件,
然后重启 Gateway 网关以加载它。
快速开始
bash
openclaw plugins install @openclaw/voice-call
bash
PLUGIN_SRC=./path/to/local/voice-call-plugin
openclaw plugins install "$PLUGIN_SRC"
cd "$PLUGIN_SRC" && pnpm install
使用裸包名以跟随当前官方发布标签。仅在需要可复现安装时,
才固定到精确版本。
之后重启 Gateway 网关,以便插件加载。
在 plugins.entries.voice-call.config 下设置配置(完整结构见下方
配置)。至少需要:
provider、提供商凭证、fromNumber,以及可公开访问的
webhook URL。
bash
openclaw voicecall setup
默认输出适合在聊天日志和终端中阅读。它会检查
插件启用状态、提供商凭证、webhook 暴露情况,以及
是否只有一个音频模式(`streaming` 或 `realtime`)处于启用状态。
脚本请使用 `--json`。
bash
openclaw voicecall smoke
openclaw voicecall smoke --to "+15555550123"
两者默认都是试运行。添加 `--yes` 才会实际发起一次简短的
出站通知通话:
```bash
openclaw voicecall smoke --to "+15555550123" --yes
```
对于 Twilio、Telnyx 和 Plivo,设置必须解析为 公共 webhook URL。
如果 publicUrl、隧道 URL、Tailscale URL 或服务回退
解析为 loopback 或私有网络空间,设置会失败,而不是
启动一个无法接收运营商 webhook 的提供商。
配置
如果 enabled: true,但所选提供商缺少凭证,
Gateway 网关启动会记录一条 setup-incomplete 警告,其中包含缺失键名,
并跳过启动运行时。命令、RPC 调用和智能体工具在使用时仍会
返回准确缺失的提供商配置。
语音通话凭证接受 SecretRefs。plugins.entries.voice-call.config.twilio.authToken、plugins.entries.voice-call.config.realtime.providers.*.apiKey、plugins.entries.voice-call.config.streaming.providers.*.apiKey 和 plugins.entries.voice-call.config.tts.providers.*.apiKey 会通过标准 SecretRef 表面解析;见 SecretRef 凭证表面。
{
plugins: {
entries: {
"voice-call": {
enabled: true,
config: {
provider: "twilio", // or "telnyx" | "plivo" | "mock"
fromNumber: "+15550001234", // or TWILIO_FROM_NUMBER for Twilio
toNumber: "+15550005678",
sessionScope: "per-phone", // per-phone | per-call
numbers: {
"+15550009999": {
inboundGreeting: "Silver Fox Cards, how can I help?",
responseSystemPrompt: "You are a concise baseball card specialist.",
tts: {
providers: {
openai: { voice: "alloy" },
},
},
},
},
twilio: {
accountSid: "ACxxxxxxxx",
authToken: "...",
},
telnyx: {
apiKey: "...",
connectionId: "...",
// Telnyx webhook public key from the Mission Control Portal
// (Base64; can also be set via TELNYX_PUBLIC_KEY).
publicKey: "...",
},
plivo: {
authId: "MAxxxxxxxxxxxxxxxxxxxx",
authToken: "...",
},
// Webhook server
serve: {
port: 3334,
path: "/voice/webhook",
},
// Webhook security (recommended for tunnels/proxies)
webhookSecurity: {
allowedHosts: ["voice.example.com"],
trustedProxyIPs: ["100.64.0.1"],
},
// Public exposure (pick one)
// publicUrl: "https://example.ngrok.app/voice/webhook",
// tunnel: { provider: "ngrok" },
// tailscale: { mode: "funnel", path: "/voice/webhook" },
outbound: {
defaultMode: "notify", // notify | conversation
},
streaming: { enabled: true /* see Streaming transcription */ },
realtime: { enabled: false /* see Realtime voice */ },
},
},
},
},
}
- Twilio、Telnyx 和 Plivo 都需要一个 可公开访问 的 webhook URL。
- mock 是本地开发提供商(不进行网络调用)。
- Telnyx 需要 telnyx.publicKey(或 TELNYX_PUBLIC_KEY),除非 skipSignatureVerification 为 true。
- skipSignatureVerification 仅用于本地测试。
- 在 ngrok 免费层上,将 publicUrl 设置为确切的 ngrok URL;签名验证始终强制执行。
- tunnel.allowNgrokFreeTierLoopbackBypass: true 仅在 tunnel.provider="ngrok" 且 serve.bind 为 loopback(ngrok 本地代理)时,允许带无效签名的 Twilio webhook。仅限本地开发。
- Ngrok 免费层 URL 可能会变化或添加插页行为;如果 publicUrl 漂移,Twilio 签名会失败。生产环境:优先使用稳定域名或 Tailscale funnel。
- streaming.preStartTimeoutMs 会关闭从未发送有效 start 帧的套接字。
- streaming.maxPendingConnections 限制未认证的预启动套接字总数。
- streaming.maxPendingConnectionsPerIp 限制每个来源 IP 的未认证预启动套接字数量。
- streaming.maxConnections 限制打开的媒体流套接字总数(待处理 + 活跃)。
使用 provider: "log"、twilio.from 或旧版
streaming.* OpenAI 键的旧配置会由 openclaw doctor --fix
重写。目前运行时回退仍会接受旧的语音通话键,但
重写路径是 openclaw doctor --fix,兼容填隙层是
临时的。
自动迁移的流式传输键:
- `streaming.sttProvider` → `streaming.provider`
- `streaming.openaiApiKey` → `streaming.providers.openai.apiKey`
- `streaming.sttModel` → `streaming.providers.openai.model`
- `streaming.silenceDurationMs` → `streaming.providers.openai.silenceDurationMs`
- `streaming.vadThreshold` → `streaming.providers.openai.vadThreshold`
会话作用域
默认情况下,语音通话使用 sessionScope: "per-phone",这样来自
同一来电者的重复通话会保留对话记忆。当每个运营商通话都应从
全新上下文开始时,请设置 sessionScope: "per-call",例如接待、
预约、IVR,或同一个电话号码可能代表不同会议的 Google Meet 桥接流程。
实时语音对话
realtime 为实时通话音频选择一个全双工实时语音提供商。
它独立于 streaming,后者只会将音频转发给
实时转录提供商。
realtime.enabled 不能与 streaming.enabled 组合使用。每次通话请选择一个
音频模式。
当前运行时行为:
- Twilio Media Streams 支持
realtime.enabled。 realtime.provider是可选的。如果未设置,语音通话会使用第一个已注册的实时语音提供商。- 内置实时语音提供商:Google Gemini Live(
google)和 OpenAI(openai),由各自的提供商插件注册。 - 提供商自有原始配置位于
realtime.providers.<providerId>下。 - 语音通话默认公开共享的
openclaw_agent_consult实时工具。当来电者请求更深入的推理、当前信息或普通 OpenClaw 工具时,实时模型可以调用它。 realtime.consultPolicy可选地添加指导,用于说明实时模型何时应调用openclaw_agent_consult。realtime.agentContext.enabled默认关闭。启用后,语音通话会在会话设置时向实时提供商指令中注入有界智能体身份、系统提示覆盖,以及选定的工作区文件胶囊。realtime.fastContext.enabled默认关闭。启用后,语音通话会先针对咨询问题搜索已索引的记忆/会话上下文,并在realtime.fastContext.timeoutMs内将这些片段返回给实时模型;只有当realtime.fastContext.fallbackToConsult为 true 时,才会回退到完整咨询智能体。- 如果
realtime.provider指向未注册的提供商,或根本没有注册任何实时语音提供商,语音通话会记录警告并跳过实时媒体,而不是让整个插件失败。 - 咨询会话键会在可用时复用已存储的通话会话,然后回退到配置的
sessionScope(默认为per-phone,隔离通话为per-call)。
工具策略
realtime.toolPolicy 控制咨询运行:
| 策略 | 行为 |
|---|---|
safe-read-only |
暴露咨询工具,并将常规智能体限制为 read、web_search、web_fetch、x_search、memory_search 和 memory_get。 |
owner |
暴露咨询工具,并让常规智能体使用正常的智能体工具策略。 |
none |
不暴露咨询工具。自定义 realtime.tools 仍会传递给实时提供商。 |
realtime.consultPolicy 仅控制实时模型指令:
| 策略 | 指导 |
|---|---|
auto |
保留默认提示,并让提供商决定何时调用咨询工具。 |
substantive |
直接回答简单的对话衔接内容,并在事实、记忆、工具或上下文之前进行咨询。 |
always |
在每个实质性回答之前进行咨询。 |
智能体语音上下文
当语音桥接应听起来像配置的 OpenClaw 智能体,同时又不想为
普通轮次支付完整智能体咨询往返开销时,启用 realtime.agentContext。
上下文胶囊会在创建实时会话时添加一次,因此不会增加每轮延迟。
对 openclaw_agent_consult 的调用仍会运行完整的 OpenClaw 智能体,
并且应被用于工具工作、当前信息、记忆查找或工作区状态。
{
plugins: {
entries: {
"voice-call": {
config: {
agentId: "main",
realtime: {
enabled: true,
provider: "google",
toolPolicy: "safe-read-only",
consultPolicy: "substantive",
agentContext: {
enabled: true,
maxChars: 6000,
includeIdentity: true,
includeSystemPrompt: true,
includeWorkspaceFiles: true,
files: ["SOUL.md", "IDENTITY.md", "USER.md"],
},
},
},
},
},
},
}
实时提供商示例
默认值:API 密钥来自 realtime.providers.google.apiKey、
GEMINI_API_KEY 或 GOOGLE_GENERATIVE_AI_API_KEY;模型为
gemini-2.5-flash-native-audio-preview-12-2025;语音为 Kore。
sessionResumption 和 contextWindowCompression 默认开启,适用于更长且
可重连的通话。使用 silenceDurationMs、startSensitivity 和
endSensitivity 来调优电话音频上更快的轮次交替。
```json5
{
plugins: {
entries: {
"voice-call": {
config: {
provider: "twilio",
inboundPolicy: "allowlist",
allowFrom: ["+15550005678"],
realtime: {
enabled: true,
provider: "google",
instructions: "Speak briefly. Call openclaw_agent_consult before using deeper tools.",
toolPolicy: "safe-read-only",
consultPolicy: "substantive",
consultThinkingLevel: "low",
consultFastMode: true,
agentContext: { enabled: true },
providers: {
google: {
apiKey: "${GEMINI_API_KEY}",
model: "gemini-2.5-flash-native-audio-preview-12-2025",
voice: "Kore",
silenceDurationMs: 500,
startSensitivity: "high",
},
},
},
},
},
},
},
}
```
json5
{
plugins: {
entries: {
"voice-call": {
config: {
realtime: {
enabled: true,
provider: "openai",
providers: {
openai: { apiKey: "${OPENAI_API_KEY}" },
},
},
},
},
},
},
}
请参阅 Google 提供商 和
OpenAI provider,了解提供商特定的实时语音
选项。
流式转录
streaming 为实时通话音频选择实时转录提供商。
当前运行时行为:
streaming.provider是可选项。如果未设置,Voice Call 会使用第一个已注册的实时转录提供商。- 内置实时转录提供商:Deepgram(
deepgram)、ElevenLabs(elevenlabs)、Mistral(mistral)、OpenAI(openai)和 xAI(xai),它们由各自的提供商插件注册。 - 提供商拥有的原始配置位于
streaming.providers.<providerId>下。 - Twilio 发送已接受流的
start消息后,Voice Call 会立即注册该流,在提供商连接期间通过转录提供商排队入站媒体,并且只有在实时转录就绪后才开始初始问候。 - 如果
streaming.provider指向未注册的提供商,或者没有注册任何提供商,Voice Call 会记录一条警告并跳过媒体流式传输,而不是让整个插件失败。
流式传输提供商示例
默认值:API 密钥 streaming.providers.openai.apiKey 或
OPENAI_API_KEY;模型 gpt-4o-transcribe;silenceDurationMs: 800;
vadThreshold: 0.5。
```json5
{
plugins: {
entries: {
"voice-call": {
config: {
streaming: {
enabled: true,
provider: "openai",
streamPath: "/voice/stream",
providers: {
openai: {
apiKey: "sk-...", // optional if OPENAI_API_KEY is set
model: "gpt-4o-transcribe",
silenceDurationMs: 800,
vadThreshold: 0.5,
},
},
},
},
},
},
},
}
```
默认值:API 密钥 streaming.providers.xai.apiKey 或 XAI_API_KEY;
端点 wss://api.x.ai/v1/stt;编码 mulaw;采样率 8000;
endpointingMs: 800;interimResults: true。
```json5
{
plugins: {
entries: {
"voice-call": {
config: {
streaming: {
enabled: true,
provider: "xai",
streamPath: "/voice/stream",
providers: {
xai: {
apiKey: "${XAI_API_KEY}", // optional if XAI_API_KEY is set
endpointingMs: 800,
language: "en",
},
},
},
},
},
},
},
}
```
通话 TTS
Voice Call 使用核心 messages.tts 配置为通话提供流式
语音。你可以在插件配置下以
相同结构覆盖它,它会与 messages.tts 深度合并。
{
tts: {
provider: "elevenlabs",
providers: {
elevenlabs: {
voiceId: "pMsXgVXv3BLzUgSXRplE",
modelId: "eleven_multilingual_v2",
},
},
},
}
Microsoft 语音在语音通话中会被忽略。 电话音频需要 PCM;
当前 Microsoft 传输不暴露电话 PCM 输出。
行为说明:
- 插件配置中旧版
tts.<provider>键(openai、elevenlabs、microsoft、edge)会由openclaw doctor --fix修复;已提交的配置应使用tts.providers.<provider>。 - 启用 Twilio 媒体流式传输时会使用核心 TTS;否则通话会回退到提供商原生语音。
- 如果 Twilio 媒体流已经处于活动状态,Voice Call 不会回退到 TwiML
<Say>。如果该状态下电话 TTS 不可用,播放请求会失败,而不是混合两条播放路径。 - 当电话 TTS 回退到次级提供商时,Voice Call 会记录一条包含提供商链(
from、to、attempts)的警告,以便调试。 - 当 Twilio 插话或流拆除清空待处理 TTS 队列时,排队的播放请求会完成结算,而不是让等待播放完成的来电者一直挂起。
TTS 示例
{
messages: {
tts: {
provider: "openai",
providers: {
openai: { voice: "alloy" },
},
},
},
}
{
plugins: {
entries: {
"voice-call": {
config: {
tts: {
provider: "elevenlabs",
providers: {
elevenlabs: {
apiKey: "elevenlabs_key",
voiceId: "pMsXgVXv3BLzUgSXRplE",
modelId: "eleven_multilingual_v2",
},
},
},
},
},
},
},
}
{
plugins: {
entries: {
"voice-call": {
config: {
tts: {
providers: {
openai: {
model: "gpt-4o-mini-tts",
voice: "marin",
},
},
},
},
},
},
},
}
入站通话
入站策略默认为 disabled。要启用入站通话,请设置:
{
inboundPolicy: "allowlist",
allowFrom: ["+15550001234"],
inboundGreeting: "Hello! How can I help?",
}
inboundPolicy: "allowlist" 是低保证级别的来电显示筛选。该
插件会规范化提供商提供的 From 值,并将其与
allowFrom 比较。Webhook 验证会认证提供商投递和
载荷完整性,但它不能证明 PSTN/VoIP 来电号码
所有权。请将 allowFrom 视为来电显示过滤,而不是强来电者
身份。
自动响应使用智能体系统。通过 responseModel、
responseSystemPrompt 和 responseTimeoutMs 进行调优。
按号码路由
当一个 Voice Call 插件接收多个电话号码的通话,并且每个号码都应像不同线路一样运行时,请使用 numbers。例如,一个
号码可以使用随意的个人助理,而另一个号码使用商务
人设、不同的响应智能体以及不同的 TTS 语音。
路由会根据提供商提供的被叫 To 号码选择。键必须是
E.164 号码。通话到达时,Voice Call 会解析一次匹配路由,
将匹配的路由存储到通话记录中,并为问候、经典自动响应路径、实时咨询路径以及 TTS
播放复用该生效配置。如果没有路由匹配,则使用全局 Voice Call 配置。
出站通话不使用 numbers;发起通话时请显式传入出站目标、消息和
会话。
路由覆盖目前支持:
inboundGreetingttsagentIdresponseModelresponseSystemPromptresponseTimeoutMs
tts 路由值会深度合并到全局 Voice Call tts 配置之上,因此
你通常只需要覆盖提供商语音:
{
inboundGreeting: "Hello from the main line.",
responseSystemPrompt: "You are the default voice assistant.",
tts: {
provider: "openai",
providers: {
openai: { voice: "coral" },
},
},
numbers: {
"+15550001111": {
inboundGreeting: "Silver Fox Cards, how can I help?",
responseSystemPrompt: "You are a concise baseball card specialist.",
tts: {
providers: {
openai: { voice: "alloy" },
},
},
},
},
}
口语输出契约
对于自动响应,Voice Call 会向系统提示追加严格的口语输出契约:
{"spoken":"..."}
Voice Call 会防御性地提取语音文本:
- 忽略标记为推理/错误内容的载荷。
- 解析直接 JSON、围栏 JSON 或内联
"spoken"键。 - 回退到纯文本,并移除可能的规划/元信息开头段落。
这会让语音播放聚焦于面向来电者的文本,并避免
将规划文本泄露到音频中。
对话启动行为
对于出站 conversation 通话,首条消息处理会绑定到实时
播放状态:
- 只有在初始问候正在主动播报时,才会抑制插话队列清空和自动响应。
- 如果初始播放失败,通话会返回
listening,并且初始消息会保留在队列中以便重试。 - Twilio 流式传输的初始播放会在流连接时启动,没有额外延迟。
- 插话会中止活动播放,并清除已排队但尚未播放的 Twilio TTS 条目。被清除的条目会解析为已跳过,因此后续响应逻辑可以继续,而不必等待永远不会播放的音频。
- 实时语音对话使用实时流自己的开场轮次。Voice Call 不会为该初始消息发布旧版
<Say>TwiML 更新,因此出站<Connect><Stream>会话会保持附加状态。
Twilio 流断开宽限期
当 Twilio 媒体流断开连接时,Voice Call 会等待 2000 ms,然后
自动结束通话:
- 如果流在该窗口内重新连接,则会取消自动结束。
- 如果宽限期后没有流重新注册,则会结束通话,以防止活动通话卡住。
陈旧通话清理器
使用 staleCallReaperSeconds 来结束从未收到终止
webhook 的通话(例如,从未完成的通知模式通话)。默认值
为 0(禁用)。
建议范围:
- 生产环境: 对于通知式流程,使用
120–300秒。 - 保持此值高于
maxDurationSeconds,这样正常调用才能完成。一个好的起点是maxDurationSeconds + 30–60秒。
{
plugins: {
entries: {
"voice-call": {
config: {
maxDurationSeconds: 300,
staleCallReaperSeconds: 360,
},
},
},
},
}
Webhook 安全
当代理或隧道位于 Gateway 网关 前面时,插件会重建用于签名验证的公共 URL。这些选项控制信任哪些转发头:
允许来自转发头的主机。
在没有允许列表的情况下信任转发头。
仅当请求远端 IP 匹配列表时才信任转发头。
其他保护措施:
- 已为 Twilio 和 Plivo 启用 Webhook 重放保护。重放的有效 Webhook 请求会被确认,但会跳过副作用。
- Twilio 对话轮次在
<Gather>回调中包含每轮 token,因此过期或重放的语音回调无法满足更新的待处理转录轮次。 - 当提供商所需的签名头缺失时,未认证的 Webhook 请求会在读取正文之前被拒绝。
- voice-call Webhook 使用共享的预认证正文配置(64 KB / 5 秒),并在签名验证前加上每 IP 的进行中请求上限。
使用稳定公共主机的示例:
{
plugins: {
entries: {
"voice-call": {
config: {
publicUrl: "https://voice.example.com/voice/webhook",
webhookSecurity: {
allowedHosts: ["voice.example.com"],
},
},
},
},
},
}
CLI
openclaw voicecall call --to "+15555550123" --message "Hello from OpenClaw"
openclaw voicecall start --to "+15555550123" # alias for call
openclaw voicecall continue --call-id <id> --message "Any questions?"
openclaw voicecall speak --call-id <id> --message "One moment"
openclaw voicecall dtmf --call-id <id> --digits "ww123456#"
openclaw voicecall end --call-id <id>
openclaw voicecall status --call-id <id>
openclaw voicecall tail
openclaw voicecall latency # summarize turn latency from logs
openclaw voicecall expose --mode funnel
当 Gateway 网关 已在运行时,操作性 voicecall 命令会委托给 Gateway 网关 所属的 voice-call 运行时,因此 CLI 不会绑定第二个 Webhook 服务器。如果无法访问 Gateway 网关,这些命令会回退到独立的 CLI 运行时。
latency 会从默认的 voice-call 存储路径读取 calls.jsonl。使用 --file <path> 指向其他日志,使用 --last <n> 将分析限制为最后 N 条记录(默认 200)。输出包含轮次延迟和监听等待时间的 p50/p90/p99。
智能体工具
工具名称:voice_call。
| 操作 | 参数 |
|---|---|
initiate_call |
message, to?, mode?, dtmfSequence? |
continue_call |
callId, message |
speak_to_user |
callId, message |
send_dtmf |
callId, digits |
end_call |
callId |
get_status |
callId |
此仓库在 skills/voice-call/SKILL.md 中附带了匹配的 skill 文档。
Gateway 网关 RPC
| 方法 | 参数 |
|---|---|
voicecall.initiate |
to?, message, mode?, dtmfSequence? |
voicecall.continue |
callId, message |
voicecall.speak |
callId, message |
voicecall.dtmf |
callId, digits |
voicecall.end |
callId |
voicecall.status |
callId |
dtmfSequence 仅在 mode: "conversation" 下有效。通知模式调用如果需要连接后的数字,应在调用存在后使用 voicecall.dtmf。
故障排除
设置无法通过 Webhook 暴露检查
从运行 Gateway 网关 的同一环境运行设置:
openclaw voicecall setup
openclaw voicecall setup --json
对于 twilio、telnyx 和 plivo,webhook-exposure 必须为绿色。已配置的 publicUrl 如果指向本地或专用网络空间,仍会失败,因为运营商无法回拨这些地址。不要将 localhost、127.0.0.1、0.0.0.0、10.x、172.16.x-172.31.x、192.168.x、169.254.x、fc00::/7 或 fd00::/8 用作 publicUrl。
Twilio 通知模式外呼会在创建调用请求中直接发送初始 <Say> TwiML,因此第一条语音消息不依赖 Twilio 获取 Webhook TwiML。状态回调、对话调用、连接前 DTMF、实时流和连接后调用控制仍然需要公共 Webhook。
使用一个公共暴露路径:
{
plugins: {
entries: {
"voice-call": {
config: {
publicUrl: "https://voice.example.com/voice/webhook",
// or
tunnel: { provider: "ngrok" },
// or
tailscale: { mode: "funnel", path: "/voice/webhook" },
},
},
},
},
}
更改配置后,重启或重新加载 Gateway 网关,然后运行:
openclaw voicecall setup
openclaw voicecall smoke
除非传入 --yes,否则 voicecall smoke 是一次演练。
提供商凭证失败
检查所选提供商和必需的凭证字段:
- Twilio:
twilio.accountSid、twilio.authToken和fromNumber,或TWILIO_ACCOUNT_SID、TWILIO_AUTH_TOKEN和TWILIO_FROM_NUMBER。 - Telnyx:
telnyx.apiKey、telnyx.connectionId、telnyx.publicKey和fromNumber。 - Plivo:
plivo.authId、plivo.authToken和fromNumber。
凭证必须存在于 Gateway 网关 主机上。编辑本地 shell profile 不会影响已经运行的 Gateway 网关,直到它重启或重新加载其环境。
调用已开始但提供商 Webhook 未到达
确认提供商控制台指向确切的公共 Webhook URL:
https://voice.example.com/voice/webhook
然后检查运行时状态:
openclaw voicecall status --call-id <id>
openclaw voicecall tail
openclaw logs --follow
常见原因:
publicUrl指向的路径与serve.path不同。- 隧道 URL 在 Gateway 网关 启动后发生变化。
- 代理转发请求但剥离或重写了 host/proto 头。
- 防火墙或 DNS 将公共主机名路由到了 Gateway 网关 之外的位置。
- Gateway 网关 重启时未启用 Voice Call 插件。
当反向代理或隧道位于 Gateway 网关 前面时,将 webhookSecurity.allowedHosts 设置为公共主机名,或对已知代理地址使用 webhookSecurity.trustedProxyIPs。仅当代理边界在你的控制之下时,才使用 webhookSecurity.trustForwardingHeaders。
签名验证失败
提供商签名会根据 OpenClaw 从传入请求中重建的公共 URL 进行检查。如果签名失败:
- 确认提供商 Webhook URL 与
publicUrl完全匹配,包括协议、主机和路径。 - 对于 ngrok 免费层 URL,当隧道主机名变化时更新
publicUrl。 - 确保代理保留原始 host 和 proto 头,或配置
webhookSecurity.allowedHosts。 - 不要在本地测试之外启用
skipSignatureVerification。
Google Meet Twilio 加入失败
Google Meet 使用此插件进行 Twilio 拨入加入。首先验证 Voice Call:
openclaw voicecall setup
openclaw voicecall smoke --to "+15555550123"
然后显式验证 Google Meet 传输:
openclaw googlemeet setup --transport twilio
如果 Voice Call 为绿色但 Meet 参与者始终未加入,请检查 Meet 拨入号码、PIN 和 --dtmf-sequence。电话呼叫可能是健康的,但会议可能会拒绝或忽略错误的 DTMF 序列。
Google Meet 通过 voicecall.start 使用连接前 DTMF 序列启动 Twilio 电话腿。基于 PIN 生成的序列会包含 Google Meet 插件的 voiceCall.dtmfDelayMs,作为前置 Twilio 等待数字。默认值为 12 秒,因为 Meet 拨入提示可能较晚出现。Voice Call 随后会在请求介绍问候语之前重定向回实时处理。
使用 openclaw logs --follow 查看实时阶段跟踪。健康的 Twilio Meet 加入会按以下顺序记录日志:
- Google Meet 将 Twilio 加入委托给 Voice Call。
- Voice Call 存储连接前 DTMF TwiML。
- Twilio 初始 TwiML 在实时处理前被消费并提供。
- Voice Call 为 Twilio 调用提供实时 TwiML。
- Google Meet 在 DTMF 后延迟之后使用
voicecall.speak请求介绍语音。
openclaw voicecall tail 仍会显示持久化的调用记录;它对调用状态和转录很有用,但并非每个 Webhook/实时转换都会出现在其中。
实时调用没有语音
确认仅启用一种音频模式。realtime.enabled 和 streaming.enabled 不能同时为 true。
对于实时 Twilio 调用,还要验证:
- 已加载并注册实时提供商插件。
realtime.provider未设置或命名了已注册的提供商。- 提供商 API key 可供 Gateway 网关 进程使用。
openclaw logs --follow显示实时 TwiML 已提供、实时桥接已启动,并且初始问候语已排队。
相关
📄 Zalo 个人插件
原文:https://docs.openclaw.ai/zh-CN/plugins/zalouser
通过插件为 OpenClaw 提供 Zalo Personal 支持,使用原生 zca-js 自动化普通 Zalo 用户账号。
非官方自动化可能导致账号被暂停或封禁。使用风险自负。
命名
渠道 ID 是 zalouser,用于明确表示这会自动化一个个人 Zalo 用户账号(非官方)。我们保留 zalo,以备未来可能的官方 Zalo API 集成使用。
运行位置
此插件在 Gateway 网关进程内部运行。
如果你使用远程 Gateway 网关,请在运行 Gateway 网关的机器上安装/配置它,然后重启 Gateway 网关。
不需要外部 zca/openzca CLI 二进制文件。
安装
选项 A:从 npm 安装
openclaw plugins install @openclaw/zalouser
使用裸包名可跟随当前官方发布标签。仅在你需要可复现安装时,才固定精确版本。
之后重启 Gateway 网关。
选项 B:从本地文件夹安装(开发)
PLUGIN_SRC=./path/to/local/zalouser-plugin
openclaw plugins install "$PLUGIN_SRC"
cd "$PLUGIN_SRC" && pnpm install
之后重启 Gateway 网关。
配置
渠道配置位于 channels.zalouser 下(不是 plugins.entries.*):
{
channels: {
zalouser: {
enabled: true,
dmPolicy: "pairing",
},
},
}
CLI
openclaw channels login --channel zalouser
openclaw channels logout --channel zalouser
openclaw channels status --probe
openclaw message send --channel zalouser --target <threadId> --message "Hello from OpenClaw"
openclaw directory peers list --channel zalouser --query "name"
Agent 工具
工具名称:zalouser
操作:send、image、link、friends、groups、me、status
渠道消息操作还支持用于消息回应的 react。
相关内容
📄 插件清单
原文:https://docs.openclaw.ai/zh-CN/plugins/manifest
此页面仅适用于 OpenClaw 原生插件清单。
有关兼容的包布局,请参阅 插件包。
兼容的包格式使用不同的清单文件:
- Codex 包:
.codex-plugin/plugin.json - Claude 包:
.claude-plugin/plugin.json,或不带清单的默认 Claude 组件
布局 - Cursor 包:
.cursor-plugin/plugin.json
OpenClaw 也会自动检测这些包布局,但不会根据此处描述的
openclaw.plugin.json 架构验证它们。
对于兼容包,当布局符合 OpenClaw 运行时期望时,OpenClaw 当前会读取包元数据以及声明的
技能根目录、Claude 命令根目录、Claude 包 settings.json 默认值、
Claude 包 LSP 默认值,以及受支持的钩子包。
每个 OpenClaw 原生插件都必须在插件根目录中提供一个
openclaw.plugin.json 文件。OpenClaw 使用此清单在不执行插件代码的情况下验证配置。缺失或无效的清单会被视为插件错误,并会阻止配置验证。
请参阅完整的插件系统指南:插件。
有关原生能力模型和当前外部兼容性指导:
能力模型。
此文件的作用
openclaw.plugin.json 是 OpenClaw 在加载你的插件代码之前读取的元数据。下面的所有内容都必须足够轻量,能够在不启动插件运行时的情况下检查。
用于:
- 插件身份、配置验证和配置 UI 提示
- 凭证、新手引导和设置元数据(别名、自动启用、提供商环境变量、凭证选项)
- 控制平面界面的激活提示
- 模型系列所有权简写
- 静态能力所有权快照(
contracts) - 共享
openclaw qa宿主可以检查的 QA 运行器元数据 - 合并到目录和验证界面的渠道专用配置元数据
不要用于:注册运行时行为、声明代码入口点,
或 npm install 元数据。这些应放在你的插件代码和 package.json 中。
最小示例
{
"id": "voice-call",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {}
}
}
完整示例
{
"id": "openrouter",
"name": "OpenRouter",
"description": "OpenRouter provider plugin",
"version": "1.0.0",
"providers": ["openrouter"],
"modelSupport": {
"modelPrefixes": ["router-"]
},
"modelIdNormalization": {
"providers": {
"openrouter": {
"prefixWhenBare": "openrouter"
}
}
},
"providerEndpoints": [
{
"endpointClass": "openrouter",
"hostSuffixes": ["openrouter.ai"]
}
],
"providerRequest": {
"providers": {
"openrouter": {
"family": "openrouter"
}
}
},
"cliBackends": ["openrouter-cli"],
"syntheticAuthRefs": ["openrouter-cli"],
"providerAuthEnvVars": {
"openrouter": ["OPENROUTER_API_KEY"]
},
"providerAuthAliases": {
"openrouter-coding": "openrouter"
},
"channelEnvVars": {
"openrouter-chatops": ["OPENROUTER_CHATOPS_TOKEN"]
},
"providerAuthChoices": [
{
"provider": "openrouter",
"method": "api-key",
"choiceId": "openrouter-api-key",
"choiceLabel": "OpenRouter API key",
"groupId": "openrouter",
"groupLabel": "OpenRouter",
"optionKey": "openrouterApiKey",
"cliFlag": "--openrouter-api-key",
"cliOption": "--openrouter-api-key <key>",
"cliDescription": "OpenRouter API key",
"onboardingScopes": ["text-inference"]
}
],
"uiHints": {
"apiKey": {
"label": "API key",
"placeholder": "sk-or-v1-...",
"sensitive": true
}
},
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": {
"type": "string"
}
}
}
}
顶层字段参考
| 字段 | 必需 | 类型 | 含义 |
|---|---|---|---|
id |
是 | string |
规范插件 id。这是 plugins.entries.<id> 中使用的 id。 |
configSchema |
是 | object |
此插件配置的内联 JSON Schema。 |
enabledByDefault |
否 | true |
将内置插件标记为默认启用。省略它,或设置任何非 true 值,可使插件默认保持禁用。 |
enabledByDefaultOnPlatforms |
否 | string[] |
仅在列出的 Node.js 平台上将内置插件标记为默认启用,例如 ["darwin"]。显式配置仍然优先。 |
legacyPluginIds |
否 | string[] |
会规范化为此规范插件 id 的旧版 id。 |
autoEnableWhenConfiguredProviders |
否 | string[] |
当凭证、配置或模型引用提到这些提供商 id 时,应自动启用此插件。 |
kind |
否 | "memory" | "context-engine" |
声明 plugins.slots.* 使用的互斥插件类型。 |
channels |
否 | string[] |
此插件拥有的渠道 id。用于设备发现和配置验证。 |
providers |
否 | string[] |
此插件拥有的提供商 id。 |
providerCatalogEntry |
否 | string |
轻量级提供商目录模块路径,相对于插件根目录,用于清单作用域的提供商目录元数据;可在不激活完整插件运行时的情况下加载。 |
modelSupport |
否 | object |
清单拥有的简写模型系列元数据,用于在运行时之前自动加载插件。 |
modelCatalog |
否 | object |
此插件拥有的提供商的声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的控制平面契约,无需加载插件运行时。 |
modelPricing |
否 | object |
提供商拥有的外部定价查找策略。使用它可让本地/自托管提供商选择退出远程定价目录,或将提供商引用映射到 OpenRouter/LiteLLM 目录 id,而无需在核心中硬编码提供商 id。 |
modelIdNormalization |
否 | object |
提供商拥有的模型 id 别名/前缀清理,必须在提供商运行时加载之前运行。 |
providerEndpoints |
否 | object[] |
清单拥有的端点 host/baseUrl 元数据,用于核心必须在提供商运行时加载之前分类的提供商路由。 |
providerRequest |
否 | object |
轻量级提供商系列和请求兼容性元数据,由通用请求策略在提供商运行时加载之前使用。 |
cliBackends |
否 | string[] |
此插件拥有的 CLI 推理后端 id。用于从显式配置引用在启动时自动激活。 |
syntheticAuthRefs |
否 | string[] |
提供商或 CLI 后端引用,其插件拥有的合成凭证钩子应在运行时加载之前的冷启动模型发现期间被探测。 |
nonSecretAuthMarkers |
否 | string[] |
内置插件拥有的占位符 API key 值,表示非秘密的本地、OAuth 或环境凭证状态。 |
commandAliases |
否 | object[] |
此插件拥有的命令名称,应在运行时加载之前生成具备插件感知能力的配置和 CLI 诊断。 |
providerAuthEnvVars |
否 | Record<string, string[]> |
已弃用的兼容环境变量元数据,用于提供商凭证/Status 查找。新插件首选 setup.providers[].envVars;OpenClaw 在弃用窗口期内仍会读取此字段。 |
providerAuthAliases |
否 | Record<string, string> |
应复用另一个提供商 id 进行凭证查找的提供商 id,例如共享基础提供商 API key 和凭证配置文件的编码提供商。 |
channelEnvVars |
否 | Record<string, string[]> |
轻量级渠道环境变量元数据,OpenClaw 可在不加载插件代码的情况下检查。将其用于通用启动/配置助手应看到的环境变量驱动渠道设置或凭证界面。 |
providerAuthChoices |
否 | object[] |
轻量级凭证选项元数据,用于新手引导选择器、首选提供商解析以及简单 CLI 标志接线。 |
activation |
否 | object |
轻量级激活规划器元数据,用于启动、提供商、命令、渠道、路由和能力触发的加载。仅为元数据;插件运行时仍拥有实际行为。 |
setup |
否 | object |
轻量级设置/新手引导描述符,供发现和设置界面在不加载插件运行时的情况下检查。 |
qaRunners |
否 | object[] |
共享 openclaw qa 宿主在插件运行时加载之前使用的轻量级 QA 运行器描述符。 |
contracts |
否 | object |
外部凭证钩子、语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、web-fetch、Web 搜索和工具所有权的静态能力所有权快照。 |
mediaUnderstandingProviderMetadata |
否 | Record<string, object> |
contracts.mediaUnderstandingProviders 中声明的提供商 id 的轻量级媒体理解默认值。 |
imageGenerationProviderMetadata |
否 | Record<string, object> |
contracts.imageGenerationProviders 中声明的提供商 id 的轻量级图像生成凭证元数据,包括提供商拥有的凭证别名和 base-url 防护。 |
videoGenerationProviderMetadata |
否 | Record<string, object> |
contracts.videoGenerationProviders 中声明的提供商 id 的轻量级视频生成凭证元数据,包括提供商拥有的凭证别名和 base-url 防护。 |
musicGenerationProviderMetadata |
否 | Record<string, object> |
contracts.musicGenerationProviders 中声明的提供商 id 的轻量级音乐生成凭证元数据,包括提供商拥有的凭证别名和 base-url 防护。 |
toolMetadata |
否 | Record<string, object> |
contracts.tools 中声明的插件拥有工具的轻量级可用性元数据。当工具只有在存在配置、环境变量或凭证证据时才应加载运行时时使用它。 |
channelConfigs |
否 | Record<string, object> |
清单拥有的渠道配置元数据,会在运行时加载之前合并到发现和验证界面中。 |
skills |
否 | string[] |
要加载的 Skills 目录,相对于插件根目录。 |
name |
否 | string |
人类可读的插件名称。 |
description |
否 | string |
插件界面中显示的简短摘要。 |
version |
否 | string |
仅供参考的插件版本。 |
uiHints |
否 | Record<string, object> |
配置字段的界面标签、占位符和敏感性提示。 |
生成提供商元数据参考
生成提供商元数据字段描述在匹配的 contracts.*GenerationProviders 列表中声明的提供商的静态凭证信号。
OpenClaw 会在提供商运行时加载前读取这些字段,因此核心工具无需导入每个提供商插件,就能判断某个生成提供商是否可用。
这些字段仅用于廉价的声明式事实。传输、请求转换、令牌刷新、凭证验证以及实际生成行为都保留在插件运行时中。
{
"contracts": {
"imageGenerationProviders": ["example-image"]
},
"imageGenerationProviderMetadata": {
"example-image": {
"aliases": ["example-image-oauth"],
"authProviders": ["example-image"],
"configSignals": [
{
"rootPath": "plugins.entries.example-image.config",
"overlayPath": "image",
"mode": {
"path": "mode",
"default": "local",
"allowed": ["local"]
},
"requiredAny": ["workflow", "workflowPath"],
"required": ["promptNodeId"]
}
],
"authSignals": [
{
"provider": "example-image"
},
{
"provider": "example-image-oauth",
"providerBaseUrl": {
"provider": "example-image",
"defaultBaseUrl": "https://api.example.com/v1",
"allowedBaseUrls": ["https://api.example.com/v1"]
}
}
]
}
}
}
每个元数据条目支持:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
aliases |
否 | string[] |
应计为该生成提供商的静态凭证别名的其他提供商 ID。 |
authProviders |
否 | string[] |
其已配置凭证配置文件应计为该生成提供商凭证的提供商 ID。 |
configSignals |
否 | object[] |
用于本地或自托管提供商的廉价纯配置可用性信号,可在没有凭证配置文件或环境变量的情况下配置。 |
authSignals |
否 | object[] |
显式凭证信号。存在时,它们会替换来自提供商 ID、aliases 和 authProviders 的默认信号集。 |
每个 configSignals 条目支持:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
rootPath |
是 | string |
要检查的插件所拥有配置对象的点路径,例如 plugins.entries.example.config。 |
overlayPath |
否 | string |
根配置内的点路径,其对象应在评估信号前覆盖根对象。将它用于特定能力的配置,例如 image、video 或 music。 |
required |
否 | string[] |
有效配置内必须具有已配置值的点路径。字符串必须非空;对象和数组也不得为空。 |
requiredAny |
否 | string[] |
有效配置内的点路径,其中至少一个必须具有已配置值。 |
mode |
否 | object |
有效配置内可选的字符串模式保护。当纯配置可用性仅适用于一种模式时使用它。 |
每个 mode 保护支持:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
path |
否 | string |
有效配置内的点路径。默认为 mode。 |
default |
否 | string |
当配置省略该路径时使用的模式值。 |
allowed |
否 | string[] |
如果存在,仅当有效模式是这些值之一时,信号才会通过。 |
disallowed |
否 | string[] |
如果存在,当有效模式是这些值之一时,信号会失败。 |
每个 authSignals 条目支持:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
provider |
是 | string |
要在已配置凭证配置文件中检查的提供商 ID。 |
providerBaseUrl |
否 | object |
可选保护,仅当被引用的已配置提供商使用允许的基础 URL 时,才让该信号计入。仅当凭证别名只对某些 API 有效时使用它。 |
每个 providerBaseUrl 保护支持:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
provider |
是 | string |
其 baseUrl 应被检查的提供商配置 ID。 |
defaultBaseUrl |
否 | string |
当提供商配置省略 baseUrl 时假定的基础 URL。 |
allowedBaseUrls |
是 | string[] |
此凭证信号允许的基础 URL。当已配置或默认基础 URL 与这些规范化值之一不匹配时,该信号会被忽略。 |
工具元数据参考
toolMetadata 使用与生成提供商元数据相同形状的 configSignals 和 authSignals,并按工具名称作为键。contracts.tools 声明所有权。toolMetadata 声明廉价的可用性证据,因此 OpenClaw 可以避免仅为让工具工厂返回 null 而导入插件运行时。
{
"providerAuthEnvVars": {
"example": ["EXAMPLE_API_KEY"]
},
"contracts": {
"tools": ["example_search"]
},
"toolMetadata": {
"example_search": {
"authSignals": [
{
"provider": "example"
}
],
"configSignals": [
{
"rootPath": "plugins.entries.example.config",
"overlayPath": "search",
"required": ["apiKey"]
}
]
}
}
}
如果某个工具没有 toolMetadata,OpenClaw 会保留现有行为,并在工具契约匹配策略时加载拥有该工具的插件。对于其工厂依赖凭证/配置的热路径工具,插件作者应声明 toolMetadata,而不是让核心导入运行时来询问。
providerAuthChoices 参考
每个 providerAuthChoices 条目描述一个新手引导或凭证选择。
OpenClaw 会在提供商运行时加载前读取它。
提供商设置列表使用这些清单选择、由描述符派生的设置选择以及安装目录元数据,而无需加载提供商运行时。
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
provider |
是 | string |
此选择所属的提供商 ID。 |
method |
是 | string |
要分派到的凭证方法 ID。 |
choiceId |
是 | string |
新手引导和 CLI 流程使用的稳定凭证选择 ID。 |
choiceLabel |
否 | string |
面向用户的标签。如果省略,OpenClaw 会回退到 choiceId。 |
choiceHint |
否 | string |
选择器的简短辅助文本。 |
assistantPriority |
否 | number |
数值越低,在助手驱动的交互式选择器中排序越靠前。 |
assistantVisibility |
否 | "visible" | "manual-only" |
从助手选择器中隐藏该选择,同时仍允许手动 CLI 选择。 |
deprecatedChoiceIds |
否 | string[] |
应将用户重定向到此替代选择的旧版选择 ID。 |
groupId |
否 | string |
用于分组相关选择的可选组 ID。 |
groupLabel |
否 | string |
该组面向用户的标签。 |
groupHint |
否 | string |
该组的简短辅助文本。 |
optionKey |
否 | string |
用于简单单标志凭证流程的内部选项键。 |
cliFlag |
否 | string |
CLI 标志名称,例如 --openrouter-api-key。 |
cliOption |
否 | string |
完整 CLI 选项形态,例如 --openrouter-api-key <key>。 |
cliDescription |
否 | string |
CLI 帮助中使用的描述。 |
onboardingScopes |
否 | Array<"text-inference" \| "image-generation"> |
此选择应出现在哪些新手引导界面中。如果省略,默认为 ["text-inference"]。 |
commandAliases 参考
当插件拥有一个用户可能会误放进 plugins.allow,或尝试作为根 CLI 命令运行的运行时命令名称时,使用 commandAliases。OpenClaw 使用此元数据进行诊断,而不会导入插件运行时代码。
{
"commandAliases": [
{
"name": "dreaming",
"kind": "runtime-slash",
"cliCommand": "memory"
}
]
}
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
name |
是 | string |
属于此插件的命令名称。 |
kind |
否 | "runtime-slash" |
将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 |
cliCommand |
否 | string |
如果存在,建议用于 CLI 操作的相关根 CLI 命令。 |
activation 参考
当插件可以低成本声明哪些控制平面事件应将其包含在激活/加载计划中时,使用 activation。
此块是规划器元数据,不是生命周期 API。它不会注册运行时行为,不会替代 register(...),也不承诺插件代码已经执行。激活规划器使用这些字段先缩小候选插件范围,然后再回退到现有的清单所有权元数据,例如 providers、channels、commandAliases、setup.providers、contracts.tools 和钩子。
优先使用已经描述所有权的最窄元数据。当 providers、channels、commandAliases、设置描述符或 contracts 能表达这种关系时,请使用这些字段。将 activation 用于无法由这些所有权字段表示的额外规划器提示。
对于 claude-cli、codex-cli 或 google-gemini-cli 等 CLI 运行时别名,请使用顶层 cliBackends;activation.onAgentHarnesses 仅用于没有现有所有权字段的嵌入式 agent harness ID。
此块仅为元数据。它不会注册运行时行为,也不会替代 register(...)、setupEntry 或其他运行时/插件入口点。当前消费者将其用作更广泛插件加载前的缩窄提示,因此缺少非启动激活元数据通常只会影响性能;只要清单所有权回退仍然存在,它就不应改变正确性。
每个插件都应有意设置 activation.onStartup。只有当插件必须在 Gateway 网关启动期间运行时,才将其设为 true。当插件在启动时保持惰性,并且只应从更窄的触发器加载时,将其设为 false。省略 onStartup 不再会隐式地在启动时加载插件;请为启动、渠道、配置、agent harness、内存或其他更窄的激活触发器使用显式激活元数据。
{
"activation": {
"onStartup": false,
"onProviders": ["openai"],
"onCommands": ["models"],
"onChannels": ["web"],
"onRoutes": ["gateway-webhook"],
"onConfigPaths": ["browser"],
"onCapabilities": ["provider", "tool"]
}
}
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
onStartup |
否 | boolean |
显式 Gateway 网关启动激活。每个插件都应设置此项。true 会在启动期间导入插件;false 会让其在启动时保持惰性,除非另一个匹配的触发器需要加载。 |
onProviders |
否 | string[] |
应将此插件包含在激活/加载计划中的提供商 ID。 |
onAgentHarnesses |
否 | string[] |
应将此插件包含在激活/加载计划中的嵌入式 agent harness 运行时 ID。对于 CLI 后端别名,请使用顶层 cliBackends。 |
onCommands |
否 | string[] |
应将此插件包含在激活/加载计划中的命令 ID。 |
onChannels |
否 | string[] |
应将此插件包含在激活/加载计划中的渠道 ID。 |
onRoutes |
否 | string[] |
应将此插件包含在激活/加载计划中的路由种类。 |
onConfigPaths |
否 | string[] |
根相对配置路径;当路径存在且未被显式禁用时,应将此插件包含在启动/加载计划中。 |
onCapabilities |
否 | Array<"provider" \| "channel" \| "tool" \| "hook"> |
控制平面激活规划使用的宽泛能力提示。尽可能优先使用更窄的字段。 |
当前实时消费者:
- Gateway 网关启动规划使用
activation.onStartup进行显式启动导入 - 命令触发的 CLI 规划会回退到旧版
commandAliases[].cliCommand或commandAliases[].name - agent 运行时启动规划对嵌入式 harness 使用
activation.onAgentHarnesses,并对 CLI 运行时别名使用顶层cliBackends[] - 渠道触发的设置/渠道规划在缺少显式渠道激活元数据时,会回退到旧版
channels[]所有权 - 启动插件规划会对非渠道根配置表面使用
activation.onConfigPaths,例如内置浏览器插件的browser块 - 提供商触发的设置/运行时规划在缺少显式提供商激活元数据时,会回退到旧版
providers[]和顶层cliBackends[]所有权
规划器诊断可以区分显式激活提示和清单所有权回退。例如,activation-command-hint 表示匹配了 activation.onCommands,而 manifest-command-alias 表示规划器改用了 commandAliases 所有权。这些原因标签用于宿主诊断和测试;插件作者应持续声明最能描述所有权的元数据。
qaRunners 参考
当插件在共享的 openclaw qa 根命令下贡献一个或多个传输运行器时,使用 qaRunners。保持此元数据低成本且静态;插件运行时仍通过轻量级 runtime-api.ts 表面拥有实际 CLI 注册,该表面导出 qaRunnerCliRegistrations。
{
"qaRunners": [
{
"commandName": "matrix",
"description": "Run the Docker-backed Matrix live QA lane against a disposable homeserver"
}
]
}
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
commandName |
是 | string |
挂载在 openclaw qa 下的子命令,例如 matrix。 |
description |
否 | string |
当共享宿主需要存根命令时使用的回退帮助文本。 |
setup 参考
当设置和新手引导表面需要在运行时加载前获取低成本、插件拥有的元数据时,使用 setup。
{
"setup": {
"providers": [
{
"id": "openai",
"authMethods": ["api-key"],
"envVars": ["OPENAI_API_KEY"],
"authEvidence": [
{
"type": "local-file-with-env",
"fileEnvVar": "OPENAI_CREDENTIALS_FILE",
"requiresAllEnv": ["OPENAI_PROJECT"],
"credentialMarker": "openai-local-credentials",
"source": "openai local credentials"
}
]
}
],
"cliBackends": ["openai-cli"],
"configMigrations": ["legacy-openai-auth"],
"requiresRuntime": false
}
}
顶层 cliBackends 仍然有效,并继续描述 CLI 推断后端。setup.cliBackends 是面向应保持仅元数据的控制平面/设置流程的设置专用描述符表面。
存在时,setup.providers 和 setup.cliBackends 是设置发现的首选描述符优先查找表面。如果描述符只是缩小候选插件范围,而设置仍需要更丰富的设置期运行时钩子,请设置 requiresRuntime: true,并保留 setup-api 作为回退执行路径。
OpenClaw 还会将 setup.providers[].envVars 纳入通用提供商认证和环境变量查找。providerAuthEnvVars 在弃用窗口期间仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置/Status 环境元数据放在 setup.providers[].envVars 上。
当没有可用设置入口,或 setup.requiresRuntime: false 声明不需要设置运行时时,OpenClaw 也可以从 setup.providers[].authMethods 推导简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式 providerAuthChoices 条目仍然优先。
只有当这些描述符足以支撑设置表面时,才设置 requiresRuntime: false。OpenClaw 会将显式的 false 视为仅描述符契约,并且不会为设置查找执行 setup-api 或 openclaw.setupEntry。如果仅描述符插件仍发布其中一个设置运行时入口,OpenClaw 会报告一个增量诊断并继续忽略它。省略 requiresRuntime 会保留旧版回退行为,因此已经添加描述符但未添加该标志的现有插件不会中断。
由于设置查找可能会执行插件拥有的 setup-api 代码,规范化的 setup.providers[].id 和 setup.cliBackends[] 值必须在已发现插件之间保持唯一。有歧义的所有权会失败关闭,而不是根据发现顺序选择一个胜者。
当设置运行时确实执行时,如果 setup-api 注册了清单描述符未声明的提供商或 CLI 后端,或者某个描述符没有匹配的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是增量的,不会拒绝旧版插件。
setup.providers 参考
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
id |
是 | string |
在设置或新手引导期间公开的提供商 ID。保持规范化 ID 在全局唯一。 |
authMethods |
否 | string[] |
此提供商在不加载完整运行时的情况下支持的设置/认证方法 ID。 |
envVars |
否 | string[] |
通用设置/Status 表面可以在插件运行时加载前检查的环境变量。 |
authEvidence |
否 | object[] |
针对可通过非秘密标记进行认证的提供商的低成本本地认证证据检查。 |
authEvidence 用于提供商拥有的本地凭证标记,这些标记无需加载运行时代码即可验证。这些检查必须保持低成本且本地执行:不进行网络调用,不读取 keychain 或 secret-manager,不执行 shell 命令,也不探测提供商 API。
支持的 evidence 条目:
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
type |
是 | string |
当前为 local-file-with-env。 |
fileEnvVar |
否 | string |
包含显式凭证文件路径的环境变量。 |
fallbackPaths |
否 | string[] |
当 fileEnvVar 缺失或为空时检查的本地凭证文件路径。支持 ${HOME} 和 ${APPDATA}。 |
requiresAnyEnv |
否 | string[] |
evidence 有效之前,列出的环境变量中必须至少有一个非空。 |
requiresAllEnv |
否 | string[] |
evidence 有效之前,列出的每个环境变量都必须非空。 |
credentialMarker |
是 | string |
evidence 存在时返回的非密钥标记。 |
source |
否 | string |
用于 auth/status 输出的面向用户的来源标签。 |
setup 字段
| 字段 | 必填 | 类型 | 含义 |
|---|---|---|---|
providers |
否 | object[] |
在设置和新手引导期间暴露的提供商设置描述符。 |
cliBackends |
否 | string[] |
设置时用于描述符优先设置查找的后端 ID。保持规范化 ID 在全局唯一。 |
configMigrations |
否 | string[] |
此插件设置表面拥有的配置迁移 ID。 |
requiresRuntime |
否 | boolean |
描述符查找后,设置是否仍需要执行 setup-api。 |
uiHints 参考
uiHints 是从配置字段名到小型渲染提示的映射。
{
"uiHints": {
"apiKey": {
"label": "API key",
"help": "Used for OpenRouter requests",
"placeholder": "sk-or-v1-...",
"sensitive": true
}
}
}
每个字段提示可以包含:
| 字段 | 类型 | 含义 |
|---|---|---|
label |
string |
面向用户的字段标签。 |
help |
string |
简短辅助文本。 |
tags |
string[] |
可选 UI 标签。 |
advanced |
boolean |
将该字段标记为高级字段。 |
sensitive |
boolean |
将该字段标记为秘密或敏感。 |
placeholder |
string |
表单输入的占位符文本。 |
contracts 参考
仅将 contracts 用于静态能力所有权元数据,OpenClaw 可以在不导入插件运行时的情况下读取这些元数据。
{
"contracts": {
"agentToolResultMiddleware": ["pi", "codex"],
"externalAuthProviders": ["acme-ai"],
"speechProviders": ["openai"],
"realtimeTranscriptionProviders": ["openai"],
"realtimeVoiceProviders": ["openai"],
"memoryEmbeddingProviders": ["local"],
"mediaUnderstandingProviders": ["openai", "openai-codex"],
"imageGenerationProviders": ["openai"],
"videoGenerationProviders": ["qwen"],
"webFetchProviders": ["firecrawl"],
"webSearchProviders": ["gemini"],
"migrationProviders": ["hermes"],
"tools": ["firecrawl_search", "firecrawl_scrape"]
}
}
每个列表都是可选的:
| 字段 | 类型 | 含义 |
|---|---|---|
embeddedExtensionFactories |
string[] |
Codex app-server 扩展工厂 ID,当前为 codex-app-server。 |
agentToolResultMiddleware |
string[] |
内置插件可以为其注册工具结果中间件的运行时 ID。 |
externalAuthProviders |
string[] |
此插件拥有其外部 auth profile 钩子的提供商 ID。 |
speechProviders |
string[] |
此插件拥有的语音提供商 ID。 |
realtimeTranscriptionProviders |
string[] |
此插件拥有的实时转录提供商 ID。 |
realtimeVoiceProviders |
string[] |
此插件拥有的实时语音提供商 ID。 |
memoryEmbeddingProviders |
string[] |
此插件拥有的记忆嵌入提供商 ID。 |
mediaUnderstandingProviders |
string[] |
此插件拥有的媒体理解提供商 ID。 |
imageGenerationProviders |
string[] |
此插件拥有的图像生成提供商 ID。 |
videoGenerationProviders |
string[] |
此插件拥有的视频生成提供商 ID。 |
webFetchProviders |
string[] |
此插件拥有的 Web 获取提供商 ID。 |
webSearchProviders |
string[] |
此插件拥有的 Web 搜索提供商 ID。 |
migrationProviders |
string[] |
此插件为 openclaw migrate 拥有的导入提供商 ID。 |
tools |
string[] |
此插件拥有的智能体工具名称。 |
contracts.embeddedExtensionFactories 保留用于仅限内置 Codex app-server 的扩展工厂。内置工具结果转换应改为声明 contracts.agentToolResultMiddleware,并通过 api.registerAgentToolResultMiddleware(...) 注册。外部插件不能注册工具结果中间件,因为该衔接点可以在模型看到高信任工具输出之前重写它。
运行时 api.registerTool(...) 注册必须匹配 contracts.tools。工具发现会使用此列表,仅加载能够拥有所请求工具的插件运行时。
实现 resolveExternalAuthProfiles 的提供商插件应声明 contracts.externalAuthProviders。未声明的插件仍会通过已弃用的兼容性回退运行,但该回退速度更慢,并将在迁移窗口之后移除。
内置记忆嵌入提供商应为其暴露的每个适配器 ID 声明 contracts.memoryEmbeddingProviders,包括 local 等内置适配器。独立 CLI 路径会使用此清单契约,在完整 Gateway 网关运行时注册提供商之前,仅加载拥有它的插件。
mediaUnderstandingProviderMetadata 参考
当媒体理解提供商具有默认模型、自动 auth 回退优先级,或通用核心辅助逻辑在运行时加载前需要的原生文档支持时,请使用 mediaUnderstandingProviderMetadata。键也必须在 contracts.mediaUnderstandingProviders 中声明。
{
"contracts": {
"mediaUnderstandingProviders": ["example"]
},
"mediaUnderstandingProviderMetadata": {
"example": {
"capabilities": ["image", "audio"],
"defaultModels": {
"image": "example-vision-latest",
"audio": "example-transcribe-latest"
},
"autoPriority": {
"image": 40
},
"nativeDocumentInputs": ["pdf"]
}
}
}
每个提供商条目可以包含:
| 字段 | 类型 | 含义 |
|---|---|---|
capabilities |
("image" \| "audio" \| "video")[] |
此提供商暴露的媒体能力。 |
defaultModels |
Record<string, string> |
配置未指定模型时使用的能力到模型默认值。 |
autoPriority |
Record<string, number> |
对基于凭证的自动提供商回退进行排序时,数字越小越靠前。 |
nativeDocumentInputs |
"pdf"[] |
提供商支持的原生文档输入。 |
channelConfigs 参考
当渠道插件在运行时加载前需要低成本配置元数据时,请使用 channelConfigs。对于已配置的外部渠道,如果没有可用的设置条目,或 setup.requiresRuntime: false 声明不需要设置运行时,只读渠道设置/status 发现可以直接使用此元数据。
channelConfigs 是插件清单元数据,不是新的顶层用户配置区段。用户仍然在 channels.<channel-id> 下配置渠道实例。OpenClaw 会读取清单元数据,以决定在插件运行时代码执行前,哪个插件拥有该已配置的渠道。
对于渠道插件,configSchema 和 channelConfigs 描述不同路径:
configSchema验证plugins.entries.<plugin-id>.configchannelConfigs.<channel-id>.schema验证channels.<channel-id>
声明 channels[] 的非内置插件也应声明匹配的 channelConfigs 条目。没有它们,OpenClaw 仍然可以加载插件,但冷路径配置 schema、设置和 Control UI 表面在插件运行时执行前无法知道渠道拥有的选项形状。
channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled 和 nativeSkillsAutoEnabled 可以为在渠道运行时加载前运行的命令配置检查声明静态 auto 默认值。内置渠道也可以通过 package.json#openclaw.channel.commands 发布相同默认值,并与其他由包拥有的渠道目录元数据并列。
{
"channelConfigs": {
"matrix": {
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"homeserverUrl": { "type": "string" }
}
},
"uiHints": {
"homeserverUrl": {
"label": "Homeserver URL",
"placeholder": "https://matrix.example.com"
}
},
"label": "Matrix",
"description": "Matrix homeserver connection",
"commands": {
"nativeCommandsAutoEnabled": true,
"nativeSkillsAutoEnabled": true
},
"preferOver": ["matrix-legacy"]
}
}
}
每个渠道条目可以包含:
| 字段 | 类型 | 含义 |
|---|---|---|
schema |
object |
channels.<id> 的 JSON Schema。每个声明的渠道配置条目都需要。 |
uiHints |
Record<string, object> |
该渠道配置部分的可选 UI 标签、占位符和敏感提示。 |
label |
string |
当运行时元数据尚未就绪时,合并到选择器和检查界面的渠道标签。 |
description |
string |
用于检查和目录界面的简短渠道描述。 |
commands |
object |
用于运行时前配置检查的静态原生命令和原生技能自动默认值。 |
preferOver |
string[] |
在选择界面中,此渠道应优先于的旧版或较低优先级插件 ID。 |
替换另一个渠道插件
当你的插件是某个渠道 ID 的首选所有者,而另一个插件也可以提供该渠道时,
使用 preferOver。常见情况包括重命名后的插件 ID、取代内置插件的
独立插件,或为了配置兼容性保留相同渠道 ID 的维护版 fork。
{
"id": "acme-chat",
"channels": ["chat"],
"channelConfigs": {
"chat": {
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"webhookUrl": { "type": "string" }
}
},
"preferOver": ["chat"]
}
}
}
配置 channels.chat 时,OpenClaw 会同时考虑渠道 ID 和首选插件 ID。
如果较低优先级的插件只是因为它是内置插件或默认启用而被选中,OpenClaw
会在有效运行时配置中禁用它,以便由一个插件拥有该渠道及其工具。
显式用户选择仍然优先:如果用户显式启用了两个插件,OpenClaw 会保留该
选择,并报告重复渠道/工具诊断,而不是静默更改请求的插件集合。
将 preferOver 限定在确实可以提供相同渠道的插件 ID 范围内。
它不是通用优先级字段,也不会重命名用户配置键。
modelSupport 参考
当 OpenClaw 应在插件运行时加载前,从 gpt-5.5 或 claude-sonnet-4.6
这样的简写模型 ID 推断你的提供商插件时,使用 modelSupport。
{
"modelSupport": {
"modelPrefixes": ["gpt-", "o1", "o3", "o4"],
"modelPatterns": ["^computer-use-preview"]
}
}
OpenClaw 应用以下优先级:
- 显式
provider/model引用使用所属providers清单元数据 modelPatterns优先于modelPrefixes- 如果一个非内置插件和一个内置插件都匹配,则非内置插件优先
- 剩余歧义会被忽略,直到用户或配置指定提供商
字段:
| 字段 | 类型 | 含义 |
|---|---|---|
modelPrefixes |
string[] |
使用 startsWith 与简写模型 ID 匹配的前缀。 |
modelPatterns |
string[] |
在移除配置文件后缀后,与简写模型 ID 匹配的正则表达式源。 |
modelCatalog 参考
当 OpenClaw 应在加载插件运行时前了解提供商模型元数据时,使用
modelCatalog。这是由清单拥有的来源,用于固定目录行、提供商别名、抑制规则和发现模式。
运行时刷新仍属于提供商运行时代码,但清单会告诉核心何时需要运行时。
{
"providers": ["openai"],
"modelCatalog": {
"providers": {
"openai": {
"baseUrl": "https://api.openai.com/v1",
"api": "openai-responses",
"models": [
{
"id": "gpt-5.4",
"name": "GPT-5.4",
"input": ["text", "image"],
"reasoning": true,
"contextWindow": 256000,
"maxTokens": 128000,
"cost": {
"input": 1.25,
"output": 10,
"cacheRead": 0.125
},
"status": "available",
"tags": ["default"]
}
]
}
},
"aliases": {
"azure-openai-responses": {
"provider": "openai",
"api": "azure-openai-responses"
}
},
"suppressions": [
{
"provider": "azure-openai-responses",
"model": "gpt-5.3-codex-spark",
"reason": "not available on Azure OpenAI Responses"
}
],
"discovery": {
"openai": "static"
}
}
}
顶层字段:
| 字段 | 类型 | 含义 |
|---|---|---|
providers |
Record<string, object> |
此插件拥有的提供商 ID 的目录行。键也应出现在顶层 providers 中。 |
aliases |
Record<string, object> |
应解析为所属提供商的提供商别名,用于目录或抑制规划。 |
suppressions |
object[] |
此插件因提供商特定原因而抑制的来自另一个来源的模型行。 |
discovery |
Record<string, "static" \| "refreshable" \| "runtime"> |
提供商目录是可以从清单元数据读取、刷新到缓存,还是需要运行时。 |
aliases 参与模型目录规划的提供商所有权查找。
别名目标必须是同一插件拥有的顶层提供商。当按提供商过滤的列表使用别名时,
OpenClaw 可以读取所属清单,并在不加载提供商运行时的情况下应用别名 API/基础 URL 覆盖。
别名不会展开未过滤的目录列表;宽泛列表只会发出所属规范提供商行。
suppressions 取代旧的提供商运行时 suppressBuiltInModel 钩子。
只有当提供商由该插件拥有,或声明为指向所属提供商的 modelCatalog.aliases 键时,
抑制条目才会生效。模型解析期间不再调用运行时抑制钩子。
提供商字段:
| 字段 | 类型 | 含义 |
|---|---|---|
baseUrl |
string |
此提供商目录中模型的可选默认基础 URL。 |
api |
ModelApi |
此提供商目录中模型的可选默认 API 适配器。 |
headers |
Record<string, string> |
应用于此提供商目录的可选静态标头。 |
models |
object[] |
必需的模型行。没有 id 的行会被忽略。 |
模型字段:
| 字段 | 类型 | 含义 |
|---|---|---|
id |
string |
提供商本地模型 ID,不含 provider/ 前缀。 |
name |
string |
可选显示名称。 |
api |
ModelApi |
可选的按模型 API 覆盖。 |
baseUrl |
string |
可选的按模型基础 URL 覆盖。 |
headers |
Record<string, string> |
可选的按模型静态标头。 |
input |
Array<"text" \| "image" \| "document" \| "audio" \| "video"> |
模型接受的模态。 |
reasoning |
boolean |
模型是否公开推理行为。 |
contextWindow |
number |
原生提供商上下文窗口。 |
contextTokens |
number |
当与 contextWindow 不同时,可选的有效运行时上下文上限。 |
maxTokens |
number |
已知时的最大输出 token 数。 |
cost |
object |
可选的每百万 token 美元定价,包括可选的 tieredPricing。 |
compat |
object |
与 OpenClaw 模型配置兼容性匹配的可选兼容性标志。 |
status |
"available" | "preview" | "deprecated" | "disabled" |
列表状态。仅当该行完全不应出现时才抑制。 |
statusReason |
string |
随非可用状态显示的可选原因。 |
replaces |
string[] |
此模型取代的较旧提供商本地模型 ID。 |
replacedBy |
string |
已弃用行的替换提供商本地模型 ID。 |
tags |
string[] |
选择器和过滤器使用的稳定标签。 |
抑制字段:
| 字段 | 类型 | 含义 |
|---|---|---|
provider |
string |
要抑制的上游行的提供商 ID。必须由此插件拥有,或声明为所属别名。 |
model |
string |
要抑制的提供商本地模型 ID。 |
reason |
string |
当直接请求被抑制的行时显示的可选消息。 |
when.baseUrlHosts |
string[] |
抑制生效前所需的有效提供商基础 URL 主机的可选列表。 |
when.providerConfigApiIn |
string[] |
抑制生效前所需的精确提供商配置 api 值的可选列表。 |
不要将仅运行时数据放入 modelCatalog。只有当清单
行足够完整,可以让按提供商筛选的列表和选择器界面跳过
注册表/运行时发现时,才使用 static。当清单行是有用的
可列出种子或补充项,但刷新/缓存稍后可以添加更多行时,
使用 refreshable;refreshable 行本身并不是权威来源。当 OpenClaw
必须加载提供商运行时才能知道列表时,使用 runtime。
modelIdNormalization 参考
使用 modelIdNormalization 执行廉价的、由提供商拥有的模型 ID 清理,
并且该清理必须发生在提供商运行时加载之前。这会将短模型名称、
提供商本地旧版 ID、代理前缀规则等别名保留在所属插件清单中,
而不是放入核心模型选择表。
{
"providers": ["anthropic", "openrouter"],
"modelIdNormalization": {
"providers": {
"anthropic": {
"aliases": {
"sonnet-4.6": "claude-sonnet-4-6"
}
},
"openrouter": {
"prefixWhenBare": "openrouter"
}
}
}
}
提供商字段:
| 字段 | 类型 | 含义 |
|---|---|---|
aliases |
Record<string,string> |
不区分大小写的精确模型 ID 别名。值会按写法原样返回。 |
stripPrefixes |
string[] |
在别名查找之前移除的前缀,适用于旧版提供商/模型重复。 |
prefixWhenBare |
string |
当规范化后的模型 ID 尚未包含 / 时添加的前缀。 |
prefixWhenBareAfterAliasStartsWith |
object[] |
别名查找之后的条件裸 ID 前缀规则,由 modelPrefix 和 prefix 键控。 |
providerEndpoints 参考
使用 providerEndpoints 进行端点分类,这些分类是通用请求策略在提供商运行时
加载之前必须知道的。核心仍然拥有每个 endpointClass 的含义;
插件清单拥有主机和基础 URL 元数据。
端点字段:
| 字段 | 类型 | 含义 |
|---|---|---|
endpointClass |
string |
已知的核心端点类别,例如 openrouter、moonshot-native 或 google-vertex。 |
hosts |
string[] |
映射到端点类别的精确主机名。 |
hostSuffixes |
string[] |
映射到端点类别的主机后缀。使用 . 前缀表示仅匹配域后缀。 |
baseUrls |
string[] |
映射到端点类别的精确规范化 HTTP(S) 基础 URL。 |
googleVertexRegion |
string |
精确全局主机的静态 Google Vertex 区域。 |
googleVertexRegionHostSuffix |
string |
从匹配主机中剥离的后缀,用于暴露 Google Vertex 区域前缀。 |
providerRequest 参考
使用 providerRequest 提供廉价的请求兼容性元数据,让通用
请求策略无需加载提供商运行时即可使用。将特定行为的
载荷重写保留在提供商运行时钩子或共享提供商系列辅助工具中。
{
"providers": ["vllm"],
"providerRequest": {
"providers": {
"vllm": {
"family": "vllm",
"openAICompletions": {
"supportsStreamingUsage": true
}
}
}
}
}
提供商字段:
| 字段 | 类型 | 含义 |
|---|---|---|
family |
string |
通用请求兼容性决策和诊断使用的提供商系列标签。 |
compatibilityFamily |
"moonshot" |
可选的提供商系列兼容性分组,用于共享请求辅助工具。 |
openAICompletions |
object |
OpenAI 兼容的补全请求标志,目前为 supportsStreamingUsage。 |
modelPricing 参考
当提供商需要在运行时加载之前控制控制面定价行为时,使用 modelPricing。
Gateway 网关定价缓存会读取此元数据,而不会导入提供商运行时代码。
{
"providers": ["ollama", "openrouter"],
"modelPricing": {
"providers": {
"ollama": {
"external": false
},
"openrouter": {
"openRouter": {
"passthroughProviderModel": true
},
"liteLLM": false
}
}
}
}
提供商字段:
| 字段 | 类型 | 含义 |
|---|---|---|
external |
boolean |
对于永远不应获取 OpenRouter 或 LiteLLM 定价的本地/自托管提供商,设置为 false。 |
openRouter |
false \| object |
OpenRouter 定价查找映射。false 会禁用该提供商的 OpenRouter 查找。 |
liteLLM |
false \| object |
LiteLLM 定价查找映射。false 会禁用该提供商的 LiteLLM 查找。 |
源字段:
| 字段 | 类型 | 含义 |
|---|---|---|
provider |
string |
当外部目录提供商 ID 与 OpenClaw 提供商 ID 不同时使用,例如 zai 提供商对应的 z-ai。 |
passthroughProviderModel |
boolean |
将包含斜杠的模型 ID 视为嵌套的提供商/模型引用,适用于 OpenRouter 等代理提供商。 |
modelIdTransforms |
"version-dots"[] |
额外的外部目录模型 ID 变体。version-dots 会尝试类似 claude-opus-4.6 的点号版本 ID。 |
OpenClaw 提供商索引
OpenClaw 提供商索引是 OpenClaw 拥有的提供商预览元数据,
用于插件可能尚未安装的提供商。它不是插件清单的一部分。
插件清单仍然是已安装插件的权威来源。提供商索引是内部回退契约,
未来可安装提供商和安装前模型选择器界面将在提供商插件未安装时使用它。
目录权威顺序:
- 用户配置。
- 已安装插件清单
modelCatalog。 - 来自显式刷新的模型目录缓存。
- OpenClaw 提供商索引预览行。
提供商索引不得包含密钥、启用状态、运行时钩子或
实时账号特定的模型数据。它的预览目录使用与插件清单相同的
modelCatalog 提供商行结构,但应仅限于稳定的显示元数据,
除非 api、baseUrl、定价或兼容性标志等运行时适配器字段
被有意与已安装插件清单保持一致。具有实时 /models 发现能力的提供商,
应通过显式模型目录缓存路径写入刷新后的行,而不是让普通列表或新手引导调用提供商 API。
提供商索引条目也可以携带可安装插件元数据,用于插件已移出核心或尚未安装的提供商。
此元数据遵循频道目录模式:包名、npm 安装规格、
预期完整性以及廉价的凭证选择标签,足以展示一个
可安装的设置选项。一旦插件安装完成,其清单优先,
该提供商的提供商索引条目会被忽略。
旧版顶层能力键已弃用。使用 openclaw doctor --fix 将
speechProviders、realtimeTranscriptionProviders、
realtimeVoiceProviders、mediaUnderstandingProviders、
imageGenerationProviders、videoGenerationProviders、
webFetchProviders 和 webSearchProviders 移动到 contracts 下;
普通清单加载不再将这些顶层字段视为能力所有权。
清单与 package.json
这两个文件承担不同职责:
| 文件 | 用途 |
|---|---|
openclaw.plugin.json |
发现、配置验证、凭证选择元数据,以及必须在插件代码运行前存在的 UI 提示 |
package.json |
npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 openclaw 块 |
如果你不确定某项元数据应该放在哪里,请使用此规则:
- 如果 OpenClaw 必须在加载插件代码之前知道它,请放入
openclaw.plugin.json - 如果它与打包、入口文件或 npm 安装行为有关,请放入
package.json
影响发现的 package.json 字段
一些运行时前的插件元数据会有意放在 package.json 的
openclaw 块下,而不是 openclaw.plugin.json 中。
openclaw.bundle 和 openclaw.bundle.json 不是 OpenClaw 插件契约;
原生插件必须使用 openclaw.plugin.json 以及下面支持的
package.json#openclaw 字段。
重要示例:
| 字段 | 含义 |
|---|---|
openclaw.extensions |
声明原生插件入口点。必须保留在插件包目录内。 |
openclaw.runtimeExtensions |
为已安装包声明已构建的 JavaScript 运行时入口点。必须保留在插件包目录内。 |
openclaw.setupEntry |
轻量级的仅设置入口点,用于新手引导、延迟渠道启动,以及只读渠道状态/SecretRef 发现。必须保留在插件包目录内。 |
openclaw.runtimeSetupEntry |
为已安装包声明已构建的 JavaScript 设置入口点。需要 setupEntry,必须存在,并且必须保留在插件包目录内。 |
openclaw.channel |
低成本渠道目录元数据,例如标签、文档路径、别名和选择文案。 |
openclaw.channel.commands |
在渠道运行时加载之前,由配置、审计和命令列表界面使用的静态原生命令和原生技能自动默认元数据。 |
openclaw.channel.configuredState |
轻量级已配置状态检查器元数据,可以在不加载完整渠道运行时的情况下回答“仅 env 的设置是否已经存在?” |
openclaw.channel.persistedAuthState |
轻量级持久化凭证检查器元数据,可以在不加载完整渠道运行时的情况下回答“是否已有任何登录?” |
openclaw.install.clawhubSpec / openclaw.install.npmSpec / openclaw.install.localPath |
面向内置插件和外部发布插件的安装/更新提示。 |
openclaw.install.defaultChoice |
当多个安装来源可用时的首选安装路径。 |
openclaw.install.minHostVersion |
支持的最低 OpenClaw 主机版本,使用类似 >=2026.3.22 或 >=2026.5.1-beta.1 的 semver 下限。 |
openclaw.install.expectedIntegrity |
预期的 npm dist 完整性字符串,例如 sha512-...;安装和更新流程会用它校验获取到的构件。 |
openclaw.install.allowInvalidConfigRecovery |
当配置无效时,允许一个狭窄的内置插件重新安装恢复路径。 |
openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen |
允许仅设置渠道界面在启动期间先于完整渠道插件加载。 |
清单元数据决定运行时加载前哪些提供商/渠道/设置选择会出现在
新手引导中。package.json#openclaw.install 告诉新手引导,当用户选择其中一个
选项时如何获取或启用该插件。不要把安装提示移到 openclaw.plugin.json。
openclaw.install.minHostVersion 会在安装和清单注册表加载期间对非内置插件来源强制执行。无效值会被拒绝;
较新但有效的值会让旧主机跳过外部插件。内置源插件假定与主机检出版本一致。
官方的按需安装元数据应在插件发布到 ClawHub 时使用 clawhubSpec;新手引导会将其视为首选远程来源,并在安装后记录 ClawHub 构件事实。npmSpec 仍然是尚未迁移到 ClawHub 的包的兼容性回退。
精确的 npm 版本固定已存在于 npmSpec 中,例如
"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"。官方外部目录条目应将精确 spec 与 expectedIntegrity 配对,这样如果获取到的 npm 构件不再匹配固定发布版本,更新流程会以关闭方式失败。交互式新手引导仍会为了兼容性提供受信任注册表 npm spec,包括裸包名和 dist-tag。目录诊断可以区分精确、浮动、完整性固定、缺少完整性、包名不匹配和无效默认选择来源。它们还会在存在 expectedIntegrity 但没有可由其固定的有效 npm 来源时发出警告。当存在 expectedIntegrity 时,安装/更新流程会强制执行它;当它被省略时,注册表解析会在没有完整性固定的情况下记录。
渠道插件应在状态、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时提供 openclaw.setupEntry。设置入口应公开渠道元数据以及设置安全的配置、状态和密钥适配器;将网络客户端、Gateway 网关监听器和传输运行时保留在主扩展入口点中。
运行时入口点字段不会覆盖源入口点字段的包边界检查。例如,openclaw.runtimeExtensions 不能让一个逃逸的 openclaw.extensions 路径变得可加载。
openclaw.install.allowInvalidConfigRecovery 有意保持狭窄。它不会让任意损坏的配置变得可安装。目前它只允许安装流程从特定的过期内置插件升级失败中恢复,例如缺少内置插件路径,或同一内置插件存在过期的 channels.<id> 条目。不相关的配置错误仍会阻止安装,并将操作员引导到 openclaw doctor --fix。
openclaw.channel.persistedAuthState 是面向一个极小检查器模块的包元数据:
{
"openclaw": {
"channel": {
"id": "whatsapp",
"persistedAuthState": {
"specifier": "./auth-presence",
"exportName": "hasAnyWhatsAppAuth"
}
}
}
}
当设置、Doctor、状态或只读存在性流程需要在完整渠道插件加载前进行低成本的是/否凭证探测时使用它。持久化凭证状态不是已配置渠道状态:不要使用此元数据自动启用插件、修复运行时依赖项,或决定是否应加载渠道运行时。目标导出应是一个只读取持久化状态的小函数;不要让它通过完整渠道运行时 barrel 转发。
openclaw.channel.configuredState 对低成本仅 env 已配置检查遵循相同形状:
{
"openclaw": {
"channel": {
"id": "telegram",
"configuredState": {
"specifier": "./configured-state",
"exportName": "hasTelegramConfiguredState"
}
}
}
}
当渠道可以从 env 或其他极小的非运行时输入回答已配置状态时使用它。如果检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 config.hasConfiguredState 钩子中。
发现优先级(重复插件 ID)
OpenClaw 会从多个根发现插件(内置、全局安装、工作区、显式配置选择的路径)。如果两个发现结果共享同一个 id,只保留最高优先级清单;较低优先级的重复项会被丢弃,而不是并排加载。
优先级从高到低:
- 配置选择 — 在
plugins.entries.<id>中显式固定的路径 - 内置 — 随 OpenClaw 一起发布的插件
- 全局安装 — 安装到全局 OpenClaw 插件根的插件
- 工作区 — 相对于当前工作区发现的插件
影响:
- 位于工作区中的内置插件分叉副本或过期副本不会遮蔽内置构建。
- 如果确实要用本地插件覆盖内置插件,请通过
plugins.entries.<id>固定它,使其凭优先级胜出,而不是依赖工作区发现。 - 重复丢弃会被记录,因此 Doctor 和启动诊断可以指向被丢弃的副本。
- 配置选择的重复覆盖在诊断中会表述为显式覆盖,但仍会发出警告,以便过期分叉和意外遮蔽保持可见。
JSON Schema 要求
- 每个插件都必须随附一个 JSON Schema,即使它不接受任何配置。
- 空 schema 是可接受的(例如
{ "type": "object", "additionalProperties": false })。 - Schema 会在配置读/写时验证,而不是在运行时验证。
- 当用新配置键扩展或分叉内置插件时,请同时更新该插件的
openclaw.plugin.jsonconfigSchema。内置插件 schema 是严格的,因此如果在用户配置中添加plugins.entries.<id>.config.myNewKey,但没有把myNewKey添加到configSchema.properties,就会在插件运行时加载前被拒绝。
示例 schema 扩展:
{
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"myNewKey": {
"type": "string"
}
}
}
}
验证行为
- 未知的
channels.*键是错误,除非该渠道 ID 由
插件清单声明。 plugins.entries.<id>、plugins.allow、plugins.deny和plugins.slots.*
必须引用可发现的插件 ID。未知 ID 是错误。- 如果插件已安装但清单或 schema 损坏或缺失,
验证会失败,Doctor 会报告插件错误。 - 如果插件配置存在但插件被禁用,配置会被保留,并且
Doctor + 日志中会显示警告。
完整的 plugins.* schema 请参阅配置参考。
备注
- 清单是原生 OpenClaw 插件必需的,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 验证。
- 原生清单使用 JSON5 解析,因此只要最终值仍是对象,就可以接受注释、尾随逗号和未加引号的键。
- 清单加载器只读取已记录的清单字段。避免使用自定义顶层键。
- 当插件不需要
channels、providers、cliBackends和skills时,都可以省略。 providerCatalogEntry必须保持轻量,不应导入宽泛的运行时代码;将它用于静态提供商目录元数据或窄范围发现描述符,而不是请求时执行。providerDiscoveryEntry是旧版拼写,现有插件仍可使用。- 独占插件类型通过
plugins.slots.*选择:通过plugins.slots.memory选择kind: "memory",通过plugins.slots.contextEngine选择kind: "context-engine"(默认legacy)。 - 在此清单中声明独占插件类型。运行时入口
OpenClawPluginDefinition.kind已弃用,仅作为旧插件的兼容性回退保留。 - 环境变量元数据(
setup.providers[].envVars、已弃用的providerAuthEnvVars和channelEnvVars)仅是声明式的。Status、审计、cron 投递验证和其他只读界面在将环境变量视为已配置之前,仍会应用插件信任和有效激活策略。 - 对于需要提供商代码的运行时向导元数据,请参阅 提供商运行时钩子。
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器 allowlist 要求(例如 pnpm
allow-build-scripts+pnpm rebuild <package>)。
相关内容
插件入门指南。
内部架构和能力模型。
插件 SDK 参考和子路径导入。
📄 注册工具
原文:https://docs.openclaw.ai/zh-CN/plugins/agent-tools
此页面已移动。请参阅 构建插件:注册智能体工具。
相关内容
📄 OpenProse
原文:https://docs.openclaw.ai/zh-CN/prose
OpenProse 是一种可移植、以 Markdown 为先的工作流格式,用于编排 AI 会话。在 OpenClaw 中,它以插件形式提供,会安装一个 OpenProse Skills 包以及一个 /prose 斜杠命令。程序存放在 .prose 文件中,并且可以通过显式控制流生成多个子智能体。
官方网站:https://www.prose.md
它可以做什么
- 通过显式并行机制执行多智能体研究 + 综合。
- 可重复、审批安全的工作流(代码审查、事件分诊、内容流水线)。
- 可复用的
.prose程序,可在受支持的智能体运行时之间运行。
安装 + 启用
内置插件默认处于禁用状态。启用 OpenProse:
openclaw plugins enable open-prose
启用插件后,重启 Gateway 网关。
开发 / 本地检出:openclaw plugins install ./path/to/local/open-prose-plugin
斜杠命令
OpenProse 将 /prose 注册为一个可由用户调用的 skill 命令。它会路由到 OpenProse VM 指令,并在底层使用 OpenClaw 工具。
常用命令:
/prose help
/prose run <file.prose>
/prose run <handle/slug>
/prose run <https://example.com/file.prose>
/prose compile <file.prose>
/prose examples
/prose update
示例:一个简单的 .prose 文件
# Research + synthesis with two agents running in parallel.
input topic: "What should we research?"
agent researcher:
model: sonnet
prompt: "You research thoroughly and cite sources."
agent writer:
model: opus
prompt: "You write a concise summary."
parallel:
findings = session: researcher
prompt: "Research {topic}."
draft = session: writer
prompt: "Summarize {topic}."
session "Merge the findings + draft into a final answer."
context: { findings, draft }
文件位置
OpenProse 将状态保存在你的工作区下的 .prose/ 中:
.prose/
├── .env
├── runs/
│ └── {YYYYMMDD}-{HHMMSS}-{random}/
│ ├── program.prose
│ ├── state.md
│ ├── bindings/
│ └── agents/
└── agents/
用户级持久智能体位于:
~/.prose/agents/
状态模式
OpenProse 支持多种状态后端:
- filesystem(默认):
.prose/runs/... - in-context:瞬态,用于小型程序
- sqlite(实验性):需要
sqlite3二进制文件 - postgres(实验性):需要
psql和连接字符串
说明:
- sqlite / postgres 为选择启用且属于实验性功能。
- postgres 凭证会流入子智能体日志;请使用专用且最小权限的数据库。
远程程序
/prose run <handle/slug> 会解析为 https://p.prose.md/<handle>/<slug>。
直接 URL 会按原样抓取。这会使用 web_fetch 工具(或针对 POST 使用 exec)。
OpenClaw 运行时映射
OpenProse 程序会映射到 OpenClaw 原语:
| OpenProse 概念 | OpenClaw 工具 |
|---|---|
| 生成会话 / Task 工具 | sessions_spawn |
| 文件读取 / 写入 | read / write |
| Web 抓取 | web_fetch |
如果你的工具允许列表阻止了这些工具,OpenProse 程序将无法运行。参见 Skills 配置。
安全 + 审批
请像对待代码一样对待 .prose 文件。运行前先审查。使用 OpenClaw 工具允许列表和审批门控来控制副作用。
对于确定性、带审批门控的工作流,可与 Lobster 对比。