1. WorkBuddy Claw 一号员工上岗:openclaw 二次开发到底在改什么
WorkBuddy Claw 是腾讯推出的 AI 同事产品,你可以把它理解成一个能听懂人话、在你电脑上自主规划并执行任务的智能体,而 Claw 则是它的手机遥控器——在企业微信、飞书、钉钉、QQ 里发一条消息,就能远程调度电脑上的 WorkBuddy 干活。openclaw 是它的开源内核,也是二次开发的入口。适合谁?适合那些不满足于“开箱即用”、想把 AI 同事接入自己业务流、定制专属技能和自动化任务的开发者与团队。
我试过把 openclaw 拉下来跑通第一个自动化任务,整个过程踩了不少坑,但也摸清了二次开发的最小闭环。这篇文章就按“环境准备 → 配置项梳理 → 首个任务跑通 → 验证结果 → 排障”的顺序,把每一步的可复制片段给你。
先说清楚二次开发改的是什么。openclaw 的核心是一套 Agent 调度框架:它接收指令,拆解成子任务,调用本地或云端的工具(文件读写、命令执行、HTTP 请求、技能插件),最后汇总结果。二次开发主要动三个地方:一是技能(Skill)的注册与实现,二是模型接入配置,三是任务调度与回调逻辑。你不需要改内核,只需要在约定的扩展点上挂自己的代码。
为什么强调“一号员工”这个定位?因为 openclaw 的设计目标不是聊天,而是交付可验收的结果。它支持多 Agents 并行、云端与本地协同、定时任务和工作流沉淀。这意味着你的二次开发可以围绕“让这个员工学会一项新技能”来展开,而不是从零搭一个 Agent 框架。
环境准备阶段,你需要一台能跑 Node.js 的机器(本地或云主机都行),Node 18 以上,pnpm 或 npm 任选。openclaw 的仓库结构里,skills/目录放技能实现,config/放模型和运行时配置,tasks/放任务定义。第一次跑建议先用官方示例技能验证链路,再替换成自己的。
这里有个容易忽略的点:openclaw 的技能是声明式注册的,每个技能有一个 manifest 描述它的名称、入参、出参和触发方式。你写技能时,只要按 manifest 约定实现 handler 函数即可,框架负责调度和错误重试。这个设计让二次开发的门槛降了很多——你不需要懂调度器内部,只要会写一个函数。
模型接入方面,openclaw 支持多家模型供应商。如果你想让自己的 Agent 稳定跑起来,建议用一个兼容 OpenAI 接口协议的网关来统一管理 Key 和模型路由。TaoToken 就是这样一个入口,它的 API 地址是 https://taotoken.net/api,兼容主流接口格式,配置时把 Base URL 指向它、填上你的 Key、指定 Model ID 就行。这样你换模型时不用改代码,只改配置。
接下来进入实操。我会先给出环境准备和依赖安装的完整命令,再给出配置文件的 JSON 片段,然后写一个最小技能,最后用一次真实请求验证整个链路。每一步都有可复制的代码和预期结果,你跟着做就能跑通。
2. TaoToken 前置:openclaw 二次开发的模型接入与 Key 准备
在写第一行技能代码之前,先把模型接入这条链路打通。openclaw 的 Agent 要能思考、规划、调用工具,背后必须有一个稳定的模型服务。二次开发阶段你可能会频繁切换模型做对比,所以用一个统一的网关来管理接入是最省事的做法。
TaoToken 的定位就是模型接入网关,它兼容 OpenAI 的接口协议,你拿到的 Key 可以同时用于对话、代码补全等场景。对于 openclaw 二次开发来说,你只需要关心三件事:Base URL、API Key、Model ID。这三个东西填对了,Agent 就能跑起来。
先拿 Key。访问 https://taotoken.net/api-keys 创建你的 API Key,复制下来保存好。注意这个 Key 只在创建时完整显示一次,丢了就得重新建。拿到 Key 之后,你的接入信息是:
- Base URL:https://taotoken.net/api
- API Key:你刚创建的那串字符
- Model ID:按你需要的模型填,比如 claude-sonnet-4-20250514 或 gpt-4o 这类
如果你用的是 Claude Code 做辅助开发,可以走 https://taotoken.net/claude-code-anthropic 这个入口,它把 Anthropic 风格的接口也做了适配。对于 openclaw 这种需要频繁调用工具的 Agent,建议选一个支持 function calling 的模型,否则技能调度会失败。
配置写在哪里?openclaw 的模型配置通常在config/models.json或环境变量里。推荐用环境变量,避免 Key 进版本库。你可以建一个.env文件:
# .env OPENCLAW_BASE_URL=https://taotoken.net/api OPENCLAW_API_KEY=sk-你的Key OPENCLAW_MODEL_ID=claude-sonnet-4-20250514然后在 openclaw 的配置加载逻辑里读取这三个变量。如果你用的是 JSON 配置,可以这样写:
{ "model": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "${OPENCLAW_API_KEY}", "modelId": "claude-sonnet-4-20250514", "maxTokens": 4096, "temperature": 0.3 }, "runtime": { "maxConcurrentTasks": 3, "taskTimeoutMs": 120000 } }注意apiKey用了${OPENCLAW_API_KEY}这种占位符写法,openclaw 启动时会从环境变量注入。这样你的配置文件可以安全地提交到仓库,Key 留在本地。
为什么 temperature 设 0.3?因为 Agent 任务需要稳定复现,太高的随机性会让同一个指令每次跑出不同结果,排障时很痛苦。maxConcurrentTasks 设 3 是保守值,先跑通再往上加。
配置写完后,先别急着跑 Agent,用一条 curl 验证模型链路是否通:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENCLAW_API_KEY" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复 OK 两个字母"}], "max_tokens": 16 }'如果返回的 JSON 里choices[0].message.content包含 OK,说明 Key 和 Base URL 都对。这一步很重要,因为后面 Agent 报错时,你要能区分是模型链路问题还是技能代码问题。我踩过的坑就是:技能 handler 里抛了异常,但错误信息被模型调用失败掩盖了,查了半天才发现是 Key 过期。
还有一个细节:openclaw 在调用模型时可能会带 tools 参数(function calling)。如果你的模型不支持,会返回 400。这时候要么换模型,要么在配置里关掉工具调用,改成纯文本解析。建议直接用支持 function calling 的模型,省事。
Key 准备好、链路验证通过之后,就可以进入技能开发了。下一节我会给出一个完整的最小技能实现,以及它在 openclaw 里怎么注册、怎么被调度。
3. 可复制配置:openclaw 技能注册与 settings 片段
这一节是二次开发的核心。openclaw 的技能机制是:你在skills/目录下建一个文件夹,里面放manifest.json和handler.js(或.ts),框架启动时扫描并注册。Agent 在规划任务时,会根据 manifest 里的描述决定是否调用这个技能。
先看目录结构:
openclaw/ ├── config/ │ └── models.json ├── skills/ │ └── daily-report/ │ ├── manifest.json │ └── handler.js └── tasks/ └── daily-report.task.jsonmanifest.json描述技能元信息:
{ "name": "daily-report", "version": "1.0.0", "description": "生成每日工作日报,汇总指定目录下的文件变更并输出 Markdown", "trigger": { "type": "command", "keywords": ["日报", "daily report", "生成日报"] }, "input": { "type": "object", "properties": { "targetDir": { "type": "string", "description": "要汇总的目录路径" }, "date": { "type": "string", "description": "日期,格式 YYYY-MM-DD,默认今天" } }, "required": ["targetDir"] }, "output": { "type": "object", "properties": { "reportPath": { "type": "string" }, "summary": { "type": "string" } } } }这个 manifest 告诉 openclaw:当用户说“生成日报”时,可以调用这个技能,需要传入 targetDir。框架会把模型解析出的参数传给 handler。
handler.js是实际执行逻辑:
const fs = require('fs'); const path = require('path'); module.exports = async function handler(params, context) { const { targetDir, date } = params; const reportDate = date || new Date().toISOString().slice(0, 10); if (!fs.existsSync(targetDir)) { throw new Error(`目录不存在: ${targetDir}`); } const files = fs.readdirSync(targetDir, { withFileTypes: true }); const fileList = files .filter(f => f.isFile()) .map(f => { const stat = fs.statSync(path.join(targetDir, f.name)); return { name: f.name, size: stat.size, mtime: stat.mtime.toISOString() }; }); const summary = fileList .map(f => `- ${f.name} (${f.size} bytes, 修改于 ${f.mtime})`) .join('\n'); const reportContent = `# 日报 ${reportDate}\n\n## 文件变更\n\n${summary}\n`; const reportPath = path.join(targetDir, `report-${reportDate}.md`); fs.writeFileSync(reportPath, reportContent, 'utf-8'); return { reportPath, summary: `共 ${fileList.length} 个文件,报告已写入 ${reportPath}` }; };这个 handler 做了三件事:校验目录、读取文件列表、生成 Markdown 报告并写回磁盘。返回的对象会被 openclaw 记录,并作为任务结果展示。
接下来是任务定义tasks/daily-report.task.json,它让这个技能可以定时触发:
{ "name": "daily-report-task", "skill": "daily-report", "schedule": "0 18 * * *", "params": { "targetDir": "/Users/yourname/work/logs" }, "enabled": true }schedule用的是 cron 表达式,0 18 * * *表示每天 18:00 执行。openclaw 的调度器会读取这个文件并注册定时任务。
如果你用的是 TypeScript 版本,handler 的签名类似,只是多了类型定义。核心逻辑不变。
配置里还有一个关键项:技能的超时和重试。在config/runtime.json里可以设:
{ "skillTimeoutMs": 30000, "skillRetry": { "maxAttempts": 2, "backoffMs": 1000 } }这意味着单个技能最多跑 30 秒,失败重试 2 次,每次间隔 1 秒。对于日报这种 IO 密集型任务够用了。如果是调用外部 API 的技能,把超时调大。
注册完技能后,openclaw 启动时会打印已加载的技能列表。你可以在日志里看到[SkillRegistry] loaded: daily-report@1.0.0。如果没看到,说明 manifest 格式有问题,检查 JSON 是否合法、name 是否重复。
这一节的配置片段你可以直接复制到自己的项目里,改一下 targetDir 和 schedule 就能跑。下一节我会用一次真实请求验证整个链路,包括模型解析指令、技能执行、结果返回。
4. 验证请求:跑通首个自动化任务并确认结果
配置写完了,现在跑一次真实请求。openclaw 的启动命令通常是:
cd openclaw pnpm install pnpm start启动后你会看到类似输出:
[Config] loaded models.json [SkillRegistry] loaded: daily-report@1.0.0 [TaskScheduler] registered: daily-report-task (0 18 * * *) [Server] listening on http://localhost:3000这说明技能和定时任务都注册成功了。接下来用 HTTP 请求触发一次任务。openclaw 一般会暴露一个/api/task接口:
curl -X POST http://localhost:3000/api/task \ -H "Content-Type: application/json" \ -d '{ "instruction": "帮我生成今天的日报,目录是 /Users/yourname/work/logs", "skillHint": "daily-report" }'注意skillHint是可选的,如果你不指定,openclaw 会让模型自己判断该调用哪个技能。第一次跑建议指定,减少变量。
预期返回:
{ "taskId": "task-20250520-001", "status": "completed", "skill": "daily-report", "result": { "reportPath": "/Users/yourname/work/logs/report-2025-05-20.md", "summary": "共 12 个文件,报告已写入 /Users/yourname/work/logs/report-2025-05-20.md" }, "durationMs": 842 }如果 status 是 completed,去目标目录看报告文件是否存在、内容是否正确。打开report-2025-05-20.md,应该能看到文件列表和修改时间。
这一步验证了什么?验证了模型链路通、技能注册成功、参数解析正确、handler 执行无异常、结果回传正常。整个二次开发的最小闭环就跑通了。
如果你想验证定时任务,可以把 cron 改成*/2 * * * *(每 2 分钟),等两分钟看日志里是否有自动执行记录。或者直接调用调度器的触发接口:
curl -X POST http://localhost:3000/api/schedule/trigger \ -H "Content-Type: application/json" \ -d '{"taskName": "daily-report-task"}'返回里会显示任务被手动触发,执行结果和上面一样。
还有一个验证点:多 Agents 并行。你可以同时发两个请求,一个生成日报,一个做别的(比如文件重命名)。openclaw 会并行执行,看板里能看到两个任务的状态。这验证了 maxConcurrentTasks 配置生效。
跑通之后,你可以把技能替换成自己的业务逻辑。比如把“读取文件列表”改成“调用内部 API 拉取工单”,把“写 Markdown”改成“发送到企业微信”。框架不变,只改 handler。
这里有个实用技巧:在 handler 里加日志,方便排障。openclaw 的 context 对象通常带 logger:
module.exports = async function handler(params, context) { context.logger.info('daily-report started', { targetDir: params.targetDir }); // ... context.logger.info('daily-report finished', { reportPath }); return { reportPath, summary }; };日志会输出到 openclaw 的控制台或日志文件。排障时先看日志,再看模型返回,最后看技能代码。
验证通过后,你就有了一个可复现的二次开发闭环。接下来可以把这个技能接入 Claw,通过企业微信或飞书远程触发。Claw 的接入配置在 openclaw 的config/claw.json里,填上 IM 平台的 webhook 和 token 即可。这部分官方有图文教程,按步骤操作就行。
5. 本篇常见错排查:401、local proxy failed 与 reading choices
二次开发过程中最容易卡在几个报错上。这一节我把真实遇到过的错误和排查路径列出来,你对照着看。
401 Unauthorized。这个最常见,原因是 API Key 无效或没传对。检查三件事:Key 是否复制完整(有没有多余空格)、环境变量是否真的注入到进程里(echo $OPENCLAW_API_KEY看看)、Base URL 是否写成了https://taotoken.net/api而不是带/v1的路径。openclaw 的模型客户端通常会自动拼/v1/chat/completions,你如果 Base URL 里已经带了/v1,就会变成/v1/v1/...,返回 404 或 401。正确写法是 Base URL 只到/api。
local proxy failed。这个报错通常出现在 openclaw 尝试通过本地代理访问模型时。如果你没有配代理,检查配置文件里是否有proxy字段被误开。openclaw 的默认配置里 proxy 是关闭的,但有些示例配置会带上。把proxy设为null或删掉这个字段。另外,如果你在容器里跑 openclaw,容器内的 localhost 和宿主机的 localhost 不是一回事,代理地址要写宿主机的 IP。
reading 'choices'。这个报错的全称通常是Cannot read properties of undefined (reading 'choices'),意思是模型返回的 JSON 里没有choices字段。原因可能是:模型返回了错误信息(比如{"error": {"message": "..."}}),但 openclaw 的解析代码直接读了response.choices。排查方法是把原始返回打印出来。在模型客户端里加一行console.log(JSON.stringify(rawResponse)),看看到底返回了什么。常见原因是模型 ID 写错了,或者账户余额不足。
OAuth 相关报错。如果你用的是 Claude Code 或某些需要 OAuth 的入口,可能会遇到 token 过期。这时候重新走一遍授权流程,或者改用 API Key 方式接入。TaoToken 的 API Key 方式不涉及 OAuth,配置更简单。
技能未注册。日志里没有[SkillRegistry] loaded: your-skill,说明 manifest 有问题。检查 JSON 是否合法(用jq . manifest.json验证)、name 是否和目录名一致、handler 文件是否存在。openclaw 对 manifest 的字段有校验,缺name或description会跳过注册。
任务超时。如果技能执行超过skillTimeoutMs,任务会被标记为 timeout。日报这种任务一般不会超时,但如果你在 handler 里调用了慢速外部 API,就要把超时调大。另外,重试次数设太多会导致任务卡很久,建议 maxAttempts 不超过 3。
参数解析错误。模型把targetDir解析成了别的字段名,导致 handler 收到 undefined。解决办法是在 manifest 的input.properties里把描述写清楚,并在 handler 里做参数校验:
if (!params.targetDir) { throw new Error('缺少必需参数 targetDir'); }这样错误信息更明确,排障更快。
Claw 远程触发无响应。如果你已经接入了企业微信或飞书,但发消息后没反应,检查 Claw 的 webhook 配置和 openclaw 的回调地址是否匹配。另外,Claw 的消息需要包含技能关键词,或者你在 Claw 配置里指定了默认技能。看 openclaw 的日志里有没有收到消息记录,如果没有,说明 webhook 没通。
排障的通用思路是:先看日志,再看原始返回,最后看配置。openclaw 的日志级别可以在config/logging.json里调成 debug,会打印更多细节。
6. 语义一致 CTA:把一号员工接入你的工作流
跑通第一个技能之后,下一步就是把它接入真实工作流。你可以从这几个入口继续:
想让 Agent 能对话、验证模型效果,用模型对话入口:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model-chat
需要长期跑编码任务或 Agent 工作流,用 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding-plan
管理你的 API Key 和用量,去控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console
创建新的 Key:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api-keys
接入文档和配置示例:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc
如果你用 Claude Code 做辅助开发,走这个入口:https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=claude-code-anthropic
官网首页:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
把 openclaw 的技能目录当成你的“员工培训手册”,每加一个技能,这个一号员工就多会一件事。从日报开始,慢慢扩展到数据清洗、竞品抓取、会议纪要整理。跑通一个就沉淀一个,别贪多。