{"id":289,"date":"2026-03-21T22:47:26","date_gmt":"2026-03-21T14:47:26","guid":{"rendered":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/tools-plugin\/"},"modified":"2026-03-21T23:08:52","modified_gmt":"2026-03-21T15:08:52","slug":"tools-plugin","status":"publish","type":"post","link":"https:\/\/pa.yingzhi8.cn\/index.php\/2026\/03\/21\/tools-plugin\/","title":{"rendered":"\u63d2\u4ef6"},"content":{"rendered":"<h1>\u63d2\u4ef6<\/h1>\n<h1>\u63d2\u4ef6\uff08\u6269\u5c55\uff09<\/h1>\n<h2>\u5feb\u901f\u5f00\u59cb\uff08\u521a\u63a5\u89e6\u63d2\u4ef6\uff1f\uff09<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u662f\u4ee5\u4e0b\u4e24\u79cd\u4e4b\u4e00\uff1a<\/p>\n<ul>\n<li>\u539f\u751f <strong>OpenClaw \u63d2\u4ef6<\/strong>\uff08<code>openclaw.plugin.json<\/code> + \u8fd0\u884c\u65f6\u6a21\u5757\uff09\uff0c\u6216<\/li>\n<li>\u517c\u5bb9\u7684 <strong>bundle<\/strong>\uff08<code>.codex-plugin\/plugin.json<\/code> \u6216 <code>.claude-plugin\/plugin.json<\/code>\uff09<\/li>\n<\/ul>\n<p>\u4e24\u8005\u90fd\u4f1a\u663e\u793a\u5728 <code>openclaw plugins<\/code> \u4e0b\uff0c\u4f46\u53ea\u6709\u539f\u751f OpenClaw \u63d2\u4ef6\u4f1a\u5728\u8fdb\u7a0b\u5185\u6267\u884c\u8fd0\u884c\u65f6\u4ee3\u7801\u3002<\/p>\n<p>\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5f53\u4f60\u60f3\u8981\u67d0\u9879\u6838\u5fc3 OpenClaw \u5c1a\u672a\u5185\u7f6e\u7684\u529f\u80fd\u65f6\uff0c\u5c31\u4f1a\u4f7f\u7528\u63d2\u4ef6\uff08\u6216\u8005\u4f60\u5e0c\u671b\u5c06\u53ef\u9009\u529f\u80fd\u4fdd\u7559\u5728\u4e3b\u5b89\u88c5\u4e4b\u5916\uff09\u3002<\/p>\n<p>\u5feb\u6377\u8def\u5f84\uff1a<\/p>\n<ol>\n<li>\u67e5\u770b\u5f53\u524d\u5df2\u52a0\u8f7d\u7684\u5185\u5bb9\uff1a<\/li>\n<\/ol>\n<p>&#8220;`bash  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nopenclaw plugins list<\/p>\n<pre><code>\n2. \u5b89\u88c5\u5b98\u65b9\u63d2\u4ef6\uff08\u793a\u4f8b\uff1aVoice Call\uff09\uff1a\n\n```bash  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nopenclaw plugins install @openclaw\/voice-call\n<\/code><\/pre>\n<p>Npm \u89c4\u683c\u4ec5\u652f\u6301 <strong>registry-only<\/strong>\uff08\u5305\u540d + \u53ef\u9009\u7684 <strong>\u7cbe\u786e\u7248\u672c<\/strong> \u6216 <strong>dist-tag<\/strong>\uff09\u3002<\/p>\n<p>Git\/URL\/file \u89c4\u683c\u548c semver \u8303\u56f4\u90fd\u4f1a\u88ab\u62d2\u7edd\u3002<\/p>\n<p>\u88f8\u89c4\u683c\u548c <code>@latest<\/code> \u4f1a\u505c\u7559\u5728\u7a33\u5b9a\u901a\u9053\u3002\u5982\u679c npm \u5c06\u5176\u4e2d\u4efb\u4e00\u89e3\u6790\u4e3a\u9884\u53d1\u5e03\u7248\u672c\uff0cOpenClaw \u4f1a\u505c\u6b62\u5e76\u8981\u6c42\u4f60\u901a\u8fc7\u9884\u53d1\u5e03\u6807\u7b7e\uff08\u4f8b\u5982 <code>@beta<\/code>\/<code>@rc<\/code>\uff09\u6216\u7cbe\u786e\u7684\u9884\u53d1\u5e03\u7248\u672c\u663e\u5f0f\u9009\u62e9\u52a0\u5165\u3002<\/p>\n<ol start=\"3\">\n<li>\u91cd\u542f Gateway \u7f51\u5173\uff0c\u7136\u540e\u5728 <code>plugins.entries.&lt;id&gt;.config<\/code> \u4e0b\u8fdb\u884c\u914d\u7f6e\u3002<\/li>\n<\/ol>\n<p>\u67e5\u770b <a href=\"\/plugins\/voice-call\">Voice Call<\/a> \u83b7\u53d6\u4e00\u4e2a\u5177\u4f53\u7684\u63d2\u4ef6\u793a\u4f8b\u3002<br \/>\n\u60f3\u627e\u7b2c\u4e09\u65b9\u5217\u8868\uff1f\u8bf7\u67e5\u770b <a href=\"\/plugins\/community\">Community plugins<\/a>\u3002<br \/>\n\u9700\u8981\u4e86\u89e3 bundle \u517c\u5bb9\u6027\u7ec6\u8282\uff1f\u8bf7\u67e5\u770b <a href=\"\/plugins\/bundles\">Plugin bundles<\/a>\u3002<\/p>\n<p>\u5bf9\u4e8e\u517c\u5bb9\u7684 bundle\uff0c\u53ef\u4ece\u672c\u5730\u76ee\u5f55\u6216\u5f52\u6863\u6587\u4ef6\u5b89\u88c5\uff1a<\/p>\n<p>&#8220;`bash  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nopenclaw plugins install .\/my-bundle<br \/>\nopenclaw plugins install .\/my-bundle.tgz<\/p>\n<pre><code>\n## \u67b6\u6784\n\nOpenClaw \u7684\u63d2\u4ef6\u7cfb\u7edf\u6709\u56db\u5c42\uff1a\n\n1. **\u6e05\u5355 + \u53d1\u73b0**\n   OpenClaw \u4f1a\u4ece\u5df2\u914d\u7f6e\u8def\u5f84\u3001\u5de5\u4f5c\u533a\u6839\u76ee\u5f55\u3001\u5168\u5c40\u6269\u5c55\u6839\u76ee\u5f55\u4ee5\u53ca\u968f\u9644\u6269\u5c55\u4e2d\u67e5\u627e\u5019\u9009\u63d2\u4ef6\u3002\u53d1\u73b0\u8fc7\u7a0b\u4f1a\u5148\u8bfb\u53d6\u539f\u751f `openclaw.plugin.json` \u6e05\u5355\u4ee5\u53ca\u53d7\u652f\u6301\u7684 bundle \u6e05\u5355\u3002\n2. **\u542f\u7528 + \u9a8c\u8bc1**\n   \u6838\u5fc3\u4f1a\u51b3\u5b9a\u67d0\u4e2a\u5df2\u53d1\u73b0\u63d2\u4ef6\u662f\u542f\u7528\u3001\u7981\u7528\u3001\u963b\u6b62\uff0c\u8fd8\u662f\u88ab\u9009\u7528\u4e8e\u67d0\u4e2a\u72ec\u5360\u63d2\u69fd\uff08\u4f8b\u5982\u5185\u5b58\uff09\u3002\n3. **\u8fd0\u884c\u65f6\u52a0\u8f7d**\n   \u539f\u751f OpenClaw \u63d2\u4ef6\u901a\u8fc7 jiti \u5728\u8fdb\u7a0b\u5185\u52a0\u8f7d\uff0c\u5e76\u5c06\u529f\u80fd\u6ce8\u518c\u5230\u4e00\u4e2a\u4e2d\u592e\u6ce8\u518c\u8868\u4e2d\u3002\u517c\u5bb9\u7684 bundle \u4f1a\u88ab\u89c4\u8303\u5316\u4e3a\u6ce8\u518c\u8868\u8bb0\u5f55\uff0c\u800c\u4e0d\u4f1a\u5bfc\u5165\u8fd0\u884c\u65f6\u4ee3\u7801\u3002\n4. **\u8868\u9762\u6d88\u8d39**\n   OpenClaw \u7684\u5176\u4f59\u90e8\u5206\u4f1a\u8bfb\u53d6\u6ce8\u518c\u8868\uff0c\u4ee5\u516c\u5f00\u5de5\u5177\u3001\u6e20\u9053\u3001\u63d0\u4f9b\u5546\u8bbe\u7f6e\u3001hooks\u3001HTTP \u8def\u7531\u3001CLI \u547d\u4ee4\u548c\u670d\u52a1\u3002\n\n\u91cd\u8981\u7684\u8bbe\u8ba1\u8fb9\u754c\uff1a\n\n* \u53d1\u73b0 + \u914d\u7f6e\u9a8c\u8bc1\u5e94\u57fa\u4e8e **manifest\/schema \u5143\u6570\u636e** \u8fd0\u884c\uff0c\u800c\u4e0d\u6267\u884c\u63d2\u4ef6\u4ee3\u7801\n* \u539f\u751f\u8fd0\u884c\u65f6\u884c\u4e3a\u6765\u81ea\u63d2\u4ef6\u6a21\u5757\u7684 `register(api)` \u8def\u5f84\n\n\u8fd9\u79cd\u62c6\u5206\u8ba9 OpenClaw \u80fd\u591f\u5728\u5b8c\u6574\u8fd0\u884c\u65f6\u6fc0\u6d3b\u4e4b\u524d\uff0c\u5c31\u9a8c\u8bc1\u914d\u7f6e\u3001\u89e3\u91ca\u7f3a\u5931\/\u88ab\u7981\u7528\u7684\u63d2\u4ef6\uff0c\u5e76\u6784\u5efa UI\/schema \u63d0\u793a\u3002\n\n## \u517c\u5bb9\u7684 bundle\n\nOpenClaw \u8fd8\u8bc6\u522b\u4e24\u79cd\u517c\u5bb9\u7684\u5916\u90e8 bundle \u5e03\u5c40\uff1a\n\n* Codex \u98ce\u683c bundle\uff1a`.codex-plugin\/plugin.json`\n* Claude \u98ce\u683c bundle\uff1a`.claude-plugin\/plugin.json`\uff0c\u6216\u8005\u6ca1\u6709\u6e05\u5355\u7684\u9ed8\u8ba4 Claude \u7ec4\u4ef6\u5e03\u5c40\n* Cursor \u98ce\u683c bundle\uff1a`.cursor-plugin\/plugin.json`\n\n\u5b83\u4eec\u4f1a\u5728\u63d2\u4ef6\u5217\u8868\u4e2d\u663e\u793a\u4e3a `format=bundle`\uff0c\u5e76\u5728\u8be6\u7ec6\/info \u8f93\u51fa\u4e2d\u663e\u793a `codex` \u6216 `claude` \u5b50\u7c7b\u578b\u3002\n\n\u6709\u5173\u7cbe\u786e\u7684\u68c0\u6d4b\u89c4\u5219\u3001\u6620\u5c04\u884c\u4e3a\u548c\u5f53\u524d\u652f\u6301\u77e9\u9635\uff0c\u8bf7\u53c2\u9605 [Plugin bundles](\/plugins\/bundles)\u3002\n\n\u76ee\u524d\uff0cOpenClaw \u5c06\u8fd9\u4e9b\u5185\u5bb9\u89c6\u4e3a **\u80fd\u529b\u5305**\uff0c\u800c\u4e0d\u662f\u539f\u751f\u8fd0\u884c\u65f6\u63d2\u4ef6\uff1a\n\n* \u5f53\u524d\u652f\u6301\uff1a\u6346\u7ed1\u7684 `skills`\n* \u5f53\u524d\u652f\u6301\uff1aClaude `commands\/` markdown \u6839\u76ee\u5f55\uff0c\u6620\u5c04\u5230\u5e38\u89c4 OpenClaw \u6280\u80fd\u52a0\u8f7d\u5668\n* \u5f53\u524d\u652f\u6301\uff1aClaude bundle `settings.json` \u9ed8\u8ba4\u503c\uff0c\u7528\u4e8e\u5d4c\u5165\u5f0f Pi \u667a\u80fd\u4f53\u8bbe\u7f6e\uff08\u4f1a\u6e05\u7406 shell override \u952e\uff09\n* \u5f53\u524d\u652f\u6301\uff1aCursor `.cursor\/commands\/*.md` \u6839\u76ee\u5f55\uff0c\u6620\u5c04\u5230\u5e38\u89c4 OpenClaw \u6280\u80fd\u52a0\u8f7d\u5668\n* \u5f53\u524d\u652f\u6301\uff1a\u4f7f\u7528 OpenClaw hook-pack \u5e03\u5c40\u7684 Codex bundle hook \u76ee\u5f55\uff08`HOOK.md` + `handler.ts`\/`handler.js`\uff09\n* \u5df2\u68c0\u6d4b\u4f46\u5c1a\u672a\u63a5\u7ebf\uff1a\u5176\u4ed6\u5df2\u58f0\u660e\u7684 bundle \u80fd\u529b\uff0c\u4f8b\u5982 agents\u3001Claude hook \u81ea\u52a8\u5316\u3001Cursor rules\/hooks\/MCP \u5143\u6570\u636e\u3001MCP\/app\/LSP \u5143\u6570\u636e\u3001\u8f93\u51fa\u6837\u5f0f\n\n\u8fd9\u610f\u5473\u7740 bundle \u7684\u5b89\u88c5\/\u53d1\u73b0\/\u5217\u8868\/info\/\u542f\u7528\u90fd\u53ef\u6b63\u5e38\u5de5\u4f5c\uff0c\u5e76\u4e14\u5f53 bundle \u88ab\u542f\u7528\u65f6\uff0cbundle skills\u3001Claude command-skills\u3001Claude bundle settings \u9ed8\u8ba4\u503c\u4ee5\u53ca\u517c\u5bb9\u7684 Codex hook \u76ee\u5f55\u90fd\u4f1a\u88ab\u52a0\u8f7d\uff0c\u4f46 bundle \u8fd0\u884c\u65f6\u4ee3\u7801\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u5185\u6267\u884c\u3002\n\nBundle hook \u652f\u6301\u4ec5\u9650\u4e8e\u5e38\u89c4 OpenClaw hook \u76ee\u5f55\u683c\u5f0f\uff08\u5728\u58f0\u660e\u7684 hook \u6839\u76ee\u5f55\u4e0b\u4f7f\u7528 `HOOK.md` \u52a0\u4e0a `handler.ts`\/`handler.js`\uff09\u3002\n\u4f9b\u5e94\u5546\u7279\u5b9a\u7684 shell\/JSON hook \u8fd0\u884c\u65f6\uff0c\u5305\u62ec Claude `hooks.json`\uff0c\u5f53\u524d\u4ec5\u4f1a\u88ab\u68c0\u6d4b\uff0c\u4e0d\u4f1a\u88ab\u76f4\u63a5\u6267\u884c\u3002\n\n## \u6267\u884c\u6a21\u578b\n\n\u539f\u751f OpenClaw \u63d2\u4ef6\u4e0e Gateway \u7f51\u5173 **\u5728\u540c\u4e00\u8fdb\u7a0b\u5185** \u8fd0\u884c\u3002\u5b83\u4eec\u4e0d\u4f1a\u8fdb\u884c\u6c99\u7bb1\u9694\u79bb\u3002\u5df2\u52a0\u8f7d\u7684\u539f\u751f\u63d2\u4ef6\u4e0e\u6838\u5fc3\u4ee3\u7801\u5904\u4e8e\u76f8\u540c\u7684\u8fdb\u7a0b\u7ea7\u4fe1\u4efb\u8fb9\u754c\u3002\n\n\u8fd9\u610f\u5473\u7740\uff1a\n\n* \u539f\u751f\u63d2\u4ef6\u53ef\u4ee5\u6ce8\u518c\u5de5\u5177\u3001\u7f51\u7edc\u5904\u7406\u5668\u3001hooks \u548c\u670d\u52a1\n* \u539f\u751f\u63d2\u4ef6\u4e2d\u7684 bug \u53ef\u80fd\u5bfc\u81f4 gateway \u5d29\u6e83\u6216\u4e0d\u7a33\u5b9a\n* \u6076\u610f\u539f\u751f\u63d2\u4ef6\u7b49\u540c\u4e8e\u5728 OpenClaw \u8fdb\u7a0b\u5185\u90e8\u6267\u884c\u4efb\u610f\u4ee3\u7801\n\n\u517c\u5bb9\u7684 bundle \u9ed8\u8ba4\u66f4\u5b89\u5168\uff0c\u56e0\u4e3a OpenClaw \u76ee\u524d\u5c06\u5b83\u4eec\u89c6\u4e3a\u5143\u6570\u636e\/\u5185\u5bb9\u5305\u3002\u5728\u5f53\u524d\u7248\u672c\u4e2d\uff0c\u8fd9\u4e3b\u8981\u610f\u5473\u7740\u6346\u7ed1\u7684\u6280\u80fd\u3002\n\n\u5bf9\u4e8e\u975e\u6346\u7ed1\u63d2\u4ef6\uff0c\u8bf7\u4f7f\u7528 allowlist \u548c\u663e\u5f0f\u5b89\u88c5\/\u52a0\u8f7d\u8def\u5f84\u3002\u5c06\u5de5\u4f5c\u533a\u63d2\u4ef6\u89c6\u4e3a\u5f00\u53d1\u671f\u4ee3\u7801\uff0c\u800c\u4e0d\u662f\u751f\u4ea7\u9ed8\u8ba4\u9879\u3002\n\n\u91cd\u8981\u4fe1\u4efb\u8bf4\u660e\uff1a\n\n* `plugins.allow` \u4fe1\u4efb\u7684\u662f **plugin id**\uff0c\u800c\u4e0d\u662f\u6765\u6e90\u51fa\u5904\u3002\n* \u5982\u679c\u67d0\u4e2a\u5de5\u4f5c\u533a\u63d2\u4ef6\u4e0e\u67d0\u4e2a\u6346\u7ed1\u63d2\u4ef6\u5177\u6709\u76f8\u540c id\uff0c\u90a3\u4e48\u542f\u7528\/\u52a0\u5165 allowlist \u540e\uff0c\u5de5\u4f5c\u533a\u63d2\u4ef6\u4f1a\u6709\u610f\u8986\u76d6\u6346\u7ed1\u526f\u672c\u3002\n* \u8fd9\u662f\u4e00\u79cd\u6b63\u5e38\u4e14\u6709\u7528\u7684\u884c\u4e3a\uff0c\u9002\u5408\u672c\u5730\u5f00\u53d1\u3001\u8865\u4e01\u6d4b\u8bd5\u548c\u70ed\u4fee\u590d\u3002\n\n## \u53ef\u7528\u63d2\u4ef6\uff08\u5b98\u65b9\uff09\n\n* Microsoft Teams \u81ea `2026.1.15` \u8d77\u4ec5\u4ee5\u63d2\u4ef6\u5f62\u5f0f\u63d0\u4f9b\uff1b\u5982\u679c\u4f60\u4f7f\u7528 Teams\uff0c\u8bf7\u5b89\u88c5 `@openclaw\/msteams`\u3002\n* Memory\uff08Core\uff09\u2014 \u6346\u7ed1\u7684\u5185\u5b58\u641c\u7d22\u63d2\u4ef6\uff08\u9ed8\u8ba4\u901a\u8fc7 `plugins.slots.memory` \u542f\u7528\uff09\n* Memory\uff08LanceDB\uff09\u2014 \u6346\u7ed1\u7684\u957f\u671f\u8bb0\u5fc6\u63d2\u4ef6\uff08\u81ea\u52a8\u53ec\u56de\/\u6355\u83b7\uff1b\u8bbe\u7f6e `plugins.slots.memory = &quot;memory-lancedb&quot;`\uff09\n* [Voice Call](\/plugins\/voice-call) \u2014 `@openclaw\/voice-call`\n* [Zalo Personal](\/plugins\/zalouser) \u2014 `@openclaw\/zalouser`\n* [Matrix](\/channels\/matrix) \u2014 `@openclaw\/matrix`\n* [Nostr](\/channels\/nostr) \u2014 `@openclaw\/nostr`\n* [Zalo](\/channels\/zalo) \u2014 `@openclaw\/zalo`\n* [Microsoft Teams](\/channels\/msteams) \u2014 `@openclaw\/msteams`\n* Anthropic provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `anthropic` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* BytePlus provider catalog \u2014 \u4ee5 `byteplus` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Cloudflare AI Gateway provider catalog \u2014 \u4ee5 `cloudflare-ai-gateway` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Google \u7f51\u7edc\u641c\u7d22 + Gemini CLI OAuth \u2014 \u4ee5 `google` \u5f62\u5f0f\u6346\u7ed1\uff08\u7f51\u9875\u641c\u7d22\u4f1a\u81ea\u52a8\u52a0\u8f7d\uff1bprovider \u8eab\u4efd\u9a8c\u8bc1\u4ecd\u9700\u9009\u62e9\u542f\u7528\uff09\n* GitHub Copilot provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `github-copilot` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Hugging Face provider catalog \u2014 \u4ee5 `huggingface` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Kilo Gateway provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `kilocode` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Kimi Coding provider catalog \u2014 \u4ee5 `kimi-coding` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* MiniMax provider catalog + usage + OAuth \u2014 \u4ee5 `minimax` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff1b\u62e5\u6709 `minimax` \u548c `minimax-portal`\uff09\n* Mistral provider \u80fd\u529b \u2014 \u4ee5 `mistral` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Model Studio provider catalog \u2014 \u4ee5 `modelstudio` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Moonshot provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `moonshot` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* NVIDIA provider catalog \u2014 \u4ee5 `nvidia` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* OpenAI provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `openai` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff1b\u540c\u65f6\u62e5\u6709 `openai` \u548c `openai-codex`\uff09\n* OpenCode Go provider \u80fd\u529b \u2014 \u4ee5 `opencode-go` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* OpenCode Zen provider \u80fd\u529b \u2014 \u4ee5 `opencode` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* OpenRouter provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `openrouter` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Qianfan provider catalog \u2014 \u4ee5 `qianfan` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Qwen OAuth\uff08provider \u8eab\u4efd\u9a8c\u8bc1 + catalog\uff09\u2014 \u4ee5 `qwen-portal-auth` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Synthetic provider catalog \u2014 \u4ee5 `synthetic` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Together provider catalog \u2014 \u4ee5 `together` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Venice provider catalog \u2014 \u4ee5 `venice` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Vercel AI Gateway provider catalog \u2014 \u4ee5 `vercel-ai-gateway` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Volcengine provider catalog \u2014 \u4ee5 `volcengine` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Xiaomi provider catalog + usage \u2014 \u4ee5 `xiaomi` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Z.AI provider \u8fd0\u884c\u65f6 \u2014 \u4ee5 `zai` \u5f62\u5f0f\u6346\u7ed1\uff08\u9ed8\u8ba4\u542f\u7528\uff09\n* Copilot Proxy\uff08provider \u8eab\u4efd\u9a8c\u8bc1\uff09\u2014 \u672c\u5730 VS Code Copilot Proxy \u6865\u63a5\uff1b\u4e0d\u540c\u4e8e\u5185\u7f6e\u7684 `github-copilot` \u8bbe\u5907\u767b\u5f55\uff08\u5df2\u6346\u7ed1\uff0c\u9ed8\u8ba4\u7981\u7528\uff09\n\n\u539f\u751f OpenClaw \u63d2\u4ef6\u662f\u901a\u8fc7 jiti \u5728\u8fd0\u884c\u65f6\u52a0\u8f7d\u7684 **TypeScript \u6a21\u5757**\u3002\n**\u914d\u7f6e\u9a8c\u8bc1\u4e0d\u4f1a\u6267\u884c\u63d2\u4ef6\u4ee3\u7801**\uff1b\u5b83\u4f7f\u7528\u7684\u662f\u63d2\u4ef6 manifest \u548c JSON Schema\u3002\u8bf7\u53c2\u9605 [Plugin manifest](\/plugins\/manifest)\u3002\n\n\u539f\u751f OpenClaw \u63d2\u4ef6\u53ef\u4ee5\u6ce8\u518c\uff1a\n\n* Gateway RPC \u65b9\u6cd5\n* Gateway HTTP \u8def\u7531\n* \u667a\u80fd\u4f53\u5de5\u5177\n* CLI \u547d\u4ee4\n* \u540e\u53f0\u670d\u52a1\n* \u4e0a\u4e0b\u6587\u5f15\u64ce\n* provider \u8eab\u4efd\u9a8c\u8bc1\u6d41\u7a0b\u548c\u6a21\u578b\u76ee\u5f55\n* \u7528\u4e8e\u52a8\u6001\u6a21\u578b id\u3001\u4f20\u8f93\u89c4\u8303\u5316\u3001\u80fd\u529b\u5143\u6570\u636e\u3001\u6d41\u5305\u88c5\u3001\u7f13\u5b58 TTL \u7b56\u7565\u3001\u7f3a\u5931\u8eab\u4efd\u9a8c\u8bc1\u63d0\u793a\u3001\u5185\u7f6e\u6a21\u578b\u6291\u5236\u3001\u76ee\u5f55\u589e\u5f3a\u3001\u8fd0\u884c\u65f6\u8eab\u4efd\u9a8c\u8bc1\u4ea4\u6362\u4ee5\u53ca usage\/billing \u8eab\u4efd\u9a8c\u8bc1 + \u5feb\u7167\u89e3\u6790\u7684 provider \u8fd0\u884c\u65f6 hooks\n* \u53ef\u9009\u914d\u7f6e\u9a8c\u8bc1\n* **Skills**\uff08\u901a\u8fc7\u5728\u63d2\u4ef6 manifest \u4e2d\u5217\u51fa `skills` \u76ee\u5f55\uff09\n* **\u81ea\u52a8\u56de\u590d\u547d\u4ee4**\uff08\u65e0\u9700\u8c03\u7528 AI \u667a\u80fd\u4f53\u5373\u53ef\u6267\u884c\uff09\n\n\u539f\u751f OpenClaw \u63d2\u4ef6\u4e0e Gateway \u7f51\u5173 **\u5728\u540c\u4e00\u8fdb\u7a0b\u5185** \u8fd0\u884c\uff0c\u56e0\u6b64\u5e94\u5c06\u5176\u89c6\u4e3a\u53d7\u4fe1\u4efb\u4ee3\u7801\u3002\n\u5de5\u5177\u7f16\u5199\u6307\u5357\uff1a[Plugin agent tools](\/plugins\/agent-tools)\u3002\n\n## Provider \u8fd0\u884c\u65f6 hooks\n\nProvider \u63d2\u4ef6\u73b0\u5728\u6709\u4e24\u5c42\uff1a\n\n* manifest \u5143\u6570\u636e\uff1a`providerAuthEnvVars`\uff0c\u7528\u4e8e\u5728\u8fd0\u884c\u65f6\u52a0\u8f7d\u524d\u8fdb\u884c\u4f4e\u6210\u672c\u7684\u73af\u5883\u8eab\u4efd\u9a8c\u8bc1\u67e5\u627e\n* \u914d\u7f6e\u65f6 hooks\uff1a`catalog` \/ \u65e7\u7248 `discovery`\n* \u8fd0\u884c\u65f6 hooks\uff1a`resolveDynamicModel`\u3001`prepareDynamicModel`\u3001`normalizeResolvedModel`\u3001`capabilities`\u3001`prepareExtraParams`\u3001`wrapStreamFn`\u3001`formatApiKey`\u3001`refreshOAuth`\u3001`buildAuthDoctorHint`\u3001`isCacheTtlEligible`\u3001`buildMissingAuthMessage`\u3001`suppressBuiltInModel`\u3001`augmentModelCatalog`\u3001`isBinaryThinking`\u3001`supportsXHighThinking`\u3001`resolveDefaultThinkingLevel`\u3001`isModernModelRef`\u3001`prepareRuntimeAuth`\u3001`resolveUsageAuth`\u3001`fetchUsageSnapshot`\n\nOpenClaw \u4ecd\u7136\u8d1f\u8d23\u901a\u7528\u7684\u667a\u80fd\u4f53\u5faa\u73af\u3001\u6545\u969c\u5207\u6362\u3001\u8f6c\u5f55\u5904\u7406\u548c\u5de5\u5177\u7b56\u7565\u3002\u8fd9\u4e9b hooks \u662f provider \u7279\u5b9a\u884c\u4e3a\u7684\u63a5\u7f1d\uff0c\u800c\u65e0\u9700\u6574\u4e2a\u81ea\u5b9a\u4e49\u63a8\u7406\u4f20\u8f93\u5c42\u3002\n\n\u5f53 provider \u5177\u6709\u57fa\u4e8e\u73af\u5883\u53d8\u91cf\u7684\u51ed\u636e\uff0c\u5e76\u4e14\u4f60\u5e0c\u671b\u901a\u7528 auth\/status\/model-picker \u8def\u5f84\u5728\u4e0d\u52a0\u8f7d\u63d2\u4ef6\u8fd0\u884c\u65f6\u7684\u60c5\u51b5\u4e0b\u5c31\u80fd\u770b\u5230\u8fd9\u4e9b\u51ed\u636e\u65f6\uff0c\u8bf7\u4f7f\u7528 manifest `providerAuthEnvVars`\u3002\n\u4fdd\u7559 provider \u8fd0\u884c\u65f6 `envVars` \u7528\u4e8e\u9762\u5411\u64cd\u4f5c\u5458\u7684\u63d0\u793a\uff0c\u4f8b\u5982\u65b0\u624b\u5f15\u5bfc\u6807\u7b7e\u6216 OAuth client-id\/client-secret \u8bbe\u7f6e\u73af\u5883\u53d8\u91cf\u3002\n\n### Hook \u987a\u5e8f\n\n\u5bf9\u4e8e model\/provider \u63d2\u4ef6\uff0cOpenClaw \u5927\u81f4\u6309\u4ee5\u4e0b\u987a\u5e8f\u4f7f\u7528 hooks\uff1a\n\n1. `catalog`\n   \u5728\u751f\u6210 `models.json` \u671f\u95f4\uff0c\u5c06 provider \u914d\u7f6e\u53d1\u5e03\u5230 `models.providers` \u4e2d\u3002\n2. \u5185\u7f6e\/\u5df2\u53d1\u73b0\u6a21\u578b\u67e5\u627e\n   OpenClaw \u4f1a\u5148\u5c1d\u8bd5\u5e38\u89c4\u6ce8\u518c\u8868\/\u76ee\u5f55\u8def\u5f84\u3002\n3. `resolveDynamicModel`\n   \u5bf9\u4e8e\u672c\u5730\u6ce8\u518c\u8868\u4e2d\u5c1a\u4e0d\u5b58\u5728\u7684 provider \u81ea\u6709 model id\uff0c\u8fdb\u884c\u540c\u6b65\u540e\u5907\u89e3\u6790\u3002\n4. `prepareDynamicModel`\n   \u4ec5\u5728\u5f02\u6b65\u6a21\u578b\u89e3\u6790\u8def\u5f84\u4e0a\u6267\u884c\u5f02\u6b65\u9884\u70ed\uff0c\u7136\u540e\u518d\u6b21\u8fd0\u884c `resolveDynamicModel`\u3002\n5. `normalizeResolvedModel`\n   \u5728\u5d4c\u5165\u5f0f\u8fd0\u884c\u5668\u4f7f\u7528\u5df2\u89e3\u6790\u6a21\u578b\u4e4b\u524d\u8fdb\u884c\u6700\u7ec8\u91cd\u5199\u3002\n6. `capabilities`\n   \u7531\u5171\u4eab\u6838\u5fc3\u903b\u8f91\u4f7f\u7528\u7684 provider \u81ea\u6709\u8f6c\u5f55\/\u5de5\u5177\u5143\u6570\u636e\u3002\n7. `prepareExtraParams`\n   \u5728\u901a\u7528\u6d41\u9009\u9879\u5305\u88c5\u5668\u4e4b\u524d\u6267\u884c provider \u81ea\u6709\u8bf7\u6c42\u53c2\u6570\u89c4\u8303\u5316\u3002\n8. `wrapStreamFn`\n   \u5728\u5e94\u7528\u901a\u7528\u5305\u88c5\u5668\u4e4b\u540e\u6267\u884c provider \u81ea\u6709\u6d41\u5305\u88c5\u5668\u3002\n9. `formatApiKey`\n   \u5f53\u5b58\u50a8\u7684 auth profile \u9700\u8981\u8f6c\u6362\u4e3a\u8fd0\u884c\u65f6 `apiKey` \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528 provider \u81ea\u6709\u8eab\u4efd\u9a8c\u8bc1\u914d\u7f6e\u5668\u3002\n10. `refreshOAuth`\n    \u5bf9\u81ea\u5b9a\u4e49\u5237\u65b0\u7aef\u70b9\u6216\u5237\u65b0\u5931\u8d25\u7b56\u7565\u6267\u884c provider \u81ea\u6709 OAuth \u5237\u65b0\u8986\u76d6\u3002\n11. `buildAuthDoctorHint`\n    \u5f53 OAuth \u5237\u65b0\u5931\u8d25\u65f6\uff0c\u8ffd\u52a0 provider \u81ea\u6709\u4fee\u590d\u63d0\u793a\u3002\n12. `isCacheTtlEligible`\n    \u4e3a\u4ee3\u7406\/backhaul provider \u63d0\u4f9b provider \u81ea\u6709\u63d0\u793a\u8bcd\u7f13\u5b58\u7b56\u7565\u3002\n13. `buildMissingAuthMessage`\n    \u7528 provider \u81ea\u6709\u5185\u5bb9\u66ff\u6362\u901a\u7528\u7684\u7f3a\u5931\u8eab\u4efd\u9a8c\u8bc1\u6062\u590d\u6d88\u606f\u3002\n14. `suppressBuiltInModel`\n    \u6267\u884c provider \u81ea\u6709\u7684\u8fc7\u65f6\u4e0a\u6e38\u6a21\u578b\u6291\u5236\uff0c\u5e76\u53ef\u8fd4\u56de\u9762\u5411\u7528\u6237\u7684\u9519\u8bef\u63d0\u793a\u3002\n15. `augmentModelCatalog`\n    \u5728\u53d1\u73b0\u540e\u9644\u52a0 provider \u81ea\u6709\u7684\u5408\u6210\/\u6700\u7ec8\u76ee\u5f55\u884c\u3002\n16. `isBinaryThinking`\n    \u4e3a\u4e8c\u5143 thinking provider \u63d0\u4f9b provider \u81ea\u6709\u7684\u5f00\/\u5173\u63a8\u7406\u5207\u6362\u3002\n17. `supportsXHighThinking`\n    \u4e3a\u9009\u5b9a\u6a21\u578b\u63d0\u4f9b provider \u81ea\u6709\u7684 `xhigh` \u63a8\u7406\u652f\u6301\u3002\n18. `resolveDefaultThinkingLevel`\n    \u4e3a\u7279\u5b9a\u6a21\u578b\u5bb6\u65cf\u63d0\u4f9b provider \u81ea\u6709\u7684\u9ed8\u8ba4 `\/think` \u7ea7\u522b\u3002\n19. `isModernModelRef`\n    \u63d0\u4f9b provider \u81ea\u6709\u7684\u73b0\u4ee3\u6a21\u578b\u5339\u914d\u5668\uff0c\u7528\u4e8e live profile \u8fc7\u6ee4\u5668\u548c smoke \u9009\u62e9\u3002\n20. `prepareRuntimeAuth`\n    \u5728\u63a8\u7406\u524d\u5c06\u5df2\u914d\u7f6e\u7684\u51ed\u636e\u4ea4\u6362\u4e3a\u5b9e\u9645\u7684\u8fd0\u884c\u65f6\u4ee4\u724c\/\u5bc6\u94a5\u3002\n21. `resolveUsageAuth`\n    \u4e3a `\/usage` \u53ca\u76f8\u5173\u72b6\u6001\u8868\u9762\u89e3\u6790 usage\/billing \u51ed\u636e\u3002\n22. `fetchUsageSnapshot`\n    \u5728\u8eab\u4efd\u9a8c\u8bc1\u89e3\u6790\u5b8c\u6210\u540e\uff0c\u6293\u53d6\u5e76\u89c4\u8303\u5316 provider \u7279\u5b9a\u7684 usage\/quota \u5feb\u7167\u3002\n\n### \u5e94\u8be5\u4f7f\u7528\u54ea\u4e2a hook\n\n* `catalog`\uff1a\u5c06 provider \u914d\u7f6e\u548c\u6a21\u578b\u76ee\u5f55\u53d1\u5e03\u5230 `models.providers`\n* `resolveDynamicModel`\uff1a\u5904\u7406\u672c\u5730\u6ce8\u518c\u8868\u4e2d\u5c1a\u672a\u5b58\u5728\u7684\u900f\u4f20\u6216\u524d\u5411\u517c\u5bb9 model id\n* `prepareDynamicModel`\uff1a\u5728\u91cd\u8bd5\u52a8\u6001\u89e3\u6790\u4e4b\u524d\u6267\u884c\u5f02\u6b65\u9884\u70ed\uff08\u4f8b\u5982\u5237\u65b0 provider \u5143\u6570\u636e\u7f13\u5b58\uff09\n* `normalizeResolvedModel`\uff1a\u5728\u63a8\u7406\u524d\u91cd\u5199\u5df2\u89e3\u6790\u6a21\u578b\u7684\u4f20\u8f93\/base URL\/\u517c\u5bb9\u6027\n* `capabilities`\uff1a\u53d1\u5e03 provider \u5bb6\u65cf\u548c\u8f6c\u5f55\/\u5de5\u5177\u5dee\u5f02\uff0c\u800c\u4e0d\u5728\u6838\u5fc3\u4e2d\u786c\u7f16\u7801 provider id\n* `prepareExtraParams`\uff1a\u5728\u901a\u7528\u6d41\u5305\u88c5\u4e4b\u524d\u8bbe\u7f6e provider \u9ed8\u8ba4\u503c\u6216\u89c4\u8303\u5316 provider \u7279\u5b9a\u7684\u6bcf\u6a21\u578b\u53c2\u6570\n* `wrapStreamFn`\uff1a\u5728\u4ecd\u4f7f\u7528\u5e38\u89c4 `pi-ai` \u6267\u884c\u8def\u5f84\u65f6\uff0c\u6dfb\u52a0 provider \u7279\u5b9a\u7684 header\/payload\/model \u517c\u5bb9\u8865\u4e01\n* `formatApiKey`\uff1a\u5c06\u5b58\u50a8\u7684 auth profile \u8f6c\u6362\u4e3a\u8fd0\u884c\u65f6 `apiKey` \u5b57\u7b26\u4e32\uff0c\u800c\u4e0d\u5728\u6838\u5fc3\u4e2d\u786c\u7f16\u7801 provider \u4ee4\u724c blob\n* `refreshOAuth`\uff1a\u4e3a\u4e0d\u9002\u914d\u5171\u4eab `pi-ai` \u5237\u65b0\u5668\u7684 provider \u81ea\u4e3b\u7ba1\u7406 OAuth \u5237\u65b0\n* `buildAuthDoctorHint`\uff1a\u5728\u5237\u65b0\u5931\u8d25\u65f6\u8ffd\u52a0 provider \u81ea\u6709\u7684\u8eab\u4efd\u9a8c\u8bc1\u4fee\u590d\u6307\u5bfc\n* `isCacheTtlEligible`\uff1a\u51b3\u5b9a provider\/\u6a21\u578b\u7ec4\u5408\u662f\u5426\u5e94\u4f7f\u7528 cache TTL \u5143\u6570\u636e\n* `buildMissingAuthMessage`\uff1a\u7528 provider \u7279\u5b9a\u6062\u590d\u63d0\u793a\u66ff\u6362\u901a\u7528 auth-store \u9519\u8bef\n* `suppressBuiltInModel`\uff1a\u9690\u85cf\u8fc7\u65f6\u4e0a\u6e38\u6761\u76ee\uff0c\u5e76\u53ef\u5728\u76f4\u63a5\u89e3\u6790\u5931\u8d25\u65f6\u8fd4\u56de provider \u81ea\u6709\u9519\u8bef\n* `augmentModelCatalog`\uff1a\u5728\u53d1\u73b0\u548c\u914d\u7f6e\u5408\u5e76\u540e\u9644\u52a0\u5408\u6210\/\u6700\u7ec8\u76ee\u5f55\u884c\n* `isBinaryThinking`\uff1a\u5728 `\/think` \u4e2d\u516c\u5f00\u4e8c\u5143\u5f00\/\u5173\u63a8\u7406 UX\uff0c\u800c\u4e0d\u786c\u7f16\u7801 provider id\n* `supportsXHighThinking`\uff1a\u8ba9\u7279\u5b9a\u6a21\u578b\u542f\u7528 `xhigh` \u63a8\u7406\u7ea7\u522b\n* `resolveDefaultThinkingLevel`\uff1a\u5c06 provider\/\u6a21\u578b\u9ed8\u8ba4\u63a8\u7406\u7b56\u7565\u79fb\u51fa\u6838\u5fc3\n* `isModernModelRef`\uff1a\u5c06 live\/smoke \u6a21\u578b\u5bb6\u65cf\u5305\u542b\u89c4\u5219\u4fdd\u7559\u5728 provider \u4e2d\n* `prepareRuntimeAuth`\uff1a\u5c06\u5df2\u914d\u7f6e\u51ed\u636e\u4ea4\u6362\u4e3a\u8bf7\u6c42\u6240\u7528\u7684\u5b9e\u9645\u77ed\u671f\u8fd0\u884c\u65f6\u4ee4\u724c\/\u5bc6\u94a5\n* `resolveUsageAuth`\uff1a\u4e3a usage\/billing \u7aef\u70b9\u89e3\u6790 provider \u81ea\u6709\u51ed\u636e\uff0c\u800c\u4e0d\u5728\u6838\u5fc3\u4e2d\u786c\u7f16\u7801\u4ee4\u724c\u89e3\u6790\n* `fetchUsageSnapshot`\uff1a\u7531 provider \u81ea\u4e3b\u7ba1\u7406 usage \u7aef\u70b9\u6293\u53d6\/\u89e3\u6790\uff0c\u800c\u6838\u5fc3\u7ee7\u7eed\u8d1f\u8d23\u6458\u8981\u6247\u51fa\u548c\u683c\u5f0f\u5316\n\n\u7ecf\u9a8c\u6cd5\u5219\uff1a\n\n* provider \u62e5\u6709\u76ee\u5f55\u6216 base URL \u9ed8\u8ba4\u503c\uff1a\u4f7f\u7528 `catalog`\n* provider \u63a5\u53d7\u4efb\u610f\u4e0a\u6e38 model id\uff1a\u4f7f\u7528 `resolveDynamicModel`\n* provider \u5728\u89e3\u6790\u672a\u77e5 id \u524d\u9700\u8981\u7f51\u7edc\u5143\u6570\u636e\uff1a\u6dfb\u52a0 `prepareDynamicModel`\n* provider \u9700\u8981\u4f20\u8f93\u91cd\u5199\u4f46\u4ecd\u4f7f\u7528\u6838\u5fc3\u4f20\u8f93\uff1a\u4f7f\u7528 `normalizeResolvedModel`\n* provider \u9700\u8981\u8f6c\u5f55\/provider \u5bb6\u65cf\u5dee\u5f02\uff1a\u4f7f\u7528 `capabilities`\n* provider \u9700\u8981\u9ed8\u8ba4\u8bf7\u6c42\u53c2\u6570\u6216\u6309 provider \u6e05\u7406\u53c2\u6570\uff1a\u4f7f\u7528 `prepareExtraParams`\n* provider \u9700\u8981\u8bf7\u6c42 header\/body\/model \u517c\u5bb9\u5305\u88c5\u800c\u4e0d\u4f7f\u7528\u81ea\u5b9a\u4e49\u4f20\u8f93\uff1a\u4f7f\u7528 `wrapStreamFn`\n* provider \u5728 auth profile \u4e2d\u5b58\u50a8\u989d\u5916\u5143\u6570\u636e\u5e76\u9700\u8981\u81ea\u5b9a\u4e49\u8fd0\u884c\u65f6\u4ee4\u724c\u683c\u5f0f\uff1a\u4f7f\u7528 `formatApiKey`\n* provider \u9700\u8981\u81ea\u5b9a\u4e49 OAuth \u5237\u65b0\u7aef\u70b9\u6216\u5237\u65b0\u5931\u8d25\u7b56\u7565\uff1a\u4f7f\u7528 `refreshOAuth`\n* provider \u5728\u5237\u65b0\u5931\u8d25\u540e\u9700\u8981 provider \u81ea\u6709\u8eab\u4efd\u9a8c\u8bc1\u4fee\u590d\u6307\u5bfc\uff1a\u4f7f\u7528 `buildAuthDoctorHint`\n* provider \u9700\u8981\u7279\u5b9a\u4e8e\u4ee3\u7406\u7684 cache TTL \u95e8\u63a7\uff1a\u4f7f\u7528 `isCacheTtlEligible`\n* provider \u9700\u8981 provider \u7279\u5b9a\u7684\u7f3a\u5931\u8eab\u4efd\u9a8c\u8bc1\u6062\u590d\u63d0\u793a\uff1a\u4f7f\u7528 `buildMissingAuthMessage`\n* provider \u9700\u8981\u9690\u85cf\u8fc7\u65f6\u4e0a\u6e38\u6761\u76ee\u6216\u7528\u5382\u5546\u63d0\u793a\u66ff\u6362\u5b83\u4eec\uff1a\u4f7f\u7528 `suppressBuiltInModel`\n* provider \u9700\u8981\u5728 `models list` \u548c\u9009\u62e9\u5668\u4e2d\u6dfb\u52a0\u5408\u6210\u7684\u524d\u5411\u517c\u5bb9\u6761\u76ee\uff1a\u4f7f\u7528 `augmentModelCatalog`\n* provider \u4ec5\u63d0\u4f9b\u4e8c\u5143 thinking \u5f00\/\u5173\uff1a\u4f7f\u7528 `isBinaryThinking`\n* provider \u53ea\u5e0c\u671b\u90e8\u5206\u6a21\u578b\u542f\u7528 `xhigh`\uff1a\u4f7f\u7528 `supportsXHighThinking`\n* provider \u62e5\u6709\u67d0\u4e2a\u6a21\u578b\u5bb6\u65cf\u9ed8\u8ba4 `\/think` \u7b56\u7565\uff1a\u4f7f\u7528 `resolveDefaultThinkingLevel`\n* provider \u62e5\u6709 live\/smoke \u9996\u9009\u6a21\u578b\u5339\u914d\uff1a\u4f7f\u7528 `isModernModelRef`\n* provider \u9700\u8981\u4ee4\u724c\u4ea4\u6362\u6216\u77ed\u671f\u8bf7\u6c42\u51ed\u636e\uff1a\u4f7f\u7528 `prepareRuntimeAuth`\n* provider \u9700\u8981\u81ea\u5b9a\u4e49 usage\/quota \u4ee4\u724c\u89e3\u6790\u6216\u4e0d\u540c\u7684 usage \u51ed\u636e\uff1a\u4f7f\u7528 `resolveUsageAuth`\n* provider \u9700\u8981 provider \u7279\u5b9a\u7684 usage \u7aef\u70b9\u6216\u8d1f\u8f7d\u89e3\u6790\u5668\uff1a\u4f7f\u7528 `fetchUsageSnapshot`\n\n\u5982\u679c provider \u9700\u8981\u5b8c\u5168\u81ea\u5b9a\u4e49\u7684\u7ebf\u534f\u8bae\u6216\u81ea\u5b9a\u4e49\u8bf7\u6c42\u6267\u884c\u5668\uff0c\u90a3\u5c5e\u4e8e\u53e6\u4e00\u7c7b\u6269\u5c55\u3002\u8fd9\u4e9b hooks \u9002\u7528\u4e8e\u4ecd\u8fd0\u884c\u5728 OpenClaw \u5e38\u89c4\u63a8\u7406\u5faa\u73af\u4e0a\u7684 provider \u884c\u4e3a\u3002\n\n### Provider \u793a\u4f8b\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\napi.registerProvider({\n  id: &quot;example-proxy&quot;,\n  label: &quot;Example Proxy&quot;,\n  auth: [],\n  catalog: {\n    order: &quot;simple&quot;,\n    run: async (ctx) =&gt; {\n      const apiKey = ctx.resolveProviderApiKey(&quot;example-proxy&quot;).apiKey;\n      if (!apiKey) {\n        return null;\n      }\n      return {\n        provider: {\n          baseUrl: &quot;https:\/\/proxy.example.com\/v1&quot;,\n          apiKey,\n          api: &quot;openai-completions&quot;,\n          models: [{ id: &quot;auto&quot;, name: &quot;Auto&quot; }],\n        },\n      };\n    },\n  },\n  resolveDynamicModel: (ctx) =&gt; ({\n    id: ctx.modelId,\n    name: ctx.modelId,\n    provider: &quot;example-proxy&quot;,\n    api: &quot;openai-completions&quot;,\n    baseUrl: &quot;https:\/\/proxy.example.com\/v1&quot;,\n    reasoning: false,\n    input: [&quot;text&quot;],\n    cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n    contextWindow: 128000,\n    maxTokens: 8192,\n  }),\n  prepareRuntimeAuth: async (ctx) =&gt; {\n    const exchanged = await exchangeToken(ctx.apiKey);\n    return {\n      apiKey: exchanged.token,\n      baseUrl: exchanged.baseUrl,\n      expiresAt: exchanged.expiresAt,\n    };\n  },\n  resolveUsageAuth: async (ctx) =&gt; {\n    const auth = await ctx.resolveOAuthToken();\n    return auth ? { token: auth.token } : null;\n  },\n  fetchUsageSnapshot: async (ctx) =&gt; {\n    return await fetchExampleProxyUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn);\n  },\n});\n<\/code><\/pre>\n<h3>\u5185\u7f6e\u793a\u4f8b<\/h3>\n<ul>\n<li>Anthropic \u4f7f\u7528 <code>resolveDynamicModel<\/code>\u3001<code>capabilities<\/code>\u3001<code>buildAuthDoctorHint<\/code>\u3001<code>resolveUsageAuth<\/code>\u3001<code>fetchUsageSnapshot<\/code>\u3001<code>isCacheTtlEligible<\/code>\u3001<code>resolveDefaultThinkingLevel<\/code> \u548c <code>isModernModelRef<\/code>\uff0c\u56e0\u4e3a\u5b83\u62e5\u6709 Claude 4.6 \u524d\u5411\u517c\u5bb9\u3001provider \u5bb6\u65cf\u63d0\u793a\u3001\u8eab\u4efd\u9a8c\u8bc1\u4fee\u590d\u6307\u5bfc\u3001usage \u7aef\u70b9\u96c6\u6210\u3001\u63d0\u793a\u8bcd\u7f13\u5b58\u8d44\u683c\u4ee5\u53ca Claude \u9ed8\u8ba4\/\u81ea\u9002\u5e94 thinking \u7b56\u7565\u3002<\/li>\n<li>OpenAI \u4f7f\u7528 <code>resolveDynamicModel<\/code>\u3001<code>normalizeResolvedModel<\/code> \u548c <code>capabilities<\/code>\uff0c\u4ee5\u53ca <code>buildMissingAuthMessage<\/code>\u3001<code>suppressBuiltInModel<\/code>\u3001<code>augmentModelCatalog<\/code>\u3001<code>supportsXHighThinking<\/code> \u548c <code>isModernModelRef<\/code>\uff0c\u56e0\u4e3a\u5b83\u62e5\u6709 GPT-5.4 \u524d\u5411\u517c\u5bb9\u3001\u76f4\u63a5 OpenAI <code>openai-completions<\/code> -&gt; <code>openai-responses<\/code> \u89c4\u8303\u5316\u3001\u652f\u6301 Codex \u7684\u8eab\u4efd\u9a8c\u8bc1\u63d0\u793a\u3001Spark \u6291\u5236\u3001\u5408\u6210 OpenAI \u5217\u8868\u884c\u4ee5\u53ca GPT-5 thinking \/ live-model \u7b56\u7565\u3002<\/li>\n<li>OpenRouter \u4f7f\u7528 <code>catalog<\/code> \u4ee5\u53ca <code>resolveDynamicModel<\/code> \u548c <code>prepareDynamicModel<\/code>\uff0c\u56e0\u4e3a\u8be5 provider \u662f\u900f\u4f20\u578b\u7684\uff0c\u53ef\u80fd\u4f1a\u5728 OpenClaw \u9759\u6001\u76ee\u5f55\u66f4\u65b0\u4e4b\u524d\u66b4\u9732\u65b0\u7684 model id\u3002<\/li>\n<li>GitHub Copilot \u4f7f\u7528 <code>catalog<\/code>\u3001<code>auth<\/code>\u3001<code>resolveDynamicModel<\/code> \u548c <code>capabilities<\/code>\uff0c\u4ee5\u53ca <code>prepareRuntimeAuth<\/code> \u548c <code>fetchUsageSnapshot<\/code>\uff0c\u56e0\u4e3a\u5b83\u9700\u8981 provider \u81ea\u6709\u8bbe\u5907\u767b\u5f55\u3001\u6a21\u578b\u56de\u9000\u884c\u4e3a\u3001Claude \u8f6c\u5f55\u5dee\u5f02\u3001GitHub token -&gt; Copilot token \u4ea4\u6362\uff0c\u4ee5\u53ca provider \u81ea\u6709 usage \u7aef\u70b9\u3002<\/li>\n<li>OpenAI Codex \u4f7f\u7528 <code>catalog<\/code>\u3001<code>resolveDynamicModel<\/code>\u3001<code>normalizeResolvedModel<\/code>\u3001<code>refreshOAuth<\/code> \u548c <code>augmentModelCatalog<\/code>\uff0c\u4ee5\u53ca <code>prepareExtraParams<\/code>\u3001<code>resolveUsageAuth<\/code> \u548c <code>fetchUsageSnapshot<\/code>\uff0c\u56e0\u4e3a\u5b83\u4ecd\u8fd0\u884c\u5728\u6838\u5fc3 OpenAI \u4f20\u8f93\u4e4b\u4e0a\uff0c\u4f46\u62e5\u6709\u81ea\u5df1\u7684\u4f20\u8f93\/base URL \u89c4\u8303\u5316\u3001OAuth \u5237\u65b0\u540e\u5907\u7b56\u7565\u3001\u9ed8\u8ba4\u4f20\u8f93\u9009\u62e9\u3001\u5408\u6210 Codex \u76ee\u5f55\u884c\u4ee5\u53ca ChatGPT usage \u7aef\u70b9\u96c6\u6210\u3002<\/li>\n<li>Google AI Studio \u548c Gemini CLI OAuth \u4f7f\u7528 <code>resolveDynamicModel<\/code> \u548c <code>isModernModelRef<\/code>\uff0c\u56e0\u4e3a\u5b83\u4eec\u62e5\u6709 Gemini 3.1 \u524d\u5411\u517c\u5bb9\u540e\u5907\u548c\u73b0\u4ee3\u6a21\u578b\u5339\u914d\uff1bGemini CLI OAuth \u8fd8\u4f7f\u7528 <code>formatApiKey<\/code>\u3001<code>resolveUsageAuth<\/code> \u548c <code>fetchUsageSnapshot<\/code> \u6765\u5904\u7406\u4ee4\u724c\u683c\u5f0f\u5316\u3001\u4ee4\u724c\u89e3\u6790\u548c quota \u7aef\u70b9\u63a5\u7ebf\u3002<\/li>\n<li>OpenRouter \u4f7f\u7528 <code>capabilities<\/code>\u3001<code>wrapStreamFn<\/code> \u548c <code>isCacheTtlEligible<\/code>\uff0c\u4ee5\u4fbf\u5c06 provider \u7279\u5b9a\u7684\u8bf7\u6c42\u5934\u3001\u8def\u7531\u5143\u6570\u636e\u3001reasoning \u8865\u4e01\u548c\u63d0\u793a\u8bcd\u7f13\u5b58\u7b56\u7565\u4ece\u6838\u5fc3\u4e2d\u79fb\u51fa\u3002<\/li>\n<li>Moonshot \u4f7f\u7528 <code>catalog<\/code> \u548c <code>wrapStreamFn<\/code>\uff0c\u56e0\u4e3a\u5b83\u4ecd\u4f7f\u7528\u5171\u4eab OpenAI \u4f20\u8f93\uff0c\u4f46\u9700\u8981 provider \u81ea\u6709 thinking \u8d1f\u8f7d\u89c4\u8303\u5316\u3002<\/li>\n<li>Kilocode \u4f7f\u7528 <code>catalog<\/code>\u3001<code>capabilities<\/code>\u3001<code>wrapStreamFn<\/code> \u548c <code>isCacheTtlEligible<\/code>\uff0c\u56e0\u4e3a\u5b83\u9700\u8981 provider \u81ea\u6709\u8bf7\u6c42\u5934\u3001reasoning \u8d1f\u8f7d\u89c4\u8303\u5316\u3001Gemini \u8f6c\u5f55\u63d0\u793a\u548c Anthropic cache-TTL \u95e8\u63a7\u3002<\/li>\n<li>Z.AI \u4f7f\u7528 <code>resolveDynamicModel<\/code>\u3001<code>prepareExtraParams<\/code>\u3001<code>wrapStreamFn<\/code>\u3001<code>isCacheTtlEligible<\/code>\u3001<code>isBinaryThinking<\/code>\u3001<code>isModernModelRef<\/code>\u3001<code>resolveUsageAuth<\/code> \u548c <code>fetchUsageSnapshot<\/code>\uff0c\u56e0\u4e3a\u5b83\u62e5\u6709 GLM-5 \u540e\u5907\u3001<code>tool_stream<\/code> \u9ed8\u8ba4\u503c\u3001\u4e8c\u5143 thinking UX\u3001\u73b0\u4ee3\u6a21\u578b\u5339\u914d\uff0c\u4ee5\u53ca usage \u8eab\u4efd\u9a8c\u8bc1 + quota \u6293\u53d6\u3002<\/li>\n<li>Mistral\u3001OpenCode Zen \u548c OpenCode Go \u4ec5\u4f7f\u7528 <code>capabilities<\/code>\uff0c\u4ee5\u4fbf\u5c06\u8f6c\u5f55\/\u5de5\u5177\u5dee\u5f02\u79fb\u51fa\u6838\u5fc3\u3002<\/li>\n<li>\u4ec5\u76ee\u5f55\u578b\u7684\u6346\u7ed1 provider\uff0c\u4f8b\u5982 <code>byteplus<\/code>\u3001<code>cloudflare-ai-gateway<\/code>\u3001<code>huggingface<\/code>\u3001<code>kimi-coding<\/code>\u3001<code>modelstudio<\/code>\u3001<code>nvidia<\/code>\u3001<code>qianfan<\/code>\u3001<code>synthetic<\/code>\u3001<code>together<\/code>\u3001<code>venice<\/code>\u3001<code>vercel-ai-gateway<\/code> \u548c <code>volcengine<\/code>\uff0c\u4ec5\u4f7f\u7528 <code>catalog<\/code>\u3002<\/li>\n<li>Qwen portal \u4f7f\u7528 <code>catalog<\/code>\u3001<code>auth<\/code> \u548c <code>refreshOAuth<\/code>\u3002<\/li>\n<li>MiniMax \u548c Xiaomi \u4f7f\u7528 <code>catalog<\/code> \u52a0 usage hooks\uff0c\u56e0\u4e3a\u5c3d\u7ba1\u63a8\u7406\u4ecd\u901a\u8fc7\u5171\u4eab\u4f20\u8f93\u8fd0\u884c\uff0c\u4f46\u5b83\u4eec\u7684 <code>\/usage<\/code> \u884c\u4e3a\u7531\u63d2\u4ef6\u62e5\u6709\u3002<\/li>\n<\/ul>\n<h2>\u52a0\u8f7d\u6d41\u6c34\u7ebf<\/h2>\n<p>\u542f\u52a8\u65f6\uff0cOpenClaw \u5927\u81f4\u4f1a\u6267\u884c\u4ee5\u4e0b\u6b65\u9aa4\uff1a<\/p>\n<ol>\n<li>\u53d1\u73b0\u5019\u9009\u63d2\u4ef6\u6839\u76ee\u5f55<\/li>\n<li>\u8bfb\u53d6\u539f\u751f\u6216\u517c\u5bb9 bundle \u7684 manifest \u548c\u5305\u5143\u6570\u636e<\/li>\n<li>\u62d2\u7edd\u4e0d\u5b89\u5168\u7684\u5019\u9009\u9879<\/li>\n<li>\u89c4\u8303\u5316\u63d2\u4ef6\u914d\u7f6e\uff08<code>plugins.enabled<\/code>\u3001<code>allow<\/code>\u3001<code>deny<\/code>\u3001<code>entries<\/code>\u3001<code>slots<\/code>\u3001<code>load.paths<\/code>\uff09<\/li>\n<li>\u51b3\u5b9a\u6bcf\u4e2a\u5019\u9009\u9879\u7684\u542f\u7528\u72b6\u6001<\/li>\n<li>\u901a\u8fc7 jiti \u52a0\u8f7d\u5df2\u542f\u7528\u7684\u539f\u751f\u6a21\u5757<\/li>\n<li>\u8c03\u7528\u539f\u751f <code>register(api)<\/code> hooks\uff0c\u5e76\u5c06\u6ce8\u518c\u5185\u5bb9\u6536\u96c6\u5230\u63d2\u4ef6\u6ce8\u518c\u8868\u4e2d<\/li>\n<li>\u5c06\u6ce8\u518c\u8868\u66b4\u9732\u7ed9\u547d\u4ee4\/\u8fd0\u884c\u65f6\u8868\u9762<\/li>\n<\/ol>\n<p>\u5b89\u5168\u95e8\u4f1a\u5728\u8fd0\u884c\u65f6\u6267\u884c <strong>\u4e4b\u524d<\/strong> \u53d1\u751f\u3002<br \/>\n\u5f53\u6761\u76ee\u9003\u9038\u51fa\u63d2\u4ef6\u6839\u76ee\u5f55\u3001\u8def\u5f84\u5bf9\u6240\u6709\u4eba\u53ef\u5199\uff0c\u6216\u5bf9\u4e8e\u975e\u6346\u7ed1\u63d2\u4ef6\u6765\u8bf4\u8def\u5f84\u6240\u6709\u6743\u770b\u8d77\u6765\u53ef\u7591\u65f6\uff0c\u5019\u9009\u9879\u4f1a\u88ab\u963b\u6b62\u3002<\/p>\n<h3>\u6e05\u5355\u4f18\u5148\u884c\u4e3a<\/h3>\n<p>Manifest \u662f\u63a7\u5236\u9762\u7684\u4e8b\u5b9e\u6765\u6e90\u3002OpenClaw \u7528\u5b83\u6765\uff1a<\/p>\n<ul>\n<li>\u8bc6\u522b\u63d2\u4ef6<\/li>\n<li>\u53d1\u73b0\u58f0\u660e\u7684\u6e20\u9053\/skills\/\u914d\u7f6e schema \u6216 bundle \u80fd\u529b<\/li>\n<li>\u9a8c\u8bc1 <code>plugins.entries.&lt;id&gt;.config<\/code><\/li>\n<li>\u589e\u5f3a Control UI \u6807\u7b7e\/\u5360\u4f4d\u7b26<\/li>\n<li>\u663e\u793a\u5b89\u88c5\/\u76ee\u5f55\u5143\u6570\u636e<\/li>\n<\/ul>\n<p>\u5bf9\u4e8e\u539f\u751f\u63d2\u4ef6\uff0c\u8fd0\u884c\u65f6\u6a21\u5757\u662f\u6570\u636e\u9762\u90e8\u5206\u3002\u5b83\u6ce8\u518c\u5b9e\u9645\u884c\u4e3a\uff0c\u4f8b\u5982 hooks\u3001\u5de5\u5177\u3001\u547d\u4ee4\u6216 provider \u6d41\u7a0b\u3002<\/p>\n<h3>\u52a0\u8f7d\u5668\u7f13\u5b58\u4e86\u4ec0\u4e48<\/h3>\n<p>OpenClaw \u4f1a\u4fdd\u7559\u77ed\u671f\u8fdb\u7a0b\u5185\u7f13\u5b58\uff0c\u7528\u4e8e\uff1a<\/p>\n<ul>\n<li>\u53d1\u73b0\u7ed3\u679c<\/li>\n<li>manifest \u6ce8\u518c\u8868\u6570\u636e<\/li>\n<li>\u5df2\u52a0\u8f7d\u7684\u63d2\u4ef6\u6ce8\u518c\u8868<\/li>\n<\/ul>\n<p>\u8fd9\u4e9b\u7f13\u5b58\u53ef\u4ee5\u51cf\u5c11\u7a81\u53d1\u542f\u52a8\u548c\u91cd\u590d\u547d\u4ee4\u5f00\u9500\u3002\u4f60\u53ef\u4ee5\u5c06\u5b83\u4eec\u7406\u89e3\u4e3a\u77ed\u751f\u547d\u5468\u671f\u7684\u6027\u80fd\u7f13\u5b58\uff0c\u800c\u4e0d\u662f\u6301\u4e45\u5316\u5b58\u50a8\u3002<\/p>\n<h2>\u8fd0\u884c\u65f6\u8f85\u52a9\u5de5\u5177<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7 <code>api.runtime<\/code> \u8bbf\u95ee\u90e8\u5206\u6838\u5fc3\u8f85\u52a9\u5de5\u5177\u3002\u5bf9\u4e8e\u7535\u8bdd TTS\uff1a<\/p>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nconst result = await api.runtime.tts.textToSpeechTelephony({<br \/>\n  text: &#8220;Hello from OpenClaw&#8221;,<br \/>\n  cfg: api.config,<br \/>\n});<\/p>\n<pre><code>\n\u8bf4\u660e\uff1a\n\n* \u4f7f\u7528\u6838\u5fc3 `messages.tts` \u914d\u7f6e\uff08OpenAI \u6216 ElevenLabs\uff09\u3002\n* \u8fd4\u56de PCM \u97f3\u9891\u7f13\u51b2\u533a + \u91c7\u6837\u7387\u3002\u63d2\u4ef6\u5fc5\u987b\u4e3a provider \u91cd\u65b0\u91c7\u6837\/\u7f16\u7801\u3002\n* Edge TTS \u4e0d\u652f\u6301\u7535\u8bdd\u573a\u666f\u3002\n\n\u5bf9\u4e8e STT\/\u8f6c\u5f55\uff0c\u63d2\u4ef6\u53ef\u4ee5\u8c03\u7528\uff1a\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nconst { text } = await api.runtime.stt.transcribeAudioFile({\n  filePath: &quot;\/tmp\/inbound-audio.ogg&quot;,\n  cfg: api.config,\n  \/\/ \u5f53\u65e0\u6cd5\u53ef\u9760\u63a8\u65ad MIME \u65f6\u53ef\u9009\uff1a\n  mime: &quot;audio\/ogg&quot;,\n});\n<\/code><\/pre>\n<p>\u8bf4\u660e\uff1a<\/p>\n<ul>\n<li>\u4f7f\u7528\u6838\u5fc3\u5a92\u4f53\u7406\u89e3\u97f3\u9891\u914d\u7f6e\uff08<code>tools.media.audio<\/code>\uff09\u548c provider \u540e\u5907\u987a\u5e8f\u3002<\/li>\n<li>\u5f53\u6ca1\u6709\u751f\u6210\u8f6c\u5f55\u8f93\u51fa\u65f6\uff08\u4f8b\u5982\u8f93\u5165\u88ab\u8df3\u8fc7\/\u4e0d\u53d7\u652f\u6301\uff09\uff0c\u8fd4\u56de <code>{ text: undefined }<\/code>\u3002<\/li>\n<\/ul>\n<h2>Gateway HTTP \u8def\u7531<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528 <code>api.registerHttpRoute(...)<\/code> \u516c\u5f00 HTTP \u7aef\u70b9\u3002<\/p>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\napi.registerHttpRoute({<br \/>\n  path: &#8220;\/acme\/webhook&#8221;,<br \/>\n  auth: &#8220;plugin&#8221;,<br \/>\n  match: &#8220;exact&#8221;,<br \/>\n  handler: async (_req, res) =&gt; {<br \/>\n    res.statusCode = 200;<br \/>\n    res.end(&#8220;ok&#8221;);<br \/>\n    return true;<br \/>\n  },<br \/>\n});<\/p>\n<pre><code>\n\u8def\u7531\u5b57\u6bb5\uff1a\n\n* `path`\uff1aGateway \u7f51\u5173 HTTP \u670d\u52a1\u5668\u4e0b\u7684\u8def\u7531\u8def\u5f84\u3002\n* `auth`\uff1a\u5fc5\u586b\u3002\u4f7f\u7528 `&quot;gateway&quot;` \u4ee5\u8981\u6c42\u5e38\u89c4 gateway \u8eab\u4efd\u9a8c\u8bc1\uff0c\u6216\u4f7f\u7528 `&quot;plugin&quot;` \u4ee5\u8fdb\u884c\u63d2\u4ef6\u7ba1\u7406\u7684\u8eab\u4efd\u9a8c\u8bc1\/webhook \u9a8c\u8bc1\u3002\n* `match`\uff1a\u53ef\u9009\u3002`&quot;exact&quot;`\uff08\u9ed8\u8ba4\uff09\u6216 `&quot;prefix&quot;`\u3002\n* `replaceExisting`\uff1a\u53ef\u9009\u3002\u5141\u8bb8\u540c\u4e00\u63d2\u4ef6\u66ff\u6362\u81ea\u8eab\u73b0\u6709\u7684\u8def\u7531\u6ce8\u518c\u3002\n* `handler`\uff1a\u5f53\u8def\u7531\u5904\u7406\u4e86\u8bf7\u6c42\u65f6\u8fd4\u56de `true`\u3002\n\n\u8bf4\u660e\uff1a\n\n* `api.registerHttpHandler(...)` \u5df2\u8fc7\u65f6\u3002\u8bf7\u4f7f\u7528 `api.registerHttpRoute(...)`\u3002\n* \u63d2\u4ef6\u8def\u7531\u5fc5\u987b\u663e\u5f0f\u58f0\u660e `auth`\u3002\n* \u9664\u975e\u8bbe\u7f6e `replaceExisting: true`\uff0c\u5426\u5219\u7cbe\u786e `path + match` \u51b2\u7a81\u4f1a\u88ab\u62d2\u7edd\uff0c\u800c\u4e14\u4e00\u4e2a\u63d2\u4ef6\u4e0d\u80fd\u66ff\u6362\u53e6\u4e00\u4e2a\u63d2\u4ef6\u7684\u8def\u7531\u3002\n* \u5177\u6709\u4e0d\u540c `auth` \u7ea7\u522b\u7684\u91cd\u53e0\u8def\u7531\u4f1a\u88ab\u62d2\u7edd\u3002\u8bf7\u4ec5\u5728\u76f8\u540c auth \u7ea7\u522b\u4e0a\u4fdd\u7559 `exact`\/`prefix` \u8d2f\u7a7f\u94fe\u3002\n\n## Plugin SDK \u5bfc\u5165\u8def\u5f84\n\n\u7f16\u5199\u63d2\u4ef6\u65f6\uff0c\u8bf7\u4f7f\u7528 SDK \u5b50\u8def\u5f84\uff0c\u800c\u4e0d\u662f\u5355\u4f53\u5f0f `openclaw\/plugin-sdk` \u5bfc\u5165\uff1a\n\n* `openclaw\/plugin-sdk\/core` \u7528\u4e8e\u901a\u7528\u63d2\u4ef6 API\u3001provider \u8eab\u4efd\u9a8c\u8bc1\u7c7b\u578b\u548c\u5171\u4eab\u8f85\u52a9\u5de5\u5177\u3002\n* `openclaw\/plugin-sdk\/compat` \u7528\u4e8e\u6bd4 `core` \u9700\u8981\u66f4\u5e7f\u6cdb\u5171\u4eab\u8fd0\u884c\u65f6\u8f85\u52a9\u5de5\u5177\u7684\u6346\u7ed1\/\u5185\u90e8\u63d2\u4ef6\u4ee3\u7801\u3002\n* `openclaw\/plugin-sdk\/telegram` \u7528\u4e8e Telegram \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/discord` \u7528\u4e8e Discord \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/slack` \u7528\u4e8e Slack \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/signal` \u7528\u4e8e Signal \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/imessage` \u7528\u4e8e iMessage \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/whatsapp` \u7528\u4e8e WhatsApp \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/line` \u7528\u4e8e LINE \u6e20\u9053\u63d2\u4ef6\u3002\n* `openclaw\/plugin-sdk\/msteams` \u7528\u4e8e\u6346\u7ed1\u7684 Microsoft Teams \u63d2\u4ef6\u8868\u9762\u3002\n* \u4e5f\u63d0\u4f9b\u6346\u7ed1\u6269\u5c55\u4e13\u7528\u5b50\u8def\u5f84\uff1a\n  `openclaw\/plugin-sdk\/acpx`\u3001`openclaw\/plugin-sdk\/bluebubbles`\u3001\n  `openclaw\/plugin-sdk\/copilot-proxy`\u3001`openclaw\/plugin-sdk\/device-pair`\u3001\n  `openclaw\/plugin-sdk\/diagnostics-otel`\u3001`openclaw\/plugin-sdk\/diffs`\u3001\n  `openclaw\/plugin-sdk\/feishu`\u3001`openclaw\/plugin-sdk\/googlechat`\u3001\n  `openclaw\/plugin-sdk\/irc`\u3001`openclaw\/plugin-sdk\/llm-task`\u3001\n  `openclaw\/plugin-sdk\/lobster`\u3001`openclaw\/plugin-sdk\/matrix`\u3001\n  `openclaw\/plugin-sdk\/mattermost`\u3001`openclaw\/plugin-sdk\/memory-core`\u3001\n  `openclaw\/plugin-sdk\/memory-lancedb`\u3001\n  `openclaw\/plugin-sdk\/minimax-portal-auth`\u3001\n  `openclaw\/plugin-sdk\/nextcloud-talk`\u3001`openclaw\/plugin-sdk\/nostr`\u3001\n  `openclaw\/plugin-sdk\/open-prose`\u3001`openclaw\/plugin-sdk\/phone-control`\u3001\n  `openclaw\/plugin-sdk\/qwen-portal-auth`\u3001`openclaw\/plugin-sdk\/synology-chat`\u3001\n  `openclaw\/plugin-sdk\/talk-voice`\u3001`openclaw\/plugin-sdk\/test-utils`\u3001\n  `openclaw\/plugin-sdk\/thread-ownership`\u3001`openclaw\/plugin-sdk\/tlon`\u3001\n  `openclaw\/plugin-sdk\/twitch`\u3001`openclaw\/plugin-sdk\/voice-call`\u3001\n  `openclaw\/plugin-sdk\/zalo` \u548c `openclaw\/plugin-sdk\/zalouser`\u3002\n\n## Provider \u76ee\u5f55\n\nProvider \u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528\n`registerProvider({ catalog: { run(...) { ... } } })`\n\u5b9a\u4e49\u7528\u4e8e\u63a8\u7406\u7684\u6a21\u578b\u76ee\u5f55\u3002\n\n`catalog.run(...)` \u8fd4\u56de\u4e0e OpenClaw \u5199\u5165\n`models.providers` \u76f8\u540c\u7684\u7ed3\u6784\uff1a\n\n* `{ provider }` \u8868\u793a\u4e00\u4e2a provider \u6761\u76ee\n* `{ providers }` \u8868\u793a\u591a\u4e2a provider \u6761\u76ee\n\n\u5f53\u63d2\u4ef6\u62e5\u6709 provider \u7279\u5b9a\u7684 model id\u3001base URL \u9ed8\u8ba4\u503c\u6216\u7531\u8eab\u4efd\u9a8c\u8bc1\u63a7\u5236\u7684\u6a21\u578b\u5143\u6570\u636e\u65f6\uff0c\u8bf7\u4f7f\u7528 `catalog`\u3002\n\n`catalog.order` \u63a7\u5236\u63d2\u4ef6\u76ee\u5f55\u76f8\u5bf9\u4e8e OpenClaw \u5185\u7f6e\u9690\u5f0f provider \u7684\u5408\u5e76\u65f6\u673a\uff1a\n\n* `simple`\uff1a\u7eaf API \u5bc6\u94a5\u6216\u73af\u5883\u53d8\u91cf\u9a71\u52a8\u7684 provider\n* `profile`\uff1a\u5f53\u5b58\u5728 auth profile \u65f6\u51fa\u73b0\u7684 provider\n* `paired`\uff1a\u4f1a\u5408\u6210\u591a\u4e2a\u76f8\u5173 provider \u6761\u76ee\u7684 provider\n* `late`\uff1a\u6700\u540e\u4e00\u8f6e\uff0c\u5728\u5176\u4ed6\u9690\u5f0f provider \u4e4b\u540e\n\n\u540e\u51fa\u73b0\u7684 provider \u4f1a\u5728\u952e\u51b2\u7a81\u65f6\u80dc\u51fa\uff0c\u56e0\u6b64\u63d2\u4ef6\u53ef\u4ee5\u6709\u610f\u7528\u76f8\u540c provider id \u8986\u76d6\u5185\u7f6e provider \u6761\u76ee\u3002\n\n\u517c\u5bb9\u6027\uff1a\n\n* `discovery` \u4ecd\u53ef\u4f5c\u4e3a\u65e7\u7248\u522b\u540d\u4f7f\u7528\n* \u5982\u679c\u540c\u65f6\u6ce8\u518c\u4e86 `catalog` \u548c `discovery`\uff0cOpenClaw \u4f1a\u4f7f\u7528 `catalog`\n\n\u517c\u5bb9\u6027\u8bf4\u660e\uff1a\n\n* `openclaw\/plugin-sdk` \u4ecd\u652f\u6301\u73b0\u6709\u5916\u90e8\u63d2\u4ef6\u3002\n* \u65b0\u7684\u548c\u5df2\u8fc1\u79fb\u7684\u6346\u7ed1\u63d2\u4ef6\u5e94\u4f7f\u7528\u6e20\u9053\u6216\u6269\u5c55\u4e13\u7528\u5b50\u8def\u5f84\uff1b\u901a\u7528\u8868\u9762\u4f7f\u7528 `core`\uff0c\u53ea\u6709\u5728\u786e\u5b9e\u9700\u8981\u66f4\u5e7f\u6cdb\u5171\u4eab\u8f85\u52a9\u5de5\u5177\u65f6\u624d\u4f7f\u7528 `compat`\u3002\n\n## \u53ea\u8bfb\u6e20\u9053\u68c0\u67e5\n\n\u5982\u679c\u4f60\u7684\u63d2\u4ef6\u6ce8\u518c\u4e86\u4e00\u4e2a\u6e20\u9053\uff0c\u5efa\u8bae\u4e0e `resolveAccount(...)` \u4e00\u8d77\u5b9e\u73b0\n`plugin.config.inspectAccount(cfg, accountId)`\u3002\n\n\u539f\u56e0\uff1a\n\n* `resolveAccount(...)` \u662f\u8fd0\u884c\u65f6\u8def\u5f84\u3002\u5b83\u53ef\u4ee5\u5047\u5b9a\u51ed\u636e\u5df2\u5b8c\u5168\u5b9e\u4f53\u5316\uff0c\u5e76\u5728\u7f3a\u5c11\u6240\u9700 secret \u65f6\u5feb\u901f\u5931\u8d25\u3002\n* \u53ea\u8bfb\u547d\u4ee4\u8def\u5f84\uff0c\u4f8b\u5982 `openclaw status`\u3001`openclaw status --all`\u3001\n  `openclaw channels status`\u3001`openclaw channels resolve` \u4ee5\u53ca Doctor\/\u914d\u7f6e\u4fee\u590d\u6d41\u7a0b\uff0c\u4e0d\u5e94\u4ec5\u4e3a\u4e86\u63cf\u8ff0\u914d\u7f6e\u5c31\u5fc5\u987b\u5b9e\u4f53\u5316\u8fd0\u884c\u65f6\u51ed\u636e\u3002\n\n\u63a8\u8350\u7684 `inspectAccount(...)` \u884c\u4e3a\uff1a\n\n* \u4ec5\u8fd4\u56de\u63cf\u8ff0\u6027\u7684\u8d26\u6237\u72b6\u6001\u3002\n* \u4fdd\u7559 `enabled` \u548c `configured`\u3002\n* \u5728\u76f8\u5173\u65f6\u5305\u542b\u51ed\u636e\u6765\u6e90\/\u72b6\u6001\u5b57\u6bb5\uff0c\u4f8b\u5982\uff1a\n  * `tokenSource`\u3001`tokenStatus`\n  * `botTokenSource`\u3001`botTokenStatus`\n  * `appTokenSource`\u3001`appTokenStatus`\n  * `signingSecretSource`\u3001`signingSecretStatus`\n* \u4f60\u65e0\u9700\u4e3a\u4e86\u62a5\u544a\u53ea\u8bfb\u53ef\u7528\u6027\u800c\u8fd4\u56de\u539f\u59cb\u4ee4\u724c\u503c\u3002\u8fd4\u56de `tokenStatus: &quot;available&quot;`\uff08\u4ee5\u53ca\u5339\u914d\u7684 source \u5b57\u6bb5\uff09\u5c31\u8db3\u591f\u652f\u6301\u72b6\u6001\u7c7b\u547d\u4ee4\u3002\n* \u5f53\u51ed\u636e\u901a\u8fc7 SecretRef \u914d\u7f6e\uff0c\u4f46\u5728\u5f53\u524d\u547d\u4ee4\u8def\u5f84\u4e2d\u4e0d\u53ef\u7528\u65f6\uff0c\u8bf7\u4f7f\u7528 `configured_unavailable`\u3002\n\n\u8fd9\u4f7f\u5f97\u53ea\u8bfb\u547d\u4ee4\u53ef\u4ee5\u62a5\u544a\u201c\u5df2\u914d\u7f6e\uff0c\u4f46\u5728\u6b64\u547d\u4ee4\u8def\u5f84\u4e2d\u4e0d\u53ef\u7528\u201d\uff0c\u800c\u4e0d\u662f\u5d29\u6e83\u6216\u9519\u8bef\u5730\u5c06\u8d26\u6237\u62a5\u544a\u4e3a\u672a\u914d\u7f6e\u3002\n\n\u6027\u80fd\u8bf4\u660e\uff1a\n\n* \u63d2\u4ef6\u53d1\u73b0\u548c manifest \u5143\u6570\u636e\u4f7f\u7528\u77ed\u671f\u8fdb\u7a0b\u5185\u7f13\u5b58\uff0c\u4ee5\u51cf\u5c11\u7a81\u53d1\u542f\u52a8\/\u91cd\u8f7d\u5de5\u4f5c\u3002\n* \u8bbe\u7f6e `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` \u6216\n  `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1` \u53ef\u7981\u7528\u8fd9\u4e9b\u7f13\u5b58\u3002\n* \u4f7f\u7528 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` \u548c\n  `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` \u8c03\u6574\u7f13\u5b58\u7a97\u53e3\u3002\n\n## \u8bbe\u5907\u53d1\u73b0 + \u4f20\u8f93\u534f\u8bae\u4f18\u5148\u7ea7\n\nOpenClaw \u6309\u4ee5\u4e0b\u987a\u5e8f\u626b\u63cf\uff1a\n\n1. \u914d\u7f6e\u8def\u5f84\n\n* `plugins.load.paths`\uff08\u6587\u4ef6\u6216\u76ee\u5f55\uff09\n\n2. \u5de5\u4f5c\u533a\u6269\u5c55\n\n* `&lt;workspace&gt;\/.openclaw\/extensions\/*.ts`\n* `&lt;workspace&gt;\/.openclaw\/extensions\/*\/index.ts`\n\n3. \u5168\u5c40\u6269\u5c55\n\n* `~\/.openclaw\/extensions\/*.ts`\n* `~\/.openclaw\/extensions\/*\/index.ts`\n\n4. \u6346\u7ed1\u6269\u5c55\uff08\u968f OpenClaw \u4e00\u8d77\u63d0\u4f9b\uff1b\u9ed8\u8ba4\u5f00\u542f\/\u5173\u95ed\u6df7\u5408\uff09\n\n* `&lt;openclaw&gt;\/extensions\/*`\n\n\u8bb8\u591a\u6346\u7ed1\u7684 provider \u63d2\u4ef6\u9ed8\u8ba4\u542f\u7528\uff0c\u8fd9\u6837\u6a21\u578b\u76ee\u5f55\/\u8fd0\u884c\u65f6 hooks \u65e0\u9700\u989d\u5916\u8bbe\u7f6e\u5373\u53ef\u4f7f\u7528\u3002\u5176\u4ed6\u63d2\u4ef6\u4ecd\u9700\u8981\u901a\u8fc7 `plugins.entries.&lt;id&gt;.enabled` \u6216\n`openclaw plugins enable &lt;id&gt;` \u663e\u5f0f\u542f\u7528\u3002\n\n\u9ed8\u8ba4\u5f00\u542f\u7684\u6346\u7ed1\u63d2\u4ef6\u793a\u4f8b\uff1a\n\n* `byteplus`\n* `cloudflare-ai-gateway`\n* `device-pair`\n* `github-copilot`\n* `huggingface`\n* `kilocode`\n* `kimi-coding`\n* `minimax`\n* `minimax`\n* `modelstudio`\n* `moonshot`\n* `nvidia`\n* `ollama`\n* `openai`\n* `openrouter`\n* `phone-control`\n* `qianfan`\n* `qwen-portal-auth`\n* `sglang`\n* `synthetic`\n* `talk-voice`\n* `together`\n* `venice`\n* `vercel-ai-gateway`\n* `vllm`\n* `volcengine`\n* `xiaomi`\n* \u6d3b\u8dc3\u7684 memory \u63d2\u69fd\u63d2\u4ef6\uff08\u9ed8\u8ba4\u63d2\u69fd\uff1a`memory-core`\uff09\n\n\u5df2\u5b89\u88c5\u7684\u63d2\u4ef6\u9ed8\u8ba4\u542f\u7528\uff0c\u4f46\u4e5f\u53ef\u4ee5\u7528\u540c\u6837\u65b9\u5f0f\u7981\u7528\u3002\n\n\u5de5\u4f5c\u533a\u63d2\u4ef6 **\u9ed8\u8ba4\u7981\u7528**\uff0c\u9664\u975e\u4f60\u663e\u5f0f\u542f\u7528\u5b83\u4eec\u6216\u5c06\u5176\u52a0\u5165 allowlist\u3002\u8fd9\u662f\u6709\u610f\u8bbe\u8ba1\u7684\uff1a\u5df2\u68c0\u51fa\u7684\u4ed3\u5e93\u4e0d\u5e94\u6084\u6084\u53d8\u6210\u751f\u4ea7 gateway \u4ee3\u7801\u3002\n\n\u52a0\u56fa\u8bf4\u660e\uff1a\n\n* \u5982\u679c `plugins.allow` \u4e3a\u7a7a\u4e14\u53ef\u53d1\u73b0\u975e\u6346\u7ed1\u63d2\u4ef6\uff0cOpenClaw \u4f1a\u5728\u542f\u52a8\u65f6\u8bb0\u5f55\u4e00\u6761\u8b66\u544a\uff0c\u5176\u4e2d\u5305\u542b plugin id \u548c\u6765\u6e90\u3002\n* \u5019\u9009\u8def\u5f84\u5728\u88ab\u63a5\u53d7\u8fdb\u5165\u53d1\u73b0\u6d41\u7a0b\u524d\u4f1a\u7ecf\u8fc7\u5b89\u5168\u68c0\u67e5\u3002\u5f53\u51fa\u73b0\u4ee5\u4e0b\u60c5\u51b5\u65f6\uff0cOpenClaw \u4f1a\u963b\u6b62\u5019\u9009\u9879\uff1a\n  * \u6269\u5c55\u6761\u76ee\u89e3\u6790\u5230\u63d2\u4ef6\u6839\u76ee\u5f55\u4e4b\u5916\uff08\u5305\u62ec\u7b26\u53f7\u94fe\u63a5\/\u8def\u5f84\u904d\u5386\u9003\u9038\uff09\uff0c\n  * \u63d2\u4ef6\u6839\u76ee\u5f55\/\u6765\u6e90\u8def\u5f84\u5bf9\u6240\u6709\u4eba\u53ef\u5199\uff0c\n  * \u5bf9\u4e8e\u975e\u6346\u7ed1\u63d2\u4ef6\u6765\u8bf4\uff0c\u8def\u5f84\u6240\u6709\u6743\u53ef\u7591\uff08POSIX owner \u65e2\u4e0d\u662f\u5f53\u524d uid \u4e5f\u4e0d\u662f root\uff09\u3002\n* \u5bf9\u4e8e\u7f3a\u5c11\u5b89\u88c5\/\u52a0\u8f7d\u8def\u5f84\u6765\u6e90\u4fe1\u606f\u7684\u5df2\u52a0\u8f7d\u975e\u6346\u7ed1\u63d2\u4ef6\uff0c\u4f1a\u53d1\u51fa\u8b66\u544a\uff0c\u4ee5\u4fbf\u4f60\u56fa\u5b9a\u4fe1\u4efb\uff08`plugins.allow`\uff09\u6216\u5b89\u88c5\u8ddf\u8e2a\uff08`plugins.installs`\uff09\u3002\n\n\u6bcf\u4e2a\u539f\u751f OpenClaw \u63d2\u4ef6\u90fd\u5fc5\u987b\u5728\u5176\u6839\u76ee\u5f55\u4e2d\u5305\u542b\u4e00\u4e2a `openclaw.plugin.json` \u6587\u4ef6\u3002\n\u5982\u679c\u67d0\u6761\u8def\u5f84\u6307\u5411\u4e00\u4e2a\u6587\u4ef6\uff0c\u5219\u63d2\u4ef6\u6839\u76ee\u5f55\u662f\u8be5\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u5e76\u4e14\u8be5\u76ee\u5f55\u5fc5\u987b\u5305\u542b\u8be5 manifest\u3002\n\n\u517c\u5bb9\u7684 bundle \u53ef\u4ee5\u6539\u4e3a\u63d0\u4f9b\u4ee5\u4e0b\u4e4b\u4e00\uff1a\n\n* `.codex-plugin\/plugin.json`\n* `.claude-plugin\/plugin.json`\n\nBundle \u76ee\u5f55\u4f1a\u4ece\u4e0e\u539f\u751f\u63d2\u4ef6\u76f8\u540c\u7684\u6839\u76ee\u5f55\u4e2d\u88ab\u53d1\u73b0\u3002\n\n\u5982\u679c\u591a\u4e2a\u63d2\u4ef6\u89e3\u6790\u4e3a\u540c\u4e00\u4e2a id\uff0c\u5219\u4ee5\u4e0a\u987a\u5e8f\u4e2d\u7684\u7b2c\u4e00\u4e2a\u5339\u914d\u9879\u80dc\u51fa\uff0c\u4f18\u5148\u7ea7\u66f4\u4f4e\u7684\u526f\u672c\u4f1a\u88ab\u5ffd\u7565\u3002\n\n\u8fd9\u610f\u5473\u7740\uff1a\n\n* \u5de5\u4f5c\u533a\u63d2\u4ef6\u4f1a\u6709\u610f\u8986\u76d6\u5177\u6709\u76f8\u540c id \u7684\u6346\u7ed1\u63d2\u4ef6\n* `plugins.allow: [&quot;foo&quot;]` \u6309 id \u6388\u6743\u6d3b\u52a8\u7684 `foo` \u63d2\u4ef6\uff0c\u5373\u4f7f\u6d3b\u52a8\u526f\u672c\u6765\u81ea\u5de5\u4f5c\u533a\u800c\u975e\u6346\u7ed1\u6269\u5c55\u6839\u76ee\u5f55\n* \u5982\u679c\u4f60\u9700\u8981\u66f4\u4e25\u683c\u7684\u6765\u6e90\u63a7\u5236\uff0c\u8bf7\u4f7f\u7528\u663e\u5f0f\u5b89\u88c5\/\u52a0\u8f7d\u8def\u5f84\uff0c\u5e76\u5728\u542f\u7528\u524d\u68c0\u67e5\u89e3\u6790\u540e\u7684\u63d2\u4ef6\u6765\u6e90\n\n### \u542f\u7528\u89c4\u5219\n\n\u542f\u7528\u72b6\u6001\u5728\u53d1\u73b0\u540e\u89e3\u6790\uff1a\n\n* `plugins.enabled: false` \u4f1a\u7981\u7528\u6240\u6709\u63d2\u4ef6\n* `plugins.deny` \u603b\u662f\u4f18\u5148\n* `plugins.entries.&lt;id&gt;.enabled: false` \u4f1a\u7981\u7528\u8be5\u63d2\u4ef6\n* \u6765\u6e90\u4e8e\u5de5\u4f5c\u533a\u7684\u63d2\u4ef6\u9ed8\u8ba4\u7981\u7528\n* \u5f53 `plugins.allow` \u975e\u7a7a\u65f6\uff0callowlist \u4f1a\u9650\u5236\u6d3b\u52a8\u96c6\u5408\n* allowlist \u662f **\u57fa\u4e8e id** \u7684\uff0c\u800c\u4e0d\u662f\u57fa\u4e8e\u6765\u6e90\n* \u6346\u7ed1\u63d2\u4ef6\u9ed8\u8ba4\u7981\u7528\uff0c\u9664\u975e\uff1a\n  * \u6346\u7ed1 id \u4f4d\u4e8e\u5185\u7f6e\u9ed8\u8ba4\u5f00\u542f\u96c6\u5408\u4e2d\uff0c\u6216\n  * \u4f60\u663e\u5f0f\u542f\u7528\u4e86\u5b83\uff0c\u6216\n  * \u6e20\u9053\u914d\u7f6e\u9690\u5f0f\u542f\u7528\u4e86\u6346\u7ed1\u6e20\u9053\u63d2\u4ef6\n* \u72ec\u5360\u63d2\u69fd\u53ef\u5f3a\u5236\u542f\u7528\u4e3a\u8be5\u63d2\u69fd\u9009\u62e9\u7684\u63d2\u4ef6\n\n\u5728\u5f53\u524d\u6838\u5fc3\u4e2d\uff0c\u9ed8\u8ba4\u5f00\u542f\u7684\u6346\u7ed1 id \u5305\u62ec\u4e0a\u9762\u7684\u672c\u5730\/provider \u8f85\u52a9\u5de5\u5177\u4ee5\u53ca\u5f53\u524d\u6d3b\u8dc3\u7684 memory \u63d2\u69fd\u63d2\u4ef6\u3002\n\n### \u5305\u96c6\u5408\n\n\u63d2\u4ef6\u76ee\u5f55\u53ef\u4ee5\u5305\u542b\u5e26\u6709 `openclaw.extensions` \u7684 `package.json`\uff1a\n\n```json  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n{\n  &quot;name&quot;: &quot;my-pack&quot;,\n  &quot;openclaw&quot;: {\n    &quot;extensions&quot;: [&quot;.\/src\/safety.ts&quot;, &quot;.\/src\/tools.ts&quot;],\n    &quot;setupEntry&quot;: &quot;.\/src\/setup-entry.ts&quot;\n  }\n}\n<\/code><\/pre>\n<p>\u6bcf\u4e2a\u6761\u76ee\u90fd\u4f1a\u6210\u4e3a\u4e00\u4e2a\u63d2\u4ef6\u3002\u5982\u679c\u8be5\u96c6\u5408\u5217\u51fa\u591a\u4e2a\u6269\u5c55\uff0c\u5219\u63d2\u4ef6 id \u5c06\u53d8\u4e3a <code>name\/&lt;fileBase&gt;<\/code>\u3002<\/p>\n<p>\u5982\u679c\u4f60\u7684\u63d2\u4ef6\u5bfc\u5165 npm \u4f9d\u8d56\uff0c\u8bf7\u5728\u8be5\u76ee\u5f55\u4e2d\u5b89\u88c5\u5b83\u4eec\uff0c\u4ee5\u4fbf <code>node_modules<\/code> \u53ef\u7528\uff08<code>npm install<\/code> \/ <code>pnpm install<\/code>\uff09\u3002<\/p>\n<p>\u5b89\u5168\u62a4\u680f\uff1a\u6bcf\u4e2a <code>openclaw.extensions<\/code> \u6761\u76ee\u5728\u89e3\u6790\u7b26\u53f7\u94fe\u63a5\u540e\u90fd\u5fc5\u987b\u4fdd\u6301\u5728\u63d2\u4ef6\u76ee\u5f55\u5185\u3002\u9003\u9038\u51fa\u5305\u76ee\u5f55\u7684\u6761\u76ee\u4f1a\u88ab\u62d2\u7edd\u3002<\/p>\n<p>\u5b89\u5168\u8bf4\u660e\uff1a<code>openclaw plugins install<\/code> \u4f1a\u4f7f\u7528<br \/>\n<code>npm install --ignore-scripts<\/code> \u5b89\u88c5\u63d2\u4ef6\u4f9d\u8d56\uff08\u4e0d\u4f1a\u8fd0\u884c\u751f\u547d\u5468\u671f\u811a\u672c\uff09\u3002<br \/>\n\u8bf7\u4fdd\u6301\u63d2\u4ef6\u4f9d\u8d56\u6811\u4e3a\u201c\u7eaf JS\/TS\u201d\uff0c\u5e76\u907f\u514d\u9700\u8981 <code>postinstall<\/code> \u6784\u5efa\u7684\u5305\u3002<\/p>\n<p>\u53ef\u9009\u9879\uff1a<code>openclaw.setupEntry<\/code> \u53ef\u4ee5\u6307\u5411\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u3001\u4ec5\u7528\u4e8e setup \u7684\u6a21\u5757\u3002<br \/>\n\u5f53 OpenClaw \u9700\u8981\u4e3a\u4e00\u4e2a\u5df2\u7981\u7528\u7684\u6e20\u9053\u63d2\u4ef6\u63d0\u4f9b setup \u8868\u9762\uff0c\u6216\u67d0\u4e2a\u6e20\u9053\u63d2\u4ef6\u867d\u7136\u5df2\u542f\u7528\u4f46\u4ecd\u672a\u914d\u7f6e\u65f6\uff0c\u5b83\u4f1a\u52a0\u8f7d <code>setupEntry<\/code>\uff0c\u800c\u4e0d\u662f\u5b8c\u6574\u63d2\u4ef6\u5165\u53e3\u3002<br \/>\n\u5f53\u4f60\u7684\u4e3b\u63d2\u4ef6\u5165\u53e3\u8fd8\u8fde\u63a5\u4e86\u5de5\u5177\u3001hooks \u6216\u5176\u4ed6\u4ec5\u8fd0\u884c\u65f6\u4ee3\u7801\u65f6\uff0c\u8fd9\u80fd\u8ba9\u542f\u52a8\u548c setup \u66f4\u8f7b\u91cf\u3002<\/p>\n<h3>\u6e20\u9053\u76ee\u5f55\u5143\u6570\u636e<\/h3>\n<p>\u6e20\u9053\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7 <code>openclaw.channel<\/code> \u516c\u5e03 setup\/discovery \u5143\u6570\u636e\uff0c\u5e76\u901a\u8fc7 <code>openclaw.install<\/code> \u516c\u5e03\u5b89\u88c5\u63d0\u793a\u3002\u8fd9\u4f7f\u6838\u5fc3\u76ee\u5f55\u4fdd\u6301\u65e0\u6570\u636e\u5316\u3002<\/p>\n<p>\u793a\u4f8b\uff1a<\/p>\n<p>&#8220;`json  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  &#8220;name&#8221;: &#8220;@openclaw\/nextcloud-talk&#8221;,<br \/>\n  &#8220;openclaw&#8221;: {<br \/>\n    &#8220;extensions&#8221;: [&#8220;.\/index.ts&#8221;],<br \/>\n    &#8220;channel&#8221;: {<br \/>\n      &#8220;id&#8221;: &#8220;nextcloud-talk&#8221;,<br \/>\n      &#8220;label&#8221;: &#8220;Nextcloud Talk&#8221;,<br \/>\n      &#8220;selectionLabel&#8221;: &#8220;Nextcloud Talk (self-hosted)&#8221;,<br \/>\n      &#8220;docsPath&#8221;: &#8220;\/channels\/nextcloud-talk&#8221;,<br \/>\n      &#8220;docsLabel&#8221;: &#8220;nextcloud-talk&#8221;,<br \/>\n      &#8220;blurb&#8221;: &#8220;\u901a\u8fc7 Nextcloud Talk webhook bot \u63d0\u4f9b\u7684\u81ea\u6258\u7ba1\u804a\u5929\u3002&#8221;,<br \/>\n      &#8220;order&#8221;: 65,<br \/>\n      &#8220;aliases&#8221;: [&#8220;nc-talk&#8221;, &#8220;nc&#8221;]<br \/>\n    },<br \/>\n    &#8220;install&#8221;: {<br \/>\n      &#8220;npmSpec&#8221;: &#8220;@openclaw\/nextcloud-talk&#8221;,<br \/>\n      &#8220;localPath&#8221;: &#8220;extensions\/nextcloud-talk&#8221;,<br \/>\n      &#8220;defaultChoice&#8221;: &#8220;npm&#8221;<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<pre><code>\nOpenClaw \u8fd8\u53ef\u4ee5\u5408\u5e76 **\u5916\u90e8\u6e20\u9053\u76ee\u5f55**\uff08\u4f8b\u5982 MPM registry \u5bfc\u51fa\uff09\u3002\n\u5c06 JSON \u6587\u4ef6\u653e\u5230\u4ee5\u4e0b\u4efb\u4e00\u4f4d\u7f6e\uff1a\n\n* `~\/.openclaw\/mpm\/plugins.json`\n* `~\/.openclaw\/mpm\/catalog.json`\n* `~\/.openclaw\/plugins\/catalog.json`\n\n\u6216\u8005\u5c06 `OPENCLAW_PLUGIN_CATALOG_PATHS`\uff08\u6216 `OPENCLAW_MPM_CATALOG_PATHS`\uff09\u6307\u5411\u4e00\u4e2a\u6216\u591a\u4e2a JSON \u6587\u4ef6\uff08\u7528\u9017\u53f7\/\u5206\u53f7\/`PATH` \u5206\u9694\uff09\u3002\n\u6bcf\u4e2a\u6587\u4ef6\u5e94\u5305\u542b\n`{ &quot;entries&quot;: [ { &quot;name&quot;: &quot;@scope\/pkg&quot;, &quot;openclaw&quot;: { &quot;channel&quot;: {...}, &quot;install&quot;: {...} } } ] }`\u3002\n\n## Plugin ID\n\n\u9ed8\u8ba4 plugin id\uff1a\n\n* \u5305\u96c6\u5408\uff1a`package.json` \u4e2d\u7684 `name`\n* \u72ec\u7acb\u6587\u4ef6\uff1a\u6587\u4ef6\u57fa\u7840\u540d\uff08`~\/...\/voice-call.ts` \u2192 `voice-call`\uff09\n\n\u5982\u679c\u63d2\u4ef6\u5bfc\u51fa `id`\uff0cOpenClaw \u4f1a\u4f7f\u7528\u5b83\uff0c\u4f46\u5982\u679c\u5b83\u4e0e\u914d\u7f6e\u7684 id \u4e0d\u5339\u914d\uff0c\u5219\u4f1a\u53d1\u51fa\u8b66\u544a\u3002\n\n## \u6ce8\u518c\u8868\u6a21\u578b\n\n\u5df2\u52a0\u8f7d\u7684\u63d2\u4ef6\u4e0d\u4f1a\u76f4\u63a5\u4fee\u6539\u4efb\u610f\u6838\u5fc3\u5168\u5c40\u5bf9\u8c61\u3002\u5b83\u4eec\u4f1a\u6ce8\u518c\u5230\u4e00\u4e2a\u4e2d\u592e\u63d2\u4ef6\u6ce8\u518c\u8868\u4e2d\u3002\n\n\u8be5\u6ce8\u518c\u8868\u8ddf\u8e2a\uff1a\n\n* \u63d2\u4ef6\u8bb0\u5f55\uff08\u8eab\u4efd\u3001\u6765\u6e90\u3001\u51fa\u5904\u3001\u72b6\u6001\u3001\u8bca\u65ad\uff09\n* \u5de5\u5177\n* \u65e7\u7248 hooks \u548c\u7c7b\u578b\u5316 hooks\n* \u6e20\u9053\n* providers\n* Gateway RPC \u5904\u7406\u5668\n* HTTP \u8def\u7531\n* CLI \u6ce8\u518c\u5668\n* \u540e\u53f0\u670d\u52a1\n* \u63d2\u4ef6\u81ea\u6709\u547d\u4ee4\n\n\u7136\u540e\uff0c\u6838\u5fc3\u529f\u80fd\u4f1a\u4ece\u8fd9\u4e2a\u6ce8\u518c\u8868\u4e2d\u8bfb\u53d6\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u4e0e\u63d2\u4ef6\u6a21\u5757\u4ea4\u4e92\u3002\u8fd9\u6837\u53ef\u4ee5\u4fdd\u6301\u5355\u5411\u52a0\u8f7d\uff1a\n\n* \u63d2\u4ef6\u6a21\u5757 -&gt; \u6ce8\u518c\u8868\u6ce8\u518c\n* \u6838\u5fc3\u8fd0\u884c\u65f6 -&gt; \u6ce8\u518c\u8868\u6d88\u8d39\n\n\u8fd9\u79cd\u5206\u79bb\u5bf9\u53ef\u7ef4\u62a4\u6027\u975e\u5e38\u91cd\u8981\u3002\u8fd9\u610f\u5473\u7740\u5927\u591a\u6570\u6838\u5fc3\u8868\u9762\u53ea\u9700\u8981\u4e00\u4e2a\u96c6\u6210\u70b9\uff1a\u201c\u8bfb\u53d6\u6ce8\u518c\u8868\u201d\uff0c\u800c\u4e0d\u662f\u201c\u4e3a\u6bcf\u4e2a\u63d2\u4ef6\u6a21\u5757\u505a\u7279\u6b8a\u5904\u7406\u201d\u3002\n\n## \u914d\u7f6e\n\n```json5  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n{\n  plugins: {\n    enabled: true,\n    allow: [&quot;voice-call&quot;],\n    deny: [&quot;untrusted-plugin&quot;],\n    load: { paths: [&quot;~\/Projects\/oss\/voice-call-extension&quot;] },\n    entries: {\n      &quot;voice-call&quot;: { enabled: true, config: { provider: &quot;twilio&quot; } },\n    },\n  },\n}\n<\/code><\/pre>\n<p>\u5b57\u6bb5\uff1a<\/p>\n<ul>\n<li><code>enabled<\/code>\uff1a\u603b\u5f00\u5173\uff08\u9ed8\u8ba4\uff1atrue\uff09<\/li>\n<li><code>allow<\/code>\uff1aallowlist\uff08\u53ef\u9009\uff09<\/li>\n<li><code>deny<\/code>\uff1adenylist\uff08\u53ef\u9009\uff1bdeny \u4f18\u5148\uff09<\/li>\n<li><code>load.paths<\/code>\uff1a\u989d\u5916\u7684\u63d2\u4ef6\u6587\u4ef6\/\u76ee\u5f55<\/li>\n<li><code>slots<\/code>\uff1a\u72ec\u5360\u63d2\u69fd\u9009\u62e9\u5668\uff0c\u4f8b\u5982 <code>memory<\/code> \u548c <code>contextEngine<\/code><\/li>\n<li><code>entries.&lt;id&gt;<\/code>\uff1a\u6bcf\u63d2\u4ef6\u5f00\u5173 + \u914d\u7f6e<\/li>\n<\/ul>\n<p>\u914d\u7f6e\u66f4\u6539 <strong>\u9700\u8981\u91cd\u542f gateway<\/strong>\u3002<\/p>\n<p>\u9a8c\u8bc1\u89c4\u5219\uff08\u4e25\u683c\uff09\uff1a<\/p>\n<ul>\n<li><code>entries<\/code>\u3001<code>allow<\/code>\u3001<code>deny<\/code> \u6216 <code>slots<\/code> \u4e2d\u51fa\u73b0\u672a\u77e5 plugin id \u90fd\u662f <strong>\u9519\u8bef<\/strong>\u3002<\/li>\n<li>\u672a\u77e5\u7684 <code>channels.&lt;id&gt;<\/code> \u952e\u90fd\u662f <strong>\u9519\u8bef<\/strong>\uff0c\u9664\u975e\u67d0\u4e2a\u63d2\u4ef6 manifest \u58f0\u660e\u4e86\u8be5\u6e20\u9053 id\u3002<\/li>\n<li>\u539f\u751f\u63d2\u4ef6\u914d\u7f6e\u4f7f\u7528\u5d4c\u5165\u5728 <code>openclaw.plugin.json<\/code> \u4e2d\u7684 JSON Schema\uff08<code>configSchema<\/code>\uff09\u8fdb\u884c\u9a8c\u8bc1\u3002<\/li>\n<li>\u517c\u5bb9\u7684 bundle \u5f53\u524d\u4e0d\u516c\u5f00\u539f\u751f OpenClaw \u914d\u7f6e schema\u3002<\/li>\n<li>\u5982\u679c\u67d0\u4e2a\u63d2\u4ef6\u88ab\u7981\u7528\uff0c\u5176\u914d\u7f6e\u4f1a\u88ab\u4fdd\u7559\uff0c\u5e76\u53d1\u51fa <strong>\u8b66\u544a<\/strong>\u3002<\/li>\n<\/ul>\n<h3>\u7981\u7528 vs \u7f3a\u5931 vs \u65e0\u6548<\/h3>\n<p>\u8fd9\u4e9b\u72b6\u6001\u6709\u610f\u533a\u5206\uff1a<\/p>\n<ul>\n<li><strong>disabled<\/strong>\uff1a\u63d2\u4ef6\u5b58\u5728\uff0c\u4f46\u542f\u7528\u89c4\u5219\u5c06\u5176\u5173\u95ed<\/li>\n<li><strong>missing<\/strong>\uff1a\u914d\u7f6e\u5f15\u7528\u4e86\u67d0\u4e2a plugin id\uff0c\u4f46\u53d1\u73b0\u8fc7\u7a0b\u6ca1\u6709\u627e\u5230\u5b83<\/li>\n<li><strong>invalid<\/strong>\uff1a\u63d2\u4ef6\u5b58\u5728\uff0c\u4f46\u5176\u914d\u7f6e\u4e0e\u58f0\u660e\u7684 schema \u4e0d\u5339\u914d<\/li>\n<\/ul>\n<p>OpenClaw \u4f1a\u4fdd\u7559\u5df2\u7981\u7528\u63d2\u4ef6\u7684\u914d\u7f6e\uff0c\u56e0\u6b64\u91cd\u65b0\u542f\u7528\u5b83\u4eec\u4e0d\u4f1a\u9020\u6210\u7834\u574f\u3002<\/p>\n<h2>Plugin \u63d2\u69fd\uff08\u72ec\u5360\u7c7b\u522b\uff09<\/h2>\n<p>\u67d0\u4e9b\u63d2\u4ef6\u7c7b\u522b\u662f <strong>\u72ec\u5360\u7684<\/strong>\uff08\u4e00\u6b21\u53ea\u80fd\u6709\u4e00\u4e2a\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001\uff09\u3002\u4f7f\u7528<br \/>\n<code>plugins.slots<\/code> \u9009\u62e9\u7531\u54ea\u4e2a\u63d2\u4ef6\u62e5\u6709\u8be5\u63d2\u69fd\uff1a<\/p>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  plugins: {<br \/>\n    slots: {<br \/>\n      memory: &#8220;memory-core&#8221;, \/\/ \u6216 &#8220;none&#8221; \u4ee5\u7981\u7528 memory \u63d2\u4ef6<br \/>\n      contextEngine: &#8220;legacy&#8221;, \/\/ \u6216\u67d0\u4e2a plugin id\uff0c\u4f8b\u5982 &#8220;lossless-claw&#8221;<br \/>\n    },<br \/>\n  },<br \/>\n}<\/p>\n<pre><code>\n\u652f\u6301\u7684\u72ec\u5360\u63d2\u69fd\uff1a\n\n* `memory`\uff1a\u6d3b\u52a8 memory \u63d2\u4ef6\uff08`&quot;none&quot;` \u4f1a\u7981\u7528 memory \u63d2\u4ef6\uff09\n* `contextEngine`\uff1a\u6d3b\u52a8\u4e0a\u4e0b\u6587\u5f15\u64ce\u63d2\u4ef6\uff08`&quot;legacy&quot;` \u662f\u5185\u7f6e\u9ed8\u8ba4\u503c\uff09\n\n\u5982\u679c\u591a\u4e2a\u63d2\u4ef6\u58f0\u660e\u4e86 `kind: &quot;memory&quot;` \u6216 `kind: &quot;context-engine&quot;`\uff0c\u5219\u53ea\u6709\u4e3a\u8be5\u63d2\u69fd\u9009\u4e2d\u7684\u63d2\u4ef6\u4f1a\u52a0\u8f7d\u3002\u5176\u4ed6\u63d2\u4ef6\u4f1a\u88ab\u7981\u7528\u5e76\u9644\u5e26\u8bca\u65ad\u4fe1\u606f\u3002\n\n### \u4e0a\u4e0b\u6587\u5f15\u64ce\u63d2\u4ef6\n\n\u4e0a\u4e0b\u6587\u5f15\u64ce\u63d2\u4ef6\u62e5\u6709\u4f1a\u8bdd\u4e0a\u4e0b\u6587\u7f16\u6392\u80fd\u529b\uff0c\u5305\u62ec\u6444\u53d6\u3001\u7ec4\u88c5\u548c\u538b\u7f29\u3002\n\u901a\u8fc7\u63d2\u4ef6\u4e2d\u7684 `api.registerContextEngine(id, factory)` \u6ce8\u518c\u5b83\u4eec\uff0c\u7136\u540e\u4f7f\u7528\n`plugins.slots.contextEngine` \u9009\u62e9\u6d3b\u52a8\u5f15\u64ce\u3002\n\n\u5f53\u4f60\u7684\u63d2\u4ef6\u9700\u8981\u66ff\u6362\u6216\u6269\u5c55\u9ed8\u8ba4\u4e0a\u4e0b\u6587\u6d41\u6c34\u7ebf\uff0c\u800c\u4e0d\u662f\u4ec5\u6dfb\u52a0\u5185\u5b58\u641c\u7d22\u6216 hooks \u65f6\uff0c\u8bf7\u4f7f\u7528\u6b64\u65b9\u5f0f\u3002\n\n## Control UI\uff08schema + \u6807\u7b7e\uff09\n\nControl UI \u4f7f\u7528 `config.schema`\uff08JSON Schema + `uiHints`\uff09\u6765\u6e32\u67d3\u66f4\u597d\u7684\u8868\u5355\u3002\n\nOpenClaw \u4f1a\u5728\u8fd0\u884c\u65f6\u6839\u636e\u5df2\u53d1\u73b0\u7684\u63d2\u4ef6\u589e\u5f3a `uiHints`\uff1a\n\n* \u4e3a `plugins.entries.&lt;id&gt;` \/ `.enabled` \/ `.config` \u6dfb\u52a0\u6bcf\u63d2\u4ef6\u6807\u7b7e\n* \u5408\u5e76\u53ef\u9009\u7684\u63d2\u4ef6\u63d0\u4f9b\u914d\u7f6e\u5b57\u6bb5\u63d0\u793a\uff0c\u8def\u5f84\u4e3a\uff1a\n  `plugins.entries.&lt;id&gt;.config.&lt;field&gt;`\n\n\u5982\u679c\u4f60\u5e0c\u671b\u63d2\u4ef6\u914d\u7f6e\u5b57\u6bb5\u663e\u793a\u66f4\u597d\u7684\u6807\u7b7e\/\u5360\u4f4d\u7b26\uff08\u5e76\u5c06 secret \u6807\u8bb0\u4e3a\u654f\u611f\uff09\uff0c\u8bf7\u5728\u63d2\u4ef6 manifest \u4e2d\u8fde\u540c JSON Schema \u4e00\u8d77\u63d0\u4f9b `uiHints`\u3002\n\n\u793a\u4f8b\uff1a\n\n```json  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n{\n  &quot;id&quot;: &quot;my-plugin&quot;,\n  &quot;configSchema&quot;: {\n    &quot;type&quot;: &quot;object&quot;,\n    &quot;additionalProperties&quot;: false,\n    &quot;properties&quot;: {\n      &quot;apiKey&quot;: { &quot;type&quot;: &quot;string&quot; },\n      &quot;region&quot;: { &quot;type&quot;: &quot;string&quot; }\n    }\n  },\n  &quot;uiHints&quot;: {\n    &quot;apiKey&quot;: { &quot;label&quot;: &quot;API Key&quot;, &quot;sensitive&quot;: true },\n    &quot;region&quot;: { &quot;label&quot;: &quot;Region&quot;, &quot;placeholder&quot;: &quot;us-east-1&quot; }\n  }\n}\n<\/code><\/pre>\n<h2>CLI<\/h2>\n<p>&#8220;`bash  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nopenclaw plugins list<br \/>\nopenclaw plugins info<br \/>\nopenclaw plugins install                  # \u5c06\u672c\u5730\u6587\u4ef6\/\u76ee\u5f55\u590d\u5236\u5230 ~\/.openclaw\/extensions\/<br \/>\nopenclaw plugins install .\/extensions\/voice-call # \u652f\u6301\u76f8\u5bf9\u8def\u5f84<br \/>\nopenclaw plugins install .\/plugin.tgz           # \u4ece\u672c\u5730 tarball \u5b89\u88c5<br \/>\nopenclaw plugins install .\/plugin.zip           # \u4ece\u672c\u5730 zip \u5b89\u88c5<br \/>\nopenclaw plugins install -l .\/extensions\/voice-call # link\uff08\u4e0d\u590d\u5236\uff09\uff0c\u7528\u4e8e\u5f00\u53d1<br \/>\nopenclaw plugins install @openclaw\/voice-call # \u4ece npm \u5b89\u88c5<br \/>\nopenclaw plugins install @openclaw\/voice-call &#8211;pin # \u5b58\u50a8\u7cbe\u786e\u89e3\u6790\u540e\u7684 name@version<br \/>\nopenclaw plugins update<br \/>\nopenclaw plugins update &#8211;all<br \/>\nopenclaw plugins enable<br \/>\nopenclaw plugins disable<br \/>\nopenclaw plugins doctor<\/p>\n<pre><code>\n`openclaw plugins list` \u4f1a\u5c06\u9876\u5c42\u683c\u5f0f\u663e\u793a\u4e3a `openclaw` \u6216 `bundle`\u3002\n\u8be6\u7ec6\u5217\u8868\/info \u8f93\u51fa\u8fd8\u4f1a\u663e\u793a bundle \u5b50\u7c7b\u578b\uff08`codex` \u6216 `claude`\uff09\u4ee5\u53ca\u5df2\u68c0\u6d4b\u5230\u7684 bundle \u80fd\u529b\u3002\n\n`plugins update` \u4ec5\u9002\u7528\u4e8e\u5728 `plugins.installs` \u4e0b\u8ddf\u8e2a\u7684 npm \u5b89\u88c5\u3002\n\u5982\u679c\u66f4\u65b0\u4e4b\u95f4\u5b58\u50a8\u7684\u5b8c\u6574\u6027\u5143\u6570\u636e\u53d1\u751f\u53d8\u5316\uff0cOpenClaw \u4f1a\u53d1\u51fa\u8b66\u544a\u5e76\u8981\u6c42\u786e\u8ba4\uff08\u4f7f\u7528\u5168\u5c40 `--yes` \u53ef\u7ed5\u8fc7\u63d0\u793a\uff09\u3002\n\n\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u6ce8\u518c\u81ea\u5df1\u7684\u9876\u5c42\u547d\u4ee4\uff08\u4f8b\u5982\uff1a`openclaw voicecall`\uff09\u3002\n\n## Plugin API\uff08\u6982\u89c8\uff09\n\n\u63d2\u4ef6\u5bfc\u51fa\u5f62\u5f0f\u53ef\u4ee5\u662f\uff1a\n\n* \u4e00\u4e2a\u51fd\u6570\uff1a`(api) =&gt; { ... }`\n* \u4e00\u4e2a\u5bf9\u8c61\uff1a`{ id, name, configSchema, register(api) { ... } }`\n\n`register(api)` \u662f\u63d2\u4ef6\u6302\u63a5\u884c\u4e3a\u7684\u5730\u65b9\u3002\u5e38\u89c1\u6ce8\u518c\u5305\u62ec\uff1a\n\n* `registerTool`\n* `registerHook`\n* `on(...)` \u7528\u4e8e\u7c7b\u578b\u5316\u751f\u547d\u5468\u671f hooks\n* `registerChannel`\n* `registerProvider`\n* `registerHttpRoute`\n* `registerCommand`\n* `registerCli`\n* `registerContextEngine`\n* `registerService`\n\n\u4e0a\u4e0b\u6587\u5f15\u64ce\u63d2\u4ef6\u8fd8\u53ef\u4ee5\u6ce8\u518c\u4e00\u4e2a\u7531\u8fd0\u884c\u65f6\u62e5\u6709\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\uff1a\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nexport default function (api) {\n  api.registerContextEngine(&quot;lossless-claw&quot;, () =&gt; ({\n    info: { id: &quot;lossless-claw&quot;, name: &quot;Lossless Claw&quot;, ownsCompaction: true },\n    async ingest() {\n      return { ingested: true };\n    },\n    async assemble({ messages }) {\n      return { messages, estimatedTokens: 0 };\n    },\n    async compact() {\n      return { ok: true, compacted: false };\n    },\n  }));\n}\n<\/code><\/pre>\n<p>\u5982\u679c\u4f60\u7684\u5f15\u64ce<strong>\u5e76\u4e0d\u62e5\u6709<\/strong>\u538b\u7f29\u7b97\u6cd5\uff0c\u4ecd\u7136\u8981\u5b9e\u73b0 <code>compact()<\/code>\uff0c\u5e76\u663e\u5f0f\u59d4\u6258\u7ed9\u8fd0\u884c\u65f6\uff1a<\/p>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nimport { delegateCompactionToRuntime } from &#8220;openclaw\/plugin-sdk&#8221;;<\/p>\n<p>export default function (api) {<br \/>\n  api.registerContextEngine(&#8220;my-memory-engine&#8221;, () =&gt; ({<br \/>\n    info: {<br \/>\n      id: &#8220;my-memory-engine&#8221;,<br \/>\n      name: &#8220;My Memory Engine&#8221;,<br \/>\n      ownsCompaction: false,<br \/>\n    },<br \/>\n    async ingest() {<br \/>\n      return { ingested: true };<br \/>\n    },<br \/>\n    async assemble({ messages }) {<br \/>\n      return { messages, estimatedTokens: 0 };<br \/>\n    },<br \/>\n    async compact(params) {<br \/>\n      return await delegateCompactionToRuntime(params);<br \/>\n    },<br \/>\n  }));<br \/>\n}<\/p>\n<pre><code>\n`ownsCompaction: false` \u4e0d\u4f1a\u81ea\u52a8\u56de\u9000\u5230 legacy \u538b\u7f29\u8def\u5f84\u3002\n\u53ea\u8981\u8be5\u5f15\u64ce\u5904\u4e8e\u6fc0\u6d3b\u72b6\u6001\uff0c\u5b83\u81ea\u5df1\u7684 `compact()` \u4ecd\u7136\u4f1a\u5904\u7406 `\/compact`\n\u548c\u6ea2\u51fa\u6062\u590d\u3002\n\n\u7136\u540e\u5728\u914d\u7f6e\u4e2d\u542f\u7528\u5b83\uff1a\n\n```json5  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\n{\n  plugins: {\n    slots: {\n      contextEngine: &quot;lossless-claw&quot;,\n    },\n  },\n}\n<\/code><\/pre>\n<h2>Plugin hooks<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u5728\u8fd0\u884c\u65f6\u6ce8\u518c hooks\u3002\u8fd9\u8ba9\u63d2\u4ef6\u80fd\u591f\u6253\u5305\u4e8b\u4ef6\u9a71\u52a8\u81ea\u52a8\u5316\uff0c\u800c\u65e0\u9700\u5355\u72ec\u5b89\u88c5 hook pack\u3002<\/p>\n<h3>\u793a\u4f8b<\/h3>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nexport default function register(api) {<br \/>\n  api.registerHook(<br \/>\n    &#8220;command:new&#8221;,<br \/>\n    async () =&gt; {<br \/>\n      \/\/ Hook \u903b\u8f91\u5199\u5728\u8fd9\u91cc\u3002<br \/>\n    },<br \/>\n    {<br \/>\n      name: &#8220;my-plugin.command-new&#8221;,<br \/>\n      description: &#8220;\u5f53 \/new \u88ab\u8c03\u7528\u65f6\u8fd0\u884c&#8221;,<br \/>\n    },<br \/>\n  );<br \/>\n}<\/p>\n<pre><code>\n\u8bf4\u660e\uff1a\n\n* \u901a\u8fc7 `api.registerHook(...)` \u663e\u5f0f\u6ce8\u518c hooks\u3002\n* Hook \u8d44\u683c\u89c4\u5219\u4ecd\u7136\u9002\u7528\uff08OS\/bins\/env\/config \u8981\u6c42\uff09\u3002\n* \u63d2\u4ef6\u7ba1\u7406\u7684 hooks \u4f1a\u5728 `openclaw hooks list` \u4e2d\u663e\u793a\u4e3a `plugin:&lt;id&gt;`\u3002\n* \u4f60\u4e0d\u80fd\u901a\u8fc7 `openclaw hooks` \u542f\u7528\/\u7981\u7528\u63d2\u4ef6\u7ba1\u7406\u7684 hooks\uff1b\u5e94\u6539\u4e3a\u542f\u7528\/\u7981\u7528\u63d2\u4ef6\u672c\u8eab\u3002\n\n### \u667a\u80fd\u4f53\u751f\u547d\u5468\u671f hooks\uff08`api.on`\uff09\n\n\u5bf9\u4e8e\u7c7b\u578b\u5316\u8fd0\u884c\u65f6\u751f\u547d\u5468\u671f hooks\uff0c\u8bf7\u4f7f\u7528 `api.on(...)`\uff1a\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nexport default function register(api) {\n  api.on(\n    &quot;before_prompt_build&quot;,\n    (event, ctx) =&gt; {\n      return {\n        prependSystemContext: &quot;Follow company style guide.&quot;,\n      };\n    },\n    { priority: 10 },\n  );\n}\n<\/code><\/pre>\n<p>\u7528\u4e8e\u63d0\u793a\u8bcd\u6784\u5efa\u7684\u91cd\u8981 hooks\uff1a<\/p>\n<ul>\n<li><code>before_model_resolve<\/code>\uff1a\u5728\u52a0\u8f7d\u4f1a\u8bdd\u4e4b\u524d\u8fd0\u884c\uff08<code>messages<\/code> \u4e0d\u53ef\u7528\uff09\u3002\u7528\u5b83\u6765\u786e\u5b9a\u6027\u5730\u8986\u76d6 <code>modelOverride<\/code> \u6216 <code>providerOverride<\/code>\u3002<\/li>\n<li><code>before_prompt_build<\/code>\uff1a\u5728\u52a0\u8f7d\u4f1a\u8bdd\u4e4b\u540e\u8fd0\u884c\uff08<code>messages<\/code> \u53ef\u7528\uff09\u3002\u7528\u5b83\u6765\u5851\u9020\u63d0\u793a\u8bcd\u8f93\u5165\u3002<\/li>\n<li><code>before_agent_start<\/code>\uff1a\u65e7\u7248\u517c\u5bb9 hook\u3002\u4f18\u5148\u4f7f\u7528\u4e0a\u9762\u4e24\u4e2a\u66f4\u660e\u786e\u7684 hooks\u3002<\/li>\n<\/ul>\n<p>\u6838\u5fc3\u5f3a\u5236\u6267\u884c\u7684 hook \u7b56\u7565\uff1a<\/p>\n<ul>\n<li>\u64cd\u4f5c\u5458\u53ef\u4ee5\u901a\u8fc7 <code>plugins.entries.&lt;id&gt;.hooks.allowPromptInjection: false<\/code> \u6309\u63d2\u4ef6\u7981\u7528\u63d0\u793a\u8bcd\u53d8\u66f4 hooks\u3002<\/li>\n<li>\u7981\u7528\u540e\uff0cOpenClaw \u4f1a\u963b\u6b62 <code>before_prompt_build<\/code>\uff0c\u5e76\u5ffd\u7565\u65e7\u7248 <code>before_agent_start<\/code> \u8fd4\u56de\u7684\u63d0\u793a\u8bcd\u53d8\u66f4\u5b57\u6bb5\uff0c\u540c\u65f6\u4fdd\u7559\u65e7\u7248 <code>modelOverride<\/code> \u548c <code>providerOverride<\/code>\u3002<\/li>\n<\/ul>\n<p><code>before_prompt_build<\/code> \u7ed3\u679c\u5b57\u6bb5\uff1a<\/p>\n<ul>\n<li><code>prependContext<\/code>\uff1a\u4e3a\u672c\u6b21\u8fd0\u884c\u5728\u7528\u6237\u63d0\u793a\u8bcd\u524d\u63d2\u5165\u6587\u672c\u3002\u6700\u9002\u5408\u6309\u8f6e\u6b21\u53d8\u5316\u6216\u52a8\u6001\u5185\u5bb9\u3002<\/li>\n<li><code>systemPrompt<\/code>\uff1a\u5b8c\u6574\u7684\u7cfb\u7edf\u63d0\u793a\u8bcd\u8986\u76d6\u3002<\/li>\n<li><code>prependSystemContext<\/code>\uff1a\u5728\u5f53\u524d\u7cfb\u7edf\u63d0\u793a\u8bcd\u524d\u63d2\u5165\u6587\u672c\u3002<\/li>\n<li><code>appendSystemContext<\/code>\uff1a\u5728\u5f53\u524d\u7cfb\u7edf\u63d0\u793a\u8bcd\u540e\u8ffd\u52a0\u6587\u672c\u3002<\/li>\n<\/ul>\n<p>\u5d4c\u5165\u5f0f\u8fd0\u884c\u65f6\u4e2d\u7684\u63d0\u793a\u8bcd\u6784\u5efa\u987a\u5e8f\uff1a<\/p>\n<ol>\n<li>\u5c06 <code>prependContext<\/code> \u5e94\u7528\u5230\u7528\u6237\u63d0\u793a\u8bcd\u3002<\/li>\n<li>\u5982\u679c\u63d0\u4f9b\u4e86 <code>systemPrompt<\/code>\uff0c\u5219\u5e94\u7528\u5176\u8986\u76d6\u3002<\/li>\n<li>\u5e94\u7528 <code>prependSystemContext + \u5f53\u524d\u7cfb\u7edf\u63d0\u793a\u8bcd + appendSystemContext<\/code>\u3002<\/li>\n<\/ol>\n<p>\u5408\u5e76\u4e0e\u4f18\u5148\u7ea7\u8bf4\u660e\uff1a<\/p>\n<ul>\n<li>Hook \u5904\u7406\u5668\u6309\u4f18\u5148\u7ea7\u8fd0\u884c\uff08\u9ad8\u8005\u4f18\u5148\uff09\u3002<\/li>\n<li>\u5bf9\u4e8e\u5408\u5e76\u578b\u4e0a\u4e0b\u6587\u5b57\u6bb5\uff0c\u503c\u4f1a\u6309\u6267\u884c\u987a\u5e8f\u62fc\u63a5\u3002<\/li>\n<li><code>before_prompt_build<\/code> \u7684\u503c\u4f1a\u5728\u65e7\u7248 <code>before_agent_start<\/code> \u540e\u5907\u503c\u4e4b\u524d\u5e94\u7528\u3002<\/li>\n<\/ul>\n<p>\u8fc1\u79fb\u6307\u5bfc\uff1a<\/p>\n<ul>\n<li>\u5c06\u9759\u6001\u6307\u5bfc\u4ece <code>prependContext<\/code> \u79fb\u5230 <code>prependSystemContext<\/code>\uff08\u6216 <code>appendSystemContext<\/code>\uff09\uff0c\u8fd9\u6837 provider \u5c31\u53ef\u4ee5\u7f13\u5b58\u7a33\u5b9a\u7684\u7cfb\u7edf\u524d\u7f00\u5185\u5bb9\u3002<\/li>\n<li>\u5c06 <code>prependContext<\/code> \u4fdd\u7559\u7ed9\u6bcf\u8f6e\u52a8\u6001\u4e0a\u4e0b\u6587\uff0c\u8fd9\u7c7b\u5185\u5bb9\u5e94\u7ee7\u7eed\u4e0e\u7528\u6237\u6d88\u606f\u7ed1\u5b9a\u3002<\/li>\n<\/ul>\n<h2>Provider \u63d2\u4ef6\uff08\u6a21\u578b\u8eab\u4efd\u9a8c\u8bc1\uff09<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u6ce8\u518c <strong>\u6a21\u578b providers<\/strong>\uff0c\u4ece\u800c\u8ba9\u7528\u6237\u80fd\u591f\u5728 OpenClaw \u5185\u5b8c\u6210 OAuth \u6216 API \u5bc6\u94a5\u8bbe\u7f6e\u3001\u5728\u65b0\u624b\u5f15\u5bfc\/\u6a21\u578b\u9009\u62e9\u5668\u4e2d\u663e\u793a provider \u8bbe\u7f6e\uff0c\u5e76\u53c2\u4e0e\u9690\u5f0f provider \u53d1\u73b0\u3002<\/p>\n<p>Provider \u63d2\u4ef6\u73b0\u5728\u662f\u6a21\u578b provider \u8bbe\u7f6e\u7684\u6a21\u5757\u5316\u6269\u5c55\u63a5\u7f1d\u3002\u5b83\u4eec\u4e0d\u518d\u53ea\u662f\u201cOAuth \u8f85\u52a9\u5de5\u5177\u201d\u3002<\/p>\n<h3>Provider \u63d2\u4ef6\u751f\u547d\u5468\u671f<\/h3>\n<p>\u4e00\u4e2a provider \u63d2\u4ef6\u53ef\u4ee5\u53c2\u4e0e\u4e94\u4e2a\u4e0d\u540c\u9636\u6bb5\uff1a<\/p>\n<ol>\n<li><strong>\u8eab\u4efd\u9a8c\u8bc1<\/strong><br \/>\n   <code>auth[].run(ctx)<\/code> \u6267\u884c OAuth\u3001API \u5bc6\u94a5\u91c7\u96c6\u3001\u8bbe\u5907\u7801\u6216\u81ea\u5b9a\u4e49\u8bbe\u7f6e\uff0c\u5e76\u8fd4\u56de auth profile \u4ee5\u53ca\u53ef\u9009\u7684\u914d\u7f6e\u8865\u4e01\u3002<\/li>\n<li><strong>\u975e\u4ea4\u4e92\u5f0f\u8bbe\u7f6e<\/strong><br \/>\n   <code>auth[].runNonInteractive(ctx)<\/code> \u5904\u7406 <code>openclaw onboard --non-interactive<\/code>\uff0c\u4e14\u4e0d\u8fdb\u884c\u63d0\u793a\u3002\u5f53 provider \u9700\u8981\u8d85\u51fa\u5185\u7f6e\u7b80\u5355 API \u5bc6\u94a5\u8def\u5f84\u4e4b\u5916\u7684\u81ea\u5b9a\u4e49\u65e0\u5934\u8bbe\u7f6e\u65f6\uff0c\u8bf7\u4f7f\u7528\u5b83\u3002<\/li>\n<li><strong>\u5411\u5bfc\u96c6\u6210<\/strong><br \/>\n   <code>wizard.setup<\/code> \u4f1a\u5411 <code>openclaw onboard<\/code> \u6dfb\u52a0\u4e00\u4e2a\u6761\u76ee\u3002<br \/>\n   <code>wizard.modelPicker<\/code> \u4f1a\u5411\u6a21\u578b\u9009\u62e9\u5668\u6dfb\u52a0\u4e00\u4e2a setup \u6761\u76ee\u3002<\/li>\n<li><strong>\u9690\u5f0f\u53d1\u73b0<\/strong><br \/>\n   <code>discovery.run(ctx)<\/code> \u53ef\u4ee5\u5728\u6a21\u578b\u89e3\u6790\/\u5217\u51fa\u671f\u95f4\u81ea\u52a8\u8d21\u732e provider \u914d\u7f6e\u3002<\/li>\n<li><strong>\u9009\u62e9\u540e\u8ddf\u8fdb<\/strong><br \/>\n   <code>onModelSelected(ctx)<\/code> \u4f1a\u5728\u6a21\u578b\u88ab\u9009\u4e2d\u540e\u8fd0\u884c\u3002\u53ef\u7528\u4e8e provider \u7279\u5b9a\u7684\u540e\u7eed\u5de5\u4f5c\uff0c\u4f8b\u5982\u4e0b\u8f7d\u672c\u5730\u6a21\u578b\u3002<\/li>\n<\/ol>\n<p>\u8fd9\u662f\u63a8\u8350\u7684\u62c6\u5206\u65b9\u5f0f\uff0c\u56e0\u4e3a\u8fd9\u4e9b\u9636\u6bb5\u5177\u6709\u4e0d\u540c\u7684\u751f\u547d\u5468\u671f\u8981\u6c42\uff1a<\/p>\n<ul>\n<li>auth \u662f\u4ea4\u4e92\u5f0f\u7684\uff0c\u5e76\u4f1a\u5199\u5165\u51ed\u636e\/\u914d\u7f6e<\/li>\n<li>\u975e\u4ea4\u4e92\u5f0f\u8bbe\u7f6e\u7531 flag\/env \u9a71\u52a8\uff0c\u4e14\u4e0d\u80fd\u63d0\u793a<\/li>\n<li>\u5411\u5bfc\u5143\u6570\u636e\u662f\u9759\u6001\u4e14\u9762\u5411 UI \u7684<\/li>\n<li>discovery \u5e94\u5b89\u5168\u3001\u5feb\u901f\u4e14\u80fd\u5bb9\u5fcd\u5931\u8d25<\/li>\n<li>\u9009\u62e9\u540e hooks \u662f\u4e0e\u6240\u9009\u6a21\u578b\u7ed1\u5b9a\u7684\u526f\u4f5c\u7528<\/li>\n<\/ul>\n<h3>Provider \u8eab\u4efd\u9a8c\u8bc1\u5951\u7ea6<\/h3>\n<p><code>auth[].run(ctx)<\/code> \u8fd4\u56de\uff1a<\/p>\n<ul>\n<li><code>profiles<\/code>\uff1a\u8981\u5199\u5165\u7684 auth profile<\/li>\n<li><code>configPatch<\/code>\uff1a\u53ef\u9009\u7684 <code>openclaw.json<\/code> \u53d8\u66f4<\/li>\n<li><code>defaultModel<\/code>\uff1a\u53ef\u9009\u7684 <code>provider\/model<\/code> \u5f15\u7528<\/li>\n<li><code>notes<\/code>\uff1a\u53ef\u9009\u7684\u9762\u5411\u7528\u6237\u5907\u6ce8<\/li>\n<\/ul>\n<p>\u7136\u540e\u6838\u5fc3\u4f1a\uff1a<\/p>\n<ol>\n<li>\u5199\u5165\u8fd4\u56de\u7684 auth profile<\/li>\n<li>\u5e94\u7528 auth-profile \u914d\u7f6e\u63a5\u7ebf<\/li>\n<li>\u5408\u5e76\u914d\u7f6e\u8865\u4e01<\/li>\n<li>\u53ef\u9009\u5730\u5e94\u7528\u9ed8\u8ba4\u6a21\u578b<\/li>\n<li>\u5728\u9002\u5f53\u65f6\u8fd0\u884c provider \u7684 <code>onModelSelected<\/code> hook<\/li>\n<\/ol>\n<p>\u8fd9\u610f\u5473\u7740 provider \u63d2\u4ef6\u62e5\u6709 provider \u7279\u5b9a\u7684\u8bbe\u7f6e\u903b\u8f91\uff0c\u800c\u6838\u5fc3\u62e5\u6709\u901a\u7528\u7684\u6301\u4e45\u5316\u548c\u914d\u7f6e\u5408\u5e76\u8def\u5f84\u3002<\/p>\n<h3>Provider \u975e\u4ea4\u4e92\u5f0f\u5951\u7ea6<\/h3>\n<p><code>auth[].runNonInteractive(ctx)<\/code> \u662f\u53ef\u9009\u7684\u3002\u5f53 provider \u9700\u8981\u65e0\u6cd5\u901a\u8fc7\u5185\u7f6e\u901a\u7528 API \u5bc6\u94a5\u6d41\u8868\u8fbe\u7684\u65e0\u5934\u8bbe\u7f6e\u65f6\uff0c\u8bf7\u5b9e\u73b0\u5b83\u3002<\/p>\n<p>\u975e\u4ea4\u4e92\u5f0f\u4e0a\u4e0b\u6587\u5305\u62ec\uff1a<\/p>\n<ul>\n<li>\u5f53\u524d\u914d\u7f6e\u548c\u57fa\u7840\u914d\u7f6e<\/li>\n<li>\u89e3\u6790\u540e\u7684 onboarding CLI \u9009\u9879<\/li>\n<li>\u8fd0\u884c\u65f6\u65e5\u5fd7\/\u9519\u8bef\u8f85\u52a9\u5de5\u5177<\/li>\n<li>\u667a\u80fd\u4f53\/\u5de5\u4f5c\u533a\u76ee\u5f55\uff0c\u4ee5\u4fbf provider \u5c06 auth \u6301\u4e45\u5316\u5230\u4e0e\u5176\u4f59 onboarding \u76f8\u540c\u7684\u4f5c\u7528\u57df\u5b58\u50a8\u4e2d<\/li>\n<li><code>resolveApiKey(...)<\/code>\uff1a\u5728\u9075\u5b88 <code>--secret-input-mode<\/code> \u7684\u540c\u65f6\uff0c\u4ece flags\u3001\u73af\u5883\u53d8\u91cf\u6216\u73b0\u6709 auth profile \u4e2d\u8bfb\u53d6 provider \u5bc6\u94a5<\/li>\n<li><code>toApiKeyCredential(...)<\/code>\uff1a\u5c06\u89e3\u6790\u540e\u7684\u5bc6\u94a5\u8f6c\u6362\u4e3a auth-profile \u51ed\u636e\uff0c\u5e76\u4f7f\u7528\u6b63\u786e\u7684\u660e\u6587\u6216 secret-ref \u5b58\u50a8\u65b9\u5f0f<\/li>\n<\/ul>\n<p>\u9002\u5408\u4f7f\u7528\u6b64\u8868\u9762\u7684 provider \u5305\u62ec\uff1a<\/p>\n<ul>\n<li>\u9700\u8981 <code>--custom-base-url<\/code> + <code>--custom-model-id<\/code> \u7684\u81ea\u6258\u7ba1 OpenAI \u517c\u5bb9\u8fd0\u884c\u65f6<\/li>\n<li>\u9700\u8981 provider \u7279\u5b9a\u975e\u4ea4\u4e92\u5f0f\u9a8c\u8bc1\u6216\u914d\u7f6e\u5408\u6210\u7684\u573a\u666f<\/li>\n<\/ul>\n<p>\u4e0d\u8981\u4ece <code>runNonInteractive<\/code> \u4e2d\u53d1\u51fa\u63d0\u793a\u3002\u5bf9\u4e8e\u7f3a\u5931\u8f93\u5165\uff0c\u8bf7\u6539\u4e3a\u8fd4\u56de\u53ef\u64cd\u4f5c\u7684\u9519\u8bef\u3002<\/p>\n<h3>Provider \u5411\u5bfc\u5143\u6570\u636e<\/h3>\n<p><code>wizard.setup<\/code> \u63a7\u5236 provider \u5728\u5206\u7ec4\u65b0\u624b\u5f15\u5bfc\u4e2d\u7684\u663e\u793a\u65b9\u5f0f\uff1a<\/p>\n<ul>\n<li><code>choiceId<\/code>\uff1aauth-choice \u503c<\/li>\n<li><code>choiceLabel<\/code>\uff1a\u9009\u9879\u6807\u7b7e<\/li>\n<li><code>choiceHint<\/code>\uff1a\u7b80\u77ed\u63d0\u793a<\/li>\n<li><code>groupId<\/code>\uff1a\u5206\u7ec4\u6876 id<\/li>\n<li><code>groupLabel<\/code>\uff1a\u5206\u7ec4\u6807\u7b7e<\/li>\n<li><code>groupHint<\/code>\uff1a\u5206\u7ec4\u63d0\u793a<\/li>\n<li><code>methodId<\/code>\uff1a\u8981\u8fd0\u884c\u7684\u8eab\u4efd\u9a8c\u8bc1\u65b9\u6cd5<\/li>\n<\/ul>\n<p><code>wizard.modelPicker<\/code> \u63a7\u5236 provider \u5728\u6a21\u578b\u9009\u62e9\u4e2d\u4f5c\u4e3a\u201c\u73b0\u5728\u8bbe\u7f6e\u5b83\u201d\u6761\u76ee\u7684\u663e\u793a\u65b9\u5f0f\uff1a<\/p>\n<ul>\n<li><code>label<\/code><\/li>\n<li><code>hint<\/code><\/li>\n<li><code>methodId<\/code><\/li>\n<\/ul>\n<p>\u5f53 provider \u5177\u6709\u591a\u79cd\u8eab\u4efd\u9a8c\u8bc1\u65b9\u6cd5\u65f6\uff0c\u5411\u5bfc\u53ef\u4ee5\u663e\u5f0f\u6307\u5411\u5176\u4e2d\u4e00\u79cd\u65b9\u6cd5\uff0c\u4e5f\u53ef\u4ee5\u8ba9 OpenClaw \u4e3a\u6bcf\u79cd\u65b9\u6cd5\u81ea\u52a8\u751f\u6210\u9009\u62e9\u9879\u3002<\/p>\n<p>\u5728\u63d2\u4ef6\u6ce8\u518c\u65f6\uff0cOpenClaw \u4f1a\u9a8c\u8bc1 provider \u5411\u5bfc\u5143\u6570\u636e\uff1a<\/p>\n<ul>\n<li>\u91cd\u590d\u6216\u7a7a\u767d\u7684 auth-method id \u4f1a\u88ab\u62d2\u7edd<\/li>\n<li>\u5f53 provider \u6ca1\u6709\u8eab\u4efd\u9a8c\u8bc1\u65b9\u6cd5\u65f6\uff0c\u5411\u5bfc\u5143\u6570\u636e\u4f1a\u88ab\u5ffd\u7565<\/li>\n<li>\u65e0\u6548\u7684 <code>methodId<\/code> \u7ed1\u5b9a\u4f1a\u964d\u7ea7\u4e3a\u8b66\u544a\uff0c\u5e76\u56de\u9000\u5230 provider \u5269\u4f59\u7684\u8eab\u4efd\u9a8c\u8bc1\u65b9\u6cd5<\/li>\n<\/ul>\n<h3>Provider discovery \u5951\u7ea6<\/h3>\n<p><code>discovery.run(ctx)<\/code> \u8fd4\u56de\u4ee5\u4e0b\u4e4b\u4e00\uff1a<\/p>\n<ul>\n<li><code>{ provider }<\/code><\/li>\n<li><code>{ providers }<\/code><\/li>\n<li><code>null<\/code><\/li>\n<\/ul>\n<p>\u5f53\u63d2\u4ef6\u62e5\u6709\u4e00\u4e2a provider id \u65f6\uff0c\u8bf7\u4f7f\u7528 <code>{ provider }<\/code> \u8fd9\u4e00\u5e38\u89c1\u60c5\u51b5\u3002<br \/>\n\u5f53\u63d2\u4ef6\u53d1\u73b0\u591a\u4e2a provider \u6761\u76ee\u65f6\uff0c\u8bf7\u4f7f\u7528 <code>{ providers }<\/code>\u3002<\/p>\n<p>Discovery \u4e0a\u4e0b\u6587\u5305\u62ec\uff1a<\/p>\n<ul>\n<li>\u5f53\u524d\u914d\u7f6e<\/li>\n<li>\u667a\u80fd\u4f53\/\u5de5\u4f5c\u533a\u76ee\u5f55<\/li>\n<li>\u8fdb\u7a0b\u73af\u5883\u53d8\u91cf<\/li>\n<li>\u4e00\u4e2a\u7528\u4e8e\u89e3\u6790 provider API \u5bc6\u94a5\u4ee5\u53ca\u53d1\u73b0\u5b89\u5168 API \u5bc6\u94a5\u503c\u7684\u8f85\u52a9\u5de5\u5177<\/li>\n<\/ul>\n<p>Discovery \u5e94\u8be5\uff1a<\/p>\n<ul>\n<li>\u5feb\u901f<\/li>\n<li>\u5c3d\u529b\u800c\u4e3a<\/li>\n<li>\u5728\u5931\u8d25\u65f6\u53ef\u5b89\u5168\u8df3\u8fc7<\/li>\n<li>\u8c28\u614e\u5904\u7406\u526f\u4f5c\u7528<\/li>\n<\/ul>\n<p>\u5b83\u4e0d\u5e94\u4f9d\u8d56\u63d0\u793a\u6216\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u8bbe\u7f6e\u3002<\/p>\n<h3>\u53d1\u73b0\u987a\u5e8f<\/h3>\n<p>Provider discovery \u6309\u6709\u5e8f\u9636\u6bb5\u8fd0\u884c\uff1a<\/p>\n<ul>\n<li><code>simple<\/code><\/li>\n<li><code>profile<\/code><\/li>\n<li><code>paired<\/code><\/li>\n<li><code>late<\/code><\/li>\n<\/ul>\n<p>\u4f7f\u7528\u5efa\u8bae\uff1a<\/p>\n<ul>\n<li><code>simple<\/code>\uff1a\u7528\u4e8e\u5ec9\u4ef7\u7684\u7eaf\u73af\u5883\u53d8\u91cf\u53d1\u73b0<\/li>\n<li><code>profile<\/code>\uff1a\u5f53\u53d1\u73b0\u4f9d\u8d56 auth profile \u65f6\u4f7f\u7528<\/li>\n<li><code>paired<\/code>\uff1a\u7528\u4e8e\u9700\u8981\u4e0e\u53e6\u4e00\u6b65\u53d1\u73b0\u534f\u4f5c\u7684 provider<\/li>\n<li><code>late<\/code>\uff1a\u7528\u4e8e\u6602\u8d35\u6216\u672c\u5730\u7f51\u7edc\u63a2\u6d4b<\/li>\n<\/ul>\n<p>\u5927\u591a\u6570\u81ea\u6258\u7ba1 provider \u5e94\u4f7f\u7528 <code>late<\/code>\u3002<\/p>\n<h3>\u826f\u597d\u7684 provider-plugin \u8fb9\u754c<\/h3>\n<p>\u9002\u5408\u505a\u6210 provider \u63d2\u4ef6\u7684\u60c5\u51b5\uff1a<\/p>\n<ul>\n<li>\u5177\u6709\u81ea\u5b9a\u4e49\u8bbe\u7f6e\u6d41\u7a0b\u7684\u672c\u5730\/\u81ea\u6258\u7ba1 providers<\/li>\n<li>provider \u7279\u5b9a\u7684 OAuth\/\u8bbe\u5907\u7801\u767b\u5f55<\/li>\n<li>\u5bf9\u672c\u5730\u6a21\u578b\u670d\u52a1\u5668\u7684\u9690\u5f0f\u53d1\u73b0<\/li>\n<li>\u9009\u62e9\u540e\u7684\u526f\u4f5c\u7528\uff0c\u4f8b\u5982\u62c9\u53d6\u6a21\u578b<\/li>\n<\/ul>\n<p>\u4e0d\u592a\u6709\u8bf4\u670d\u529b\u7684\u60c5\u51b5\uff1a<\/p>\n<ul>\n<li>\u4ec5\u5728 env var\u3001base URL \u548c\u4e00\u4e2a\u9ed8\u8ba4\u6a21\u578b\u4e0a\u4e0d\u540c\u7684\u7b80\u5355 API \u5bc6\u94a5\u578b provider<\/li>\n<\/ul>\n<p>\u8fd9\u4e9b\u4ecd\u7136\u53ef\u4ee5\u505a\u6210\u63d2\u4ef6\uff0c\u4f46\u6700\u5927\u7684\u6a21\u5757\u5316\u6536\u76ca\u6765\u81ea\u5148\u62bd\u79bb\u90a3\u4e9b\u884c\u4e3a\u4e30\u5bcc\u7684 providers\u3002<\/p>\n<p>\u901a\u8fc7 <code>api.registerProvider(...)<\/code> \u6ce8\u518c provider\u3002\u6bcf\u4e2a provider \u66b4\u9732\u4e00\u4e2a\u6216\u591a\u4e2a\u8eab\u4efd\u9a8c\u8bc1\u65b9\u6cd5\uff08OAuth\u3001API key\u3001device code \u7b49\uff09\u3002\u8fd9\u4e9b\u65b9\u6cd5\u53ef\u4ee5\u9a71\u52a8\uff1a<\/p>\n<ul>\n<li><code>openclaw models auth login --provider &lt;id&gt; [--method &lt;id&gt;]<\/code><\/li>\n<li><code>openclaw onboard<\/code><\/li>\n<li>\u6a21\u578b\u9009\u62e9\u5668\u4e2d\u7684\u201c\u81ea\u5b9a\u4e49 provider\u201d\u8bbe\u7f6e\u6761\u76ee<\/li>\n<li>\u6a21\u578b\u89e3\u6790\/\u5217\u51fa\u671f\u95f4\u7684\u9690\u5f0f provider \u53d1\u73b0<\/li>\n<\/ul>\n<p>\u793a\u4f8b\uff1a<\/p>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\napi.registerProvider({<br \/>\n  id: &#8220;acme&#8221;,<br \/>\n  label: &#8220;AcmeAI&#8221;,<br \/>\n  auth: [<br \/>\n    {<br \/>\n      id: &#8220;oauth&#8221;,<br \/>\n      label: &#8220;OAuth&#8221;,<br \/>\n      kind: &#8220;oauth&#8221;,<br \/>\n      run: async (ctx) =&gt; {<br \/>\n        \/\/ \u8fd0\u884c OAuth \u6d41\u5e76\u8fd4\u56de auth profile\u3002<br \/>\n        return {<br \/>\n          profiles: [<br \/>\n            {<br \/>\n              profileId: &#8220;acme:default&#8221;,<br \/>\n              credential: {<br \/>\n                type: &#8220;oauth&#8221;,<br \/>\n                provider: &#8220;acme&#8221;,<br \/>\n                access: &#8220;&#8230;&#8221;,<br \/>\n                refresh: &#8220;&#8230;&#8221;,<br \/>\n                expires: Date.now() + 3600 * 1000,<br \/>\n              },<br \/>\n            },<br \/>\n          ],<br \/>\n          defaultModel: &#8220;acme\/opus-1&#8221;,<br \/>\n        };<br \/>\n      },<br \/>\n    },<br \/>\n  ],<br \/>\n  wizard: {<br \/>\n    setup: {<br \/>\n      choiceId: &#8220;acme&#8221;,<br \/>\n      choiceLabel: &#8220;AcmeAI&#8221;,<br \/>\n      groupId: &#8220;acme&#8221;,<br \/>\n      groupLabel: &#8220;AcmeAI&#8221;,<br \/>\n      methodId: &#8220;oauth&#8221;,<br \/>\n    },<br \/>\n    modelPicker: {<br \/>\n      label: &#8220;AcmeAI\uff08\u81ea\u5b9a\u4e49\uff09&#8221;,<br \/>\n      hint: &#8220;\u8fde\u63a5\u4e00\u4e2a\u81ea\u6258\u7ba1 AcmeAI \u7aef\u70b9&#8221;,<br \/>\n      methodId: &#8220;oauth&#8221;,<br \/>\n    },<br \/>\n  },<br \/>\n  discovery: {<br \/>\n    order: &#8220;late&#8221;,<br \/>\n    run: async () =&gt; ({<br \/>\n      provider: {<br \/>\n        baseUrl: &#8220;https:\/\/acme.example\/v1&#8221;,<br \/>\n        api: &#8220;openai-completions&#8221;,<br \/>\n        apiKey: &#8220;${ACME_API_KEY}&#8221;,<br \/>\n        models: [],<br \/>\n      },<br \/>\n    }),<br \/>\n  },<br \/>\n});<\/p>\n<pre><code>\n\u8bf4\u660e\uff1a\n\n* `run` \u4f1a\u63a5\u6536\u4e00\u4e2a `ProviderAuthContext`\uff0c\u5176\u4e2d\u5305\u542b `prompter`\u3001`runtime`\u3001\n  `openUrl`\u3001`oauth.createVpsAwareHandlers`\u3001`secretInputMode` \u548c\n  `allowSecretRefPrompt` \u8f85\u52a9\u5de5\u5177\/\u72b6\u6001\u3002\u65b0\u624b\u5f15\u5bfc\/\u914d\u7f6e\u6d41\u7a0b\u53ef\u4ee5\u7528\u5b83\u4eec\u6765\u9075\u5b88 `--secret-input-mode`\uff0c\u6216\u63d0\u4f9b env\/file\/exec secret-ref \u91c7\u96c6\uff0c\u800c `openclaw models auth` \u4f1a\u4fdd\u6301\u66f4\u4e25\u683c\u7684\u63d0\u793a\u8868\u9762\u3002\n* `runNonInteractive` \u4f1a\u63a5\u6536\u4e00\u4e2a `ProviderAuthMethodNonInteractiveContext`\uff0c\n  \u5176\u4e2d\u5305\u542b `opts`\u3001`agentDir`\u3001`resolveApiKey` \u548c `toApiKeyCredential` \u8f85\u52a9\u5de5\u5177\uff0c\u7528\u4e8e\u65e0\u5934 onboarding\u3002\n* \u5f53\u4f60\u9700\u8981\u6dfb\u52a0\u9ed8\u8ba4\u6a21\u578b\u6216 provider \u914d\u7f6e\u65f6\uff0c\u8bf7\u8fd4\u56de `configPatch`\u3002\n* \u8fd4\u56de `defaultModel`\uff0c\u8fd9\u6837 `--set-default` \u5c31\u80fd\u66f4\u65b0\u667a\u80fd\u4f53\u9ed8\u8ba4\u503c\u3002\n* `wizard.setup` \u4f1a\u5411 `openclaw onboard` \u6dfb\u52a0\u4e00\u4e2a provider \u9009\u9879\u3002\n* `wizard.modelPicker` \u4f1a\u5411\u6a21\u578b\u9009\u62e9\u5668\u6dfb\u52a0\u4e00\u4e2a\u201c\u8bbe\u7f6e\u6b64 provider\u201d\u6761\u76ee\u3002\n* `discovery.run` \u5bf9\u4e8e\u63d2\u4ef6\u81ea\u6709 provider id \u8fd4\u56de `{ provider }`\uff0c\u5bf9\u4e8e\u591a provider \u53d1\u73b0\u8fd4\u56de `{ providers }`\u3002\n* `discovery.order` \u63a7\u5236\u8be5 provider \u76f8\u5bf9\u4e8e\u5185\u7f6e\u53d1\u73b0\u9636\u6bb5\u7684\u8fd0\u884c\u65f6\u673a\uff1a`simple`\u3001`profile`\u3001`paired` \u6216 `late`\u3002\n* `onModelSelected` \u662f\u9009\u62e9\u540e\u7684 hook\uff0c\u7528\u4e8e provider \u7279\u5b9a\u7684\u540e\u7eed\u5de5\u4f5c\uff0c\u4f8b\u5982\u62c9\u53d6\u672c\u5730\u6a21\u578b\u3002\n\n### \u6ce8\u518c\u4e00\u4e2a\u6d88\u606f\u6e20\u9053\n\n\u63d2\u4ef6\u53ef\u4ee5\u6ce8\u518c **\u6e20\u9053\u63d2\u4ef6**\uff0c\u5176\u884c\u4e3a\u7c7b\u4f3c\u5185\u7f6e\u6e20\u9053\n\uff08WhatsApp\u3001Telegram \u7b49\uff09\u3002\u6e20\u9053\u914d\u7f6e\u4f4d\u4e8e `channels.&lt;id&gt;` \u4e0b\uff0c\u5e76\u7531\u4f60\u7684\u6e20\u9053\u63d2\u4ef6\u4ee3\u7801\u8fdb\u884c\u9a8c\u8bc1\u3002\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nconst myChannel = {\n  id: &quot;acmechat&quot;,\n  meta: {\n    id: &quot;acmechat&quot;,\n    label: &quot;AcmeChat&quot;,\n    selectionLabel: &quot;AcmeChat (API)&quot;,\n    docsPath: &quot;\/channels\/acmechat&quot;,\n    blurb: &quot;\u6f14\u793a\u6e20\u9053\u63d2\u4ef6\u3002&quot;,\n    aliases: [&quot;acme&quot;],\n  },\n  capabilities: { chatTypes: [&quot;direct&quot;] },\n  config: {\n    listAccountIds: (cfg) =&gt; Object.keys(cfg.channels?.acmechat?.accounts ?? {}),\n    resolveAccount: (cfg, accountId) =&gt;\n      cfg.channels?.acmechat?.accounts?.[accountId ?? &quot;default&quot;] ?? {\n        accountId,\n      },\n  },\n  outbound: {\n    deliveryMode: &quot;direct&quot;,\n    sendText: async () =&gt; ({ ok: true }),\n  },\n};\n\nexport default function (api) {\n  api.registerChannel({ plugin: myChannel });\n}\n<\/code><\/pre>\n<p>\u8bf4\u660e\uff1a<\/p>\n<ul>\n<li>\u5c06\u914d\u7f6e\u653e\u5728 <code>channels.&lt;id&gt;<\/code> \u4e0b\uff08\u800c\u4e0d\u662f <code>plugins.entries<\/code>\uff09\u3002<\/li>\n<li><code>meta.label<\/code> \u7528\u4e8e CLI\/UI \u5217\u8868\u4e2d\u7684\u6807\u7b7e\u3002<\/li>\n<li><code>meta.aliases<\/code> \u4f1a\u4e3a\u89c4\u8303\u5316\u548c CLI \u8f93\u5165\u6dfb\u52a0\u5907\u7528 id\u3002<\/li>\n<li><code>meta.preferOver<\/code> \u5217\u51fa\u5f53\u4e24\u8005\u90fd\u5df2\u914d\u7f6e\u65f6\u5e94\u8df3\u8fc7\u81ea\u52a8\u542f\u7528\u7684\u6e20\u9053 id\u3002<\/li>\n<li><code>meta.detailLabel<\/code> \u548c <code>meta.systemImage<\/code> \u8ba9 UI \u80fd\u663e\u793a\u66f4\u4e30\u5bcc\u7684\u6e20\u9053\u6807\u7b7e\/\u56fe\u6807\u3002<\/li>\n<\/ul>\n<h3>\u6e20\u9053 setup hooks<\/h3>\n<p>\u63a8\u8350\u7684 setup \u62c6\u5206\uff1a<\/p>\n<ul>\n<li><code>plugin.setup<\/code> \u8d1f\u8d23\u8d26\u6237 id \u89c4\u8303\u5316\u3001\u9a8c\u8bc1\u548c\u914d\u7f6e\u5199\u5165\u3002<\/li>\n<li><code>plugin.setupWizard<\/code> \u8ba9\u5bbf\u4e3b\u8fd0\u884c\u901a\u7528\u5411\u5bfc\u6d41\u7a0b\uff0c\u800c\u6e20\u9053\u53ea\u63d0\u4f9b\u72b6\u6001\u3001\u51ed\u636e\u3001\u79c1\u4fe1 allowlist \u548c\u6e20\u9053\u8bbf\u95ee\u63cf\u8ff0\u7b26\u3002<\/li>\n<\/ul>\n<p><code>plugin.setupWizard<\/code> \u6700\u9002\u5408\u7b26\u5408\u5171\u4eab\u6a21\u5f0f\u7684\u6e20\u9053\uff1a<\/p>\n<ul>\n<li>\u4e00\u4e2a\u7531 <code>plugin.config.listAccountIds<\/code> \u9a71\u52a8\u7684\u8d26\u6237\u9009\u62e9\u5668<\/li>\n<li>\u5728\u63d0\u793a\u524d\u6267\u884c\u53ef\u9009\u7684\u9884\u68c0\/\u51c6\u5907\u6b65\u9aa4\uff08\u4f8b\u5982\u5b89\u88c5\u5668\/\u5f15\u5bfc\u5de5\u4f5c\uff09<\/li>\n<li>\u4e3a\u6346\u7ed1\u51ed\u636e\u96c6\u63d0\u4f9b\u53ef\u9009\u7684\u73af\u5883\u53d8\u91cf\u5feb\u6377\u63d0\u793a\uff08\u4f8b\u5982\u6210\u5bf9 bot\/app token\uff09<\/li>\n<li>\u4e00\u4e2a\u6216\u591a\u4e2a\u51ed\u636e\u63d0\u793a\uff0c\u6bcf\u4e00\u6b65\u8981\u4e48\u901a\u8fc7 <code>plugin.setup.applyAccountConfig<\/code> \u5199\u5165\uff0c\u8981\u4e48\u901a\u8fc7\u6e20\u9053\u81ea\u6709\u90e8\u5206\u8865\u4e01\u5199\u5165<\/li>\n<li>\u53ef\u9009\u7684\u975e secret \u6587\u672c\u63d0\u793a\uff08\u4f8b\u5982 CLI \u8def\u5f84\u3001base URL\u3001\u8d26\u6237 id\uff09<\/li>\n<li>\u53ef\u9009\u7684\u7531\u5bbf\u4e3b\u89e3\u6790\u7684\u6e20\u9053\/\u7fa4\u7ec4\u8bbf\u95ee allowlist \u63d0\u793a<\/li>\n<li>\u53ef\u9009\u7684\u79c1\u4fe1 allowlist \u89e3\u6790\uff08\u4f8b\u5982 <code>@username<\/code> -&gt; \u6570\u5b57 id\uff09<\/li>\n<li>setup \u5b8c\u6210\u540e\u7684\u53ef\u9009\u5b8c\u6210\u8bf4\u660e<\/li>\n<\/ul>\n<h3>\u7f16\u5199\u4e00\u4e2a\u65b0\u7684\u6d88\u606f\u6e20\u9053\uff08\u5206\u6b65\u8bf4\u660e\uff09<\/h3>\n<p>\u5f53\u4f60\u60f3\u8981\u4e00\u4e2a <strong>\u65b0\u7684\u804a\u5929\u8868\u9762<\/strong>\uff08\u5373\u201c\u6d88\u606f\u6e20\u9053\u201d\uff09\uff0c\u800c\u4e0d\u662f\u6a21\u578b provider \u65f6\uff0c\u8bf7\u4f7f\u7528\u672c\u8282\u3002<br \/>\n\u6a21\u578b provider \u6587\u6863\u4f4d\u4e8e <code>\/providers\/*<\/code>\u3002<\/p>\n<ol>\n<li>\u9009\u62e9\u4e00\u4e2a id + \u914d\u7f6e\u7ed3\u6784<\/li>\n<\/ol>\n<ul>\n<li>\u6240\u6709\u6e20\u9053\u914d\u7f6e\u90fd\u4f4d\u4e8e <code>channels.&lt;id&gt;<\/code> \u4e0b\u3002<\/li>\n<li>\u5bf9\u4e8e\u591a\u8d26\u6237\u8bbe\u7f6e\uff0c\u4f18\u5148\u4f7f\u7528 <code>channels.&lt;id&gt;.accounts.&lt;accountId&gt;<\/code>\u3002<\/li>\n<\/ul>\n<ol start=\"2\">\n<li>\u5b9a\u4e49\u6e20\u9053\u5143\u6570\u636e<\/li>\n<\/ol>\n<ul>\n<li><code>meta.label<\/code>\u3001<code>meta.selectionLabel<\/code>\u3001<code>meta.docsPath<\/code>\u3001<code>meta.blurb<\/code> \u63a7\u5236 CLI\/UI \u5217\u8868\u3002<\/li>\n<li><code>meta.docsPath<\/code> \u5e94\u6307\u5411\u7c7b\u4f3c <code>\/channels\/&lt;id&gt;<\/code> \u7684\u6587\u6863\u9875\u9762\u3002<\/li>\n<li><code>meta.preferOver<\/code> \u5141\u8bb8\u4e00\u4e2a\u63d2\u4ef6\u66ff\u6362\u53e6\u4e00\u4e2a\u6e20\u9053\uff08\u81ea\u52a8\u542f\u7528\u65f6\u4f18\u5148\u5b83\uff09\u3002<\/li>\n<li><code>meta.detailLabel<\/code> \u548c <code>meta.systemImage<\/code> \u4f9b UI \u7528\u4e8e\u8be6\u60c5\u6587\u5b57\/\u56fe\u6807\u3002<\/li>\n<\/ul>\n<ol start=\"3\">\n<li>\u5b9e\u73b0\u6240\u9700\u9002\u914d\u5668<\/li>\n<\/ol>\n<ul>\n<li><code>config.listAccountIds<\/code> + <code>config.resolveAccount<\/code><\/li>\n<li><code>capabilities<\/code>\uff08\u804a\u5929\u7c7b\u578b\u3001\u5a92\u4f53\u3001\u7ebf\u7a0b\u7b49\uff09<\/li>\n<li><code>outbound.deliveryMode<\/code> + <code>outbound.sendText<\/code>\uff08\u57fa\u7840\u53d1\u9001\uff09<\/li>\n<\/ul>\n<ol start=\"4\">\n<li>\u89c6\u9700\u8981\u6dfb\u52a0\u53ef\u9009\u9002\u914d\u5668<\/li>\n<\/ol>\n<ul>\n<li><code>setup<\/code>\uff08\u9a8c\u8bc1 + \u914d\u7f6e\u5199\u5165\uff09\u3001<code>setupWizard<\/code>\uff08\u5bbf\u4e3b\u62e5\u6709\u7684\u5411\u5bfc\uff09\u3001<code>security<\/code>\uff08\u79c1\u4fe1\u7b56\u7565\uff09\u3001<code>status<\/code>\uff08\u5065\u5eb7\/\u8bca\u65ad\uff09<\/li>\n<li><code>gateway<\/code>\uff08\u542f\u52a8\/\u505c\u6b62\/\u767b\u5f55\uff09\u3001<code>mentions<\/code>\u3001<code>threading<\/code>\u3001<code>streaming<\/code><\/li>\n<li><code>actions<\/code>\uff08\u6d88\u606f\u52a8\u4f5c\uff09\u3001<code>commands<\/code>\uff08\u539f\u751f\u547d\u4ee4\u884c\u4e3a\uff09<\/li>\n<\/ul>\n<ol start=\"5\">\n<li>\u5728\u4f60\u7684\u63d2\u4ef6\u4e2d\u6ce8\u518c\u8be5\u6e20\u9053<\/li>\n<\/ol>\n<ul>\n<li><code>api.registerChannel({ plugin })<\/code><\/li>\n<\/ul>\n<p>\u6700\u5c0f\u914d\u7f6e\u793a\u4f8b\uff1a<\/p>\n<p>&#8220;`json5  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\n{<br \/>\n  channels: {<br \/>\n    acmechat: {<br \/>\n      accounts: {<br \/>\n        default: { token: &#8220;ACME_TOKEN&#8221;, enabled: true },<br \/>\n      },<br \/>\n    },<br \/>\n  },<br \/>\n}<\/p>\n<pre><code>\n\u6700\u5c0f\u6e20\u9053\u63d2\u4ef6\uff08\u4ec5\u51fa\u7ad9\uff09\uff1a\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nconst plugin = {\n  id: &quot;acmechat&quot;,\n  meta: {\n    id: &quot;acmechat&quot;,\n    label: &quot;AcmeChat&quot;,\n    selectionLabel: &quot;AcmeChat (API)&quot;,\n    docsPath: &quot;\/channels\/acmechat&quot;,\n    blurb: &quot;AcmeChat \u6d88\u606f\u6e20\u9053\u3002&quot;,\n    aliases: [&quot;acme&quot;],\n  },\n  capabilities: { chatTypes: [&quot;direct&quot;] },\n  config: {\n    listAccountIds: (cfg) =&gt; Object.keys(cfg.channels?.acmechat?.accounts ?? {}),\n    resolveAccount: (cfg, accountId) =&gt;\n      cfg.channels?.acmechat?.accounts?.[accountId ?? &quot;default&quot;] ?? {\n        accountId,\n      },\n  },\n  outbound: {\n    deliveryMode: &quot;direct&quot;,\n    sendText: async ({ text }) =&gt; {\n      \/\/ \u5728\u8fd9\u91cc\u5c06 `text` \u53d1\u9001\u5230\u4f60\u7684\u6e20\u9053\n      return { ok: true };\n    },\n  },\n};\n\nexport default function (api) {\n  api.registerChannel({ plugin });\n}\n<\/code><\/pre>\n<p>\u52a0\u8f7d\u63d2\u4ef6\uff08\u6269\u5c55\u76ee\u5f55\u6216 <code>plugins.load.paths<\/code>\uff09\uff0c\u91cd\u542f gateway\uff0c<br \/>\n\u7136\u540e\u5728\u914d\u7f6e\u4e2d\u8bbe\u7f6e <code>channels.&lt;id&gt;<\/code>\u3002<\/p>\n<h3>\u667a\u80fd\u4f53\u5de5\u5177<\/h3>\n<p>\u8bf7\u53c2\u9605\u4e13\u95e8\u6307\u5357\uff1a<a href=\"\/plugins\/agent-tools\">Plugin agent tools<\/a>\u3002<\/p>\n<h3>\u6ce8\u518c\u4e00\u4e2a Gateway RPC \u65b9\u6cd5<\/h3>\n<p>&#8220;`ts  theme={&#8220;theme&#8221;:{&#8220;light&#8221;:&#8221;min-light&#8221;,&#8221;dark&#8221;:&#8221;min-dark&#8221;}}<br \/>\nexport default function (api) {<br \/>\n  api.registerGatewayMethod(&#8220;myplugin.status&#8221;, ({ respond }) =&gt; {<br \/>\n    respond(true, { ok: true });<br \/>\n  });<br \/>\n}<\/p>\n<pre><code>\n### \u6ce8\u518c CLI \u547d\u4ee4\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\nexport default function (api) {\n  api.registerCli(\n    ({ program }) =&gt; {\n      program.command(&quot;mycmd&quot;).action(() =&gt; {\n        console.log(&quot;Hello&quot;);\n      });\n    },\n    { commands: [&quot;mycmd&quot;] },\n  );\n}\n<\/code><\/pre>\n<h3>\u6ce8\u518c\u81ea\u52a8\u56de\u590d\u547d\u4ee4<\/h3>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u6ce8\u518c\u81ea\u5b9a\u4e49 slash \u547d\u4ee4\uff0c\u8fd9\u4e9b\u547d\u4ee4 <strong>\u65e0\u9700\u8c03\u7528 AI \u667a\u80fd\u4f53<\/strong> \u5373\u53ef\u6267\u884c\u3002<br \/>\n\u8fd9\u5bf9\u5f00\u5173\u547d\u4ee4\u3001\u72b6\u6001\u68c0\u67e5\u6216\u4e0d\u9700\u8981 LLM \u5904\u7406\u7684\u5feb\u6377\u64cd\u4f5c\u975e\u5e38\u6709\u7528\u3002<\/p>\n<p><code>``ts  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}<br \/>\nexport default function (api) {<br \/>\n  api.registerCommand({<br \/>\n    name: \"mystatus\",<br \/>\n    description: \"\u663e\u793a\u63d2\u4ef6\u72b6\u6001\",<br \/>\n    handler: (ctx) =&gt; ({<br \/>\n      text:<\/code>\u63d2\u4ef6\u6b63\u5728\u8fd0\u884c\uff01\u6e20\u9053\uff1a${ctx.channel}`,<br \/>\n    }),<br \/>\n  });<br \/>\n}<\/p>\n<pre><code>\n\u547d\u4ee4\u5904\u7406\u5668\u4e0a\u4e0b\u6587\uff1a\n\n* `senderId`\uff1a\u53d1\u9001\u8005\u7684 ID\uff08\u5982\u679c\u53ef\u7528\uff09\n* `channel`\uff1a\u53d1\u9001\u547d\u4ee4\u7684\u6e20\u9053\n* `isAuthorizedSender`\uff1a\u53d1\u9001\u8005\u662f\u5426\u4e3a\u5df2\u6388\u6743\u7528\u6237\n* `args`\uff1a\u547d\u4ee4\u540e\u7684\u53c2\u6570\uff08\u5982\u679c `acceptsArgs: true`\uff09\n* `commandBody`\uff1a\u5b8c\u6574\u547d\u4ee4\u6587\u672c\n* `config`\uff1a\u5f53\u524d OpenClaw \u914d\u7f6e\n\n\u547d\u4ee4\u9009\u9879\uff1a\n\n* `name`\uff1a\u547d\u4ee4\u540d\uff08\u4e0d\u542b\u524d\u5bfc `\/`\uff09\n* `nativeNames`\uff1a\u53ef\u9009\u7684\u539f\u751f\u547d\u4ee4\u522b\u540d\uff0c\u7528\u4e8e slash\/menu \u8868\u9762\u3002\u5bf9\u6240\u6709\u539f\u751f provider \u4f7f\u7528 `default`\uff0c\u6216\u4f7f\u7528\u5982 `discord` \u8fd9\u6837\u7684 provider \u7279\u5b9a\u952e\n* `description`\uff1a\u5728\u547d\u4ee4\u5217\u8868\u4e2d\u663e\u793a\u7684\u5e2e\u52a9\u6587\u672c\n* `acceptsArgs`\uff1a\u547d\u4ee4\u662f\u5426\u63a5\u53d7\u53c2\u6570\uff08\u9ed8\u8ba4\uff1afalse\uff09\u3002\u5982\u679c\u4e3a false \u4e14\u63d0\u4f9b\u4e86\u53c2\u6570\uff0c\u5219\u547d\u4ee4\u4e0d\u4f1a\u5339\u914d\uff0c\u6d88\u606f\u4f1a\u7ee7\u7eed\u4f20\u9012\u7ed9\u5176\u4ed6\u5904\u7406\u5668\n* `requireAuth`\uff1a\u662f\u5426\u8981\u6c42\u53d1\u9001\u8005\u5df2\u6388\u6743\uff08\u9ed8\u8ba4\uff1atrue\uff09\n* `handler`\uff1a\u8fd4\u56de `{ text: string }` \u7684\u51fd\u6570\uff08\u53ef\u4ee5\u662f\u5f02\u6b65\uff09\n\n\u5e26\u6388\u6743\u548c\u53c2\u6570\u7684\u793a\u4f8b\uff1a\n\n```ts  theme={&quot;theme&quot;:{&quot;light&quot;:&quot;min-light&quot;,&quot;dark&quot;:&quot;min-dark&quot;}}\napi.registerCommand({\n  name: &quot;setmode&quot;,\n  description: &quot;\u8bbe\u7f6e\u63d2\u4ef6\u6a21\u5f0f&quot;,\n  acceptsArgs: true,\n  requireAuth: true,\n  handler: async (ctx) =&gt; {\n    const mode = ctx.args?.trim() || &quot;default&quot;;\n    await saveMode(mode);\n    return { text: `\u6a21\u5f0f\u5df2\u8bbe\u7f6e\u4e3a\uff1a${mode}` };\n  },\n});\n<\/code><\/pre>\n<p>\u8bf4\u660e\uff1a<\/p>\n<ul>\n<li>\u63d2\u4ef6\u547d\u4ee4\u4f1a\u5728\u5185\u7f6e\u547d\u4ee4\u548c AI \u667a\u80fd\u4f53 <strong>\u4e4b\u524d<\/strong> \u5904\u7406<\/li>\n<li>\u547d\u4ee4\u662f\u5168\u5c40\u6ce8\u518c\u7684\uff0c\u9002\u7528\u4e8e\u6240\u6709\u6e20\u9053<\/li>\n<li>\u547d\u4ee4\u540d\u4e0d\u533a\u5206\u5927\u5c0f\u5199\uff08<code>\/MyStatus<\/code> \u53ef\u5339\u914d <code>\/mystatus<\/code>\uff09<\/li>\n<li>\u547d\u4ee4\u540d\u5fc5\u987b\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u5e76\u4e14\u53ea\u80fd\u5305\u542b\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u8fde\u5b57\u7b26\u548c\u4e0b\u5212\u7ebf<\/li>\n<li>\u4fdd\u7559\u547d\u4ee4\u540d\uff08\u5982 <code>help<\/code>\u3001<code>status<\/code>\u3001<code>reset<\/code> \u7b49\uff09\u4e0d\u80fd\u88ab\u63d2\u4ef6\u8986\u76d6<\/li>\n<li>\u63d2\u4ef6\u95f4\u91cd\u590d\u6ce8\u518c\u547d\u4ee4\u4f1a\u56e0\u8bca\u65ad\u9519\u8bef\u800c\u5931\u8d25<\/li>\n<\/ul>\n<h3>\u6ce8\u518c\u540e\u53f0\u670d\u52a1<\/h3>\n<p><code>ts  theme={\"theme\":{\"light\":\"min-light\",\"dark\":\"min-dark\"}}<br \/>\nexport default function (api) {<br \/>\n  api.registerService({<br \/>\n    id: \"my-service\",<br \/>\n    start: () =&gt; api.logger.info(\"ready\"),<br \/>\n    stop: () =&gt; api.logger.info(\"bye\"),<br \/>\n  });<br \/>\n}<\/code><\/p>\n<h2>\u547d\u540d\u7ea6\u5b9a<\/h2>\n<ul>\n<li>Gateway \u65b9\u6cd5\uff1a<code>pluginId.action<\/code>\uff08\u4f8b\u5982\uff1a<code>voicecall.status<\/code>\uff09<\/li>\n<li>\u5de5\u5177\uff1a<code>snake_case<\/code>\uff08\u4f8b\u5982\uff1a<code>voice_call<\/code>\uff09<\/li>\n<li>CLI \u547d\u4ee4\uff1akebab \u6216 camel\uff0c\u4f46\u907f\u514d\u4e0e\u6838\u5fc3\u547d\u4ee4\u51b2\u7a81<\/li>\n<\/ul>\n<h2>Skills<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\u5728\u4ed3\u5e93\u4e2d\u9644\u5e26\u4e00\u4e2a skill\uff08<code>skills\/&lt;name&gt;\/SKILL.md<\/code>\uff09\u3002<br \/>\n\u901a\u8fc7 <code>plugins.entries.&lt;id&gt;.enabled<\/code>\uff08\u6216\u5176\u4ed6\u914d\u7f6e\u95e8\u63a7\uff09\u542f\u7528\u5b83\uff0c\u5e76\u786e\u4fdd\u5b83\u5b58\u5728\u4e8e\u4f60\u7684\u5de5\u4f5c\u533a\/\u6258\u7ba1 skills \u4f4d\u7f6e\u4e2d\u3002<\/p>\n<h2>\u5206\u53d1\uff08npm\uff09<\/h2>\n<p>\u63a8\u8350\u6253\u5305\u65b9\u5f0f\uff1a<\/p>\n<ul>\n<li>\u4e3b\u5305\uff1a<code>openclaw<\/code>\uff08\u672c\u4ed3\u5e93\uff09<\/li>\n<li>\u63d2\u4ef6\uff1a\u4f4d\u4e8e <code>@openclaw\/*<\/code> \u4e0b\u7684\u72ec\u7acb npm \u5305\uff08\u4f8b\u5982\uff1a<code>@openclaw\/voice-call<\/code>\uff09<\/li>\n<\/ul>\n<p>\u53d1\u5e03\u5951\u7ea6\uff1a<\/p>\n<ul>\n<li>\u63d2\u4ef6 <code>package.json<\/code> \u5fc5\u987b\u5305\u542b <code>openclaw.extensions<\/code>\uff0c\u5e76\u6307\u5411\u4e00\u4e2a\u6216\u591a\u4e2a\u5165\u53e3\u6587\u4ef6\u3002<\/li>\n<li>\u53ef\u9009\uff1a<code>openclaw.setupEntry<\/code> \u53ef\u6307\u5411\u4e00\u4e2a\u8f7b\u91cf\u7ea7\u7684\u4ec5 setup \u5165\u53e3\uff0c\u7528\u4e8e\u5df2\u7981\u7528\u6216\u5c1a\u672a\u914d\u7f6e\u5b8c\u6210\u7684\u6e20\u9053 setup\u3002<\/li>\n<li>\u5165\u53e3\u6587\u4ef6\u53ef\u4ee5\u662f <code>.js<\/code> \u6216 <code>.ts<\/code>\uff08jiti \u4f1a\u5728\u8fd0\u884c\u65f6\u52a0\u8f7d TS\uff09\u3002<\/li>\n<li><code>openclaw plugins install &lt;npm-spec&gt;<\/code> \u4f1a\u4f7f\u7528 <code>npm pack<\/code>\uff0c\u63d0\u53d6\u5230 <code>~\/.openclaw\/extensions\/&lt;id&gt;\/<\/code>\uff0c\u5e76\u5728\u914d\u7f6e\u4e2d\u542f\u7528\u5b83\u3002<\/li>\n<li>\u914d\u7f6e\u952e\u7a33\u5b9a\u6027\uff1a\u5e26 scope \u7684\u5305\u4f1a\u88ab\u89c4\u8303\u5316\u4e3a <strong>\u65e0 scope<\/strong> \u7684 id\uff0c\u7528\u4e8e <code>plugins.entries.*<\/code>\u3002<\/li>\n<\/ul>\n<h2>\u793a\u4f8b\u63d2\u4ef6\uff1aVoice Call<\/h2>\n<p>\u672c\u4ed3\u5e93\u5305\u542b\u4e00\u4e2a voice-call \u63d2\u4ef6\uff08Twilio \u6216\u65e5\u5fd7\u56de\u9000\uff09\uff1a<\/p>\n<ul>\n<li>\u6e90\u7801\uff1a<code>extensions\/voice-call<\/code><\/li>\n<li>Skill\uff1a<code>skills\/voice-call<\/code><\/li>\n<li>CLI\uff1a<code>openclaw voicecall start|status<\/code><\/li>\n<li>\u5de5\u5177\uff1a<code>voice_call<\/code><\/li>\n<li>RPC\uff1a<code>voicecall.start<\/code>\u3001<code>voicecall.status<\/code><\/li>\n<li>\u914d\u7f6e\uff08twilio\uff09\uff1a<code>provider: \"twilio\"<\/code> + <code>twilio.accountSid\/authToken\/from<\/code>\uff08\u53ef\u9009 <code>statusCallbackUrl<\/code>\u3001<code>twimlUrl<\/code>\uff09<\/li>\n<li>\u914d\u7f6e\uff08\u5f00\u53d1\uff09\uff1a<code>provider: \"log\"<\/code>\uff08\u65e0\u7f51\u7edc\uff09<\/li>\n<\/ul>\n<p>\u6709\u5173\u8bbe\u7f6e\u548c\u7528\u6cd5\uff0c\u8bf7\u53c2\u9605 <a href=\"\/plugins\/voice-call\">Voice Call<\/a> \u548c <code>extensions\/voice-call\/README.md<\/code>\u3002<\/p>\n<h2>\u5b89\u5168\u8bf4\u660e<\/h2>\n<p>\u63d2\u4ef6\u4e0e Gateway \u7f51\u5173\u5728\u540c\u4e00\u8fdb\u7a0b\u5185\u8fd0\u884c\u3002\u8bf7\u5c06\u5b83\u4eec\u89c6\u4e3a\u53d7\u4fe1\u4efb\u4ee3\u7801\uff1a<\/p>\n<ul>\n<li>\u53ea\u5b89\u88c5\u4f60\u4fe1\u4efb\u7684\u63d2\u4ef6\u3002<\/li>\n<li>\u4f18\u5148\u4f7f\u7528 <code>plugins.allow<\/code> allowlist\u3002<\/li>\n<li>\u8bf7\u8bb0\u4f4f\uff0c<code>plugins.allow<\/code> \u662f\u57fa\u4e8e id \u7684\uff0c\u56e0\u6b64\u5df2\u542f\u7528\u7684\u5de5\u4f5c\u533a\u63d2\u4ef6\u53ef\u4ee5\u6709\u610f\u8986\u76d6\u5177\u6709\u76f8\u540c id \u7684\u6346\u7ed1\u63d2\u4ef6\u3002<\/li>\n<li>\u66f4\u6539\u540e\u8bf7\u91cd\u542f Gateway \u7f51\u5173\u3002<\/li>\n<\/ul>\n<h2>\u6d4b\u8bd5\u63d2\u4ef6<\/h2>\n<p>\u63d2\u4ef6\u53ef\u4ee5\uff08\u4e5f\u5e94\u8be5\uff09\u9644\u5e26\u6d4b\u8bd5\uff1a<\/p>\n<ul>\n<li>\u4ed3\u5e93\u5185\u63d2\u4ef6\u53ef\u4ee5\u5c06 Vitest \u6d4b\u8bd5\u653e\u5728 <code>src\/**<\/code> \u4e0b\uff08\u4f8b\u5982\uff1a<code>src\/plugins\/voice-call.plugin.test.ts<\/code>\uff09\u3002<\/li>\n<li>\u5355\u72ec\u53d1\u5e03\u7684\u63d2\u4ef6\u5e94\u8fd0\u884c\u81ea\u5df1\u7684 CI\uff08lint\/build\/test\uff09\uff0c\u5e76\u9a8c\u8bc1 <code>openclaw.extensions<\/code> \u6307\u5411\u6784\u5efa\u540e\u7684\u5165\u53e3\u70b9\uff08<code>dist\/index.js<\/code>\uff09\u3002<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u63d2\u4ef6 \u63d2\u4ef6\uff08\u6269\u5c55\uff09 \u5feb\u901f\u5f00\u59cb\uff08\u521a\u63a5\u89e6\u63d2\u4ef6\uff1f\uff09 \u63d2\u4ef6\u53ef\u4ee5\u662f\u4ee5\u4e0b\u4e24\u79cd\u4e4b\u4e00\uff1a \u539f\u751f OpenClaw \u63d2\u4ef6\uff08open [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-289","post","type-post","status-publish","format-standard","hentry","category-docs"],"_links":{"self":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/289","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/comments?post=289"}],"version-history":[{"count":1,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/289\/revisions"}],"predecessor-version":[{"id":584,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/posts\/289\/revisions\/584"}],"wp:attachment":[{"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/media?parent=289"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/categories?post=289"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pa.yingzhi8.cn\/index.php\/wp-json\/wp\/v2\/tags?post=289"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}