OpenClaw+ClaudeCode 长跑写代码系统:自动验收与失败返工怎么搭?

发布时间:2026/10/17 18:29:00
OpenClaw+ClaudeCode 长跑写代码系统:自动验收与失败返工怎么搭? 1. 为什么单靠 ClaudeCode 跑长任务总会断在半路很多人第一次用 ClaudeCode 写代码体验都很好给它一个明确任务它读 repo、改文件、跑测试一轮下来交付得挺漂亮。但只要你把任务拉长比如「把这个模块重构完顺便把相关测试补齐再跑通 CI」问题就来了。我试过让它连续跑一个中等规模的重构前 20 分钟很顺到第 3 轮修改时它开始重复改同一个文件测试报错它改了一处又弄坏另一处最后停在一个「看起来改完了但测试还是红的」状态然后就没有然后了。这不是 ClaudeCode 能力不行而是它本质上是一个执行者不是编排者。它擅长把「当前这一步」做到极致但不擅长记住「整个任务跑到哪了、失败了几次、下一步该干嘛」。这就是 OpenClaw ClaudeCode 组合要解决的问题。OpenClaw 负责外层编排接任务、拆阶段、记状态、判断验收、触发返工、通知人工ClaudeCode 负责执行读代码、改代码、跑局部验证、产出 diff。两者职责拆开长跑才稳。这篇文章要回答的是一个很具体的问题怎么搭一个能长时间跑起来写代码、自动验收、失败返工、不中断推进的系统适合已经用过 ClaudeCode、想把它从「单轮工具」升级成「长期 worker」的开发者。下面我会给出可复制的编排配置、验收钩子、返工触发条件以及怎么通过 TaoToken 统一 Key/API 通道接入模型调用保证长跑过程中不会因为通道问题断掉。核心检索词先摆出来OpenClaw 编排、ClaudeCode 长跑、AI Agent 自动验收、失败返工、任务队列、TaoToken 统一接入。这几个词贯穿全文你照着搭就能跑起来。先说结论避免你走弯路ClaudeCode 放在执行层只做它最强的写代码那一段OpenClaw 放在编排层负责任务队列、状态机、验收钩子、返工触发、通知验收必须独立于 coder不能让 ClaudeCode 自己宣布「我修好了」模型调用通道用 TaoToken 统一避免长跑中途 Key 失效或通道抖动导致整个任务挂掉。把这四件事定下来系统就有了骨架。接下来逐层拆。2. TaoToken 前置统一 Key 与 API 通道长跑不断线长跑系统最怕的不是代码写错而是跑到一半通道断了。ClaudeCode 在长任务里会频繁调用模型如果每次调用都依赖一个不稳定的通道或者 Key 分散在多个地方管理一旦某个 Key 限流或失效整个任务就卡死。所以第一步是把模型调用通道统一起来。TaoToken 在这里的角色是统一 Key/API 通道你只需要在 TaoToken 控制台创建一个 API Key然后在 ClaudeCode 和 OpenClaw 的配置里都指向同一个 Base URL模型调用就走同一条通道。这样长跑过程中不会出现「ClaudeCode 用的 Key 和 OpenClaw 用的 Key 不一致」这种低级但致命的问题。具体操作路径打开 TaoToken 控制台创建一个 API Key。控制台地址是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsole进去后在 API Keys 页面点创建复制出来的 Key 形如sk-xxxxxxxx先存到环境变量里别硬编码进代码。记下 Base URLhttps://taotoken.net/api。注意这个地址不带任何 UTM 参数是纯 API 入口。确认你要用的 Model ID。ClaudeCode 场景下通常用 Claude 系列模型具体 Model ID 以 TaoToken 文档里的模型列表为准文档地址https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc。这里有个关键点Base URL Key Model ID 三件套必须一致。很多长跑失败案例根源就是 ClaudeCode 配了一套、OpenClaw 配了另一套结果 OpenClaw 调度时用的模型和 ClaudeCode 执行时用的模型不是同一个验收标准对不上。环境变量建议这样设Linux/macOS 下写进~/.bashrc或~/.zshrcexport TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODEL_IDclaude-sonnet-4-5Windows 下用 PowerShell$env:TAOTOKEN_API_KEYsk-你的key $env:TAOTOKEN_BASE_URLhttps://taotoken.net/api $env:TAOTOKEN_MODEL_IDclaude-sonnet-4-5设完之后验证一下通道是否通curl -s $TAOTOKEN_BASE_URL/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 500如果返回模型列表 JSON说明通道正常。如果返回 401说明 Key 有问题如果返回连接错误说明 Base URL 写错了。这一步必须在搭编排之前做否则后面所有调试都会被通道问题干扰。为什么要强调「统一」因为长跑系统里OpenClaw 的编排层也要调用模型来做任务拆分、验收判断、返工决策。如果编排层和执行层走不同通道一旦其中一个通道抖动你会看到「ClaudeCode 明明改完了但 OpenClaw 判断不了验收结果」这种诡异现象。统一到 TaoToken 一条通道排查问题时只需要看一个地方。另外长跑任务建议在 TaoToken 控制台里给这个 Key 设置合理的额度上限和告警避免夜里跑飞了把额度烧光。这个在控制台的 Key 管理页面可以配。通道打通之后就可以进入编排配置了。3. 可复制配置任务队列、验收钩子与返工触发这一节是全文最核心的部分给出可以直接复制的配置。整个系统分三层任务队列OpenClaw 管、执行配置ClaudeCode 管、验收与返工OpenClaw 管。我按文件路径逐个给。3.1 OpenClaw 编排配置任务队列与状态机OpenClaw 的编排配置建议放在项目根目录的openclaw/orchestrator.toml。这个文件定义任务队列、阶段划分、验收钩子和返工触发条件。# openclaw/orchestrator.toml [model] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY model_id claude-sonnet-4-5 timeout_seconds 120 max_retries 3 [queue] # 任务队列每个任务是一个待推进的工程需求 store openclaw/state/tasks.jsonl poll_interval_seconds 30 max_concurrent_tasks 1 [stages] # 阶段划分需求 - 拆分 - 执行 - 验收 - 返工/完成 order [intake, plan, execute, verify, rework, done] [execute] # 执行层交给 ClaudeCode worker claudecode command claude args [--print, --output-format, json] workdir ./repo max_turns_per_task 40 [verify] # 验收钩子独立于 coder机器可判断 hooks [ lint, typecheck, unit_test, diff_review ] lint_cmd npm run lint typecheck_cmd npm run typecheck unit_test_cmd npm test -- --runInBand diff_review_cmd python3 openclaw/hooks/diff_review.py [rework] # 返工触发条件 max_attempts 3 on_failure requeue escalate_after 3 escalate_channel feishu backoff_seconds [60, 300, 900] [notify] on_done feishu on_escalate feishu summary_cron 0 8 * * *这份配置里几个关键字段解释一下[model]段把模型调用统一指向 TaoToken 的 Base URLapi_key_env指向环境变量避免 Key 写死在文件里。timeout_seconds和max_retries是长跑必须的防止单次调用卡死拖垮整个队列。[queue]段定义任务队列的存储位置。用 JSONL 格式每行一个任务方便追加和恢复。max_concurrent_tasks 1是刻意的长跑系统第一版不要并发并发会让状态管理复杂度爆炸。[stages]段是状态机的核心。任务从intake进来经过plan拆分execute执行verify验收失败进rework成功进done。每个阶段的状态都持久化进程重启后能从上次状态恢复。[verify]段是验收钩子这是整个系统最关键的设计。验收必须独立于 coder所以这里列了四个机器可判断的钩子lint、typecheck、unit_test、diff_review。前三个是标准工程检查diff_review是一个自定义脚本用来判断这次改动是否真的解决了任务描述里的问题而不是改了一堆无关文件。[rework]段定义返工触发条件。max_attempts 3表示同一个任务最多返工 3 次超过就escalate到人工。backoff_seconds [60, 300, 900]是退避策略第一次失败等 60 秒重试第二次等 5 分钟第三次等 15 分钟避免短时间内反复撞同一个错误。3.2 ClaudeCode 执行配置指向统一通道ClaudeCode 的配置放在项目根目录的.claude/settings.json。这个文件让 ClaudeCode 走 TaoToken 通道并且限制它在长跑场景下的行为。{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: ${TAOTOKEN_API_KEY}, ANTHROPIC_MODEL: claude-sonnet-4-5 }, permissions: { allow: [ Read, Edit, Bash(npm run lint), Bash(npm run typecheck), Bash(npm test:*), Bash(git diff:*), Bash(git status:*) ], deny: [ Bash(git push:*), Bash(rm -rf:*), Bash(curl:*) ] }, maxTurns: 40, autoApprove: false }这里有几个设计要点env段把ANTHROPIC_BASE_URL指向 TaoToken 的 API 地址ANTHROPIC_API_KEY引用环境变量。这样 ClaudeCode 的所有模型调用都走统一通道和 OpenClaw 编排层用的是同一个 Key、同一个 Base URL、同一个 Model ID三件套一致。permissions.allow里只放读、改、跑测试、看 diff 这些执行层需要的操作。permissions.deny里禁掉git push、rm -rf、curl这些危险操作。长跑系统里ClaudeCode 是自动执行的没有人盯着所以权限必须收紧。特别是git push绝对不能让自动 worker 直接推代码必须经过人工确认。maxTurns 40限制单个任务的最大轮次防止 ClaudeCode 在一个任务上无限循环。autoApprove false表示不自动批准所有操作配合 OpenClaw 的验收钩子使用。3.3 验收钩子脚本diff_review.pydiff_review.py是自定义验收钩子放在openclaw/hooks/diff_review.py。它的作用是判断 ClaudeCode 这次的改动是否真的针对任务描述而不是乱改。# openclaw/hooks/diff_review.py import subprocess import sys import json import os def get_diff(): result subprocess.run( [git, diff, --stat, HEAD], capture_outputTrue, textTrue ) return result.stdout def get_changed_files(): result subprocess.run( [git, diff, --name-only, HEAD], capture_outputTrue, textTrue ) return [f for f in result.stdout.strip().split(\n) if f] def main(): task_file os.environ.get(OPENCLAW_TASK_FILE, ) if not task_file or not os.path.exists(task_file): print(json.dumps({pass: False, reason: no task file})) sys.exit(1) with open(task_file) as f: task json.load(f) changed get_changed_files() if not changed: print(json.dumps({pass: False, reason: no changes})) sys.exit(1) # 改动文件数超过阈值判定为发散 if len(changed) task.get(max_files, 10): print(json.dumps({ pass: False, reason: ftoo many files changed: {len(changed)} })) sys.exit(1) # 检查是否改了任务范围外的目录 allowed_dirs task.get(allowed_dirs, [src, tests]) for f in changed: if not any(f.startswith(d) for d in allowed_dirs): print(json.dumps({ pass: False, reason: fout of scope: {f} })) sys.exit(1) print(json.dumps({pass: True, changed: changed})) if __name__ __main__: main()这个脚本做三件事检查有没有改动、检查改动文件数是否超阈值、检查改动是否在允许的目录范围内。任何一项不通过验收就失败任务进入返工。这样能有效防止 ClaudeCode 在长跑中「越改越远」。3.4 任务队列文件格式任务队列用 JSONL每行一个任务放在openclaw/state/tasks.jsonl{id: task-001, stage: intake, desc: 重构 user 模块的鉴权逻辑补齐单元测试, allowed_dirs: [src/user, tests/user], max_files: 8, attempts: 0, created_at: 2025-01-01T10:00:00Z} {id: task-002, stage: intake, desc: 修复 order 模块的并发下单 bug, allowed_dirs: [src/order, tests/order], max_files: 5, attempts: 0, created_at: 2025-01-01T10:05:00Z}每个任务带allowed_dirs和max_files这两个字段会被diff_review.py读取用来判断改动是否发散。attempts记录返工次数超过max_attempts就升级人工。配置给完了接下来验证这套东西能不能跑起来。4. 验证请求与成功结果跑一轮完整闭环配置写完先别急着上真实任务用一个最小任务验证整条链路。我建议用一个「改一个函数 补一个测试」的小任务跑通 intake → plan → execute → verify → done 全流程。4.1 启动 OpenClaw 编排器cd /path/to/your/project export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_MODEL_IDclaude-sonnet-4-5 openclaw run --config openclaw/orchestrator.toml --once--once表示只跑一轮方便调试。跑起来后OpenClaw 会读tasks.jsonl取第一个stage intake的任务进入plan阶段。4.2 观察 plan 阶段输出plan 阶段 OpenClaw 会调用模型把任务拆成子步骤输出类似{ task_id: task-001, subtasks: [ {step: 1, action: read src/user/auth.ts, type: read}, {step: 2, action: refactor validateToken function, type: edit}, {step: 3, action: add unit test for validateToken, type: edit}, {step: 4, action: run npm test -- tests/user, type: verify} ] }这个拆分结果会写回任务状态然后进入 execute 阶段。4.3 execute 阶段ClaudeCode 执行OpenClaw 调用 ClaudeCode命令是配置里定义的claude --print --output-format json openclaw/state/task-001-prompt.txtClaudeCode 读 repo、改代码、跑局部验证输出 JSON 结果。这一步的输出会被 OpenClaw 捕获写入任务状态。4.4 verify 阶段验收钩子依次执行验收钩子按配置顺序跑npm run lint npm run typecheck npm test -- --runInBand python3 openclaw/hooks/diff_review.py每个钩子返回 0 表示通过非 0 表示失败。全部通过任务进入done任何一个失败任务进入rework。成功的输出长这样{ task_id: task-001, stage: done, attempts: 1, verify_results: { lint: pass, typecheck: pass, unit_test: pass, diff_review: pass }, changed_files: [src/user/auth.ts, tests/user/auth.test.ts], completed_at: 2025-01-01T10:15:00Z }看到这个输出说明整条链路通了。任务从 intake 到 doneClaudeCode 执行了一次验收全部通过没有返工。4.5 验证返工路径光验证成功路径不够还要验证失败返工。故意在任务里加一个会失败的测试或者把allowed_dirs设成一个 ClaudeCode 必然会越界的范围观察返工是否触发。返工时的输出{ task_id: task-001, stage: rework, attempts: 1, verify_results: { lint: pass, typecheck: pass, unit_test: fail, diff_review: pass }, failure_reason: unit_test failed: validateToken returns undefined for expired token, next_action: requeue with failure context, backoff_seconds: 60 }OpenClaw 会把failure_reason作为上下文重新塞给 ClaudeCode让它针对这个失败点修。这就是「失败返工」的闭环。返工次数达到max_attempts 3后任务升级到人工通过escalate_channel发通知。4.6 验证长跑不中断最后验证长跑。往tasks.jsonl里塞 5 个任务去掉--once让 OpenClaw 持续跑openclaw run --config openclaw/orchestrator.toml观察它是否按队列顺序逐个推进每个任务走完 intake → plan → execute → verify → done/rework。中途可以手动 kill 进程再重启验证状态是否能从tasks.jsonl恢复。如果重启后能从上次中断的任务继续说明状态持久化没问题长跑基础就打好了。跑通这一轮你就有了一个最小可用的长跑编码系统。接下来是排障。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth长跑系统搭起来后报错基本集中在通道、配置、状态三类。下面按真实报错逐个排查。5.1 401 Unauthorized最常见。表现是 ClaudeCode 或 OpenClaw 调用模型时返回 401。原因通常是三个Key 没设、Key 设错、Key 和 Base URL 不匹配。排查步骤echo $TAOTOKEN_API_KEY echo $TAOTOKEN_BASE_URL curl -s $TAOTOKEN_BASE_URL/v1/models -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 200如果echo出来是空的说明环境变量没生效检查是不是写在了错误的 shell 配置文件里。如果 curl 返回 401去 TaoToken 控制台确认 Key 是否有效、是否被禁用。如果 curl 正常但 ClaudeCode 报 401检查.claude/settings.json里的ANTHROPIC_API_KEY是否正确引用了环境变量注意 JSON 里不能用${VAR}这种 shell 语法要用实际值或者确认 ClaudeCode 支持环境变量插值。5.2 local proxy failed这个报错通常出现在 ClaudeCode 尝试走本地代理时。表现是local proxy failed to connect或类似。原因一般是 ClaudeCode 配置里残留了旧的代理设置或者环境变量里有HTTP_PROXY/HTTPS_PROXY指向了一个不存在的本地端口。排查env | grep -i proxy如果有输出且指向的端口没有服务在监听就会报这个错。解决办法是清掉这些环境变量unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy然后确认.claude/settings.json里没有额外的 proxy 配置。TaoToken 的 API 地址是直连的不需要走任何本地代理。5.3 reading choices 报错这个报错通常长这样error reading choices: unexpected end of JSON input或cannot read property choices of undefined。原因是模型返回的响应格式不符合预期OpenClaw 或 ClaudeCode 在解析时拿不到choices字段。常见触发场景是通道返回了错误页 HTML 而不是 JSON或者响应被截断。排查curl -s $TAOTOKEN_BASE_URL/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-5,messages:[{role:user,content:hi}],max_tokens:10} | head -c 500如果返回的是 HTML 或错误信息说明通道有问题检查 Base URL 是否写成了带路径的地址。正确的 Base URL 是https://taotoken.net/api不要自己加/v1后缀具体路径由 SDK 拼接。如果返回正常 JSON 但 ClaudeCode 还报这个错检查max_tokens是否设得太小导致响应被截断。5.4 OAuth 相关报错ClaudeCode 某些版本会尝试 OAuth 登录流程报错形如OAuth token expired或failed to refresh OAuth token。长跑场景下OAuth 是麻烦来源因为 token 会过期而自动系统没人手动刷新。解决办法是用 API Key 而不是 OAuth。在.claude/settings.json里明确配置ANTHROPIC_API_KEY并且确认没有启用 OAuth 相关的登录配置。如果 ClaudeCode 启动时仍然尝试 OAuth检查是否有~/.claude/credentials.json之类的缓存文件清掉它强制走 API Key。5.5 三件套一致性检查上面所有报错排查到最后都要回到「Base URL Key Model ID」三件套是否一致。建议写一个检查脚本每次启动前跑一遍#!/bin/bash # openclaw/check_env.sh set -e : ${TAOTOKEN_API_KEY:?TAOTOKEN_API_KEY not set} : ${TAOTOKEN_BASE_URL:?TAOTOKEN_BASE_URL not set} : ${TAOTOKEN_MODEL_ID:?TAOTOKEN_MODEL_ID not set} echo Base URL: $TAOTOKEN_BASE_URL echo Model ID: $TAOTOKEN_MODEL_ID echo Key prefix: ${TAOTOKEN_API_KEY:0:8}... curl -sf $TAOTOKEN_BASE_URL/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY /dev/null \ echo channel OK \ || { echo channel FAILED; exit 1; }把这个脚本挂在 OpenClaw 启动前通道有问题直接拦住不让它带着坏配置跑长任务。5.6 状态文件损坏长跑系统另一个常见问题是tasks.jsonl被写坏比如进程被 kill 时正在写一行导致最后一行 JSON 不完整。OpenClaw 读取时解析失败整个队列卡住。排查tail -1 openclaw/state/tasks.jsonl | python3 -m json.tool如果报 JSON 解析错误说明最后一行坏了。手动删掉最后一行或者写一个修复脚本把不完整的行截掉。更稳妥的做法是在 OpenClaw 配置里开启原子写每次更新任务状态时先写临时文件再 rename避免半行写入。排障这部分核心就一句话通道问题查三件套状态问题查 JSONL权限问题查 settings.json。把这三类覆盖住长跑基本不会因为环境问题中断。6. 语义一致 CTA把通道和编排都落到 TaoToken 上整套系统跑通之后你会发现真正决定长跑稳定性的不是 ClaudeCode 有多聪明而是通道稳不稳、编排清不清晰、验收严不严格。ClaudeCode 负责把代码写好OpenClaw 负责把任务推进下去而这两者之间的模型调用统一走 TaoToken 的 Key/API 通道才能保证长跑过程中不会因为通道问题断线。如果你现在正在搭这套系统建议按这个顺序落地先把 TaoToken 的 Key 建好确认 Base URL、Key、Model ID 三件套一致用check_env.sh验证通道。控制台在https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsoleAPI Keys 页面创建即可。接入细节看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc里面有各语言的接入示例。通道通了之后把orchestrator.toml和.claude/settings.json按第 3 节的配置复制进去先用一个小任务跑--once验证 intake → plan → execute → verify → done 全流程。成功路径通了再故意制造一次失败验证返工路径。两条路径都通再上真实任务队列。如果你还在选模型阶段想先对比不同模型在编码任务上的表现可以直接用模型对话页面测一测https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentchat。同一个任务描述换不同 Model ID 跑一遍看哪个在你这套验收钩子下通过率最高再把它写进orchestrator.toml的model_id。如果你打算把这套长跑系统长期用于日常编码和 Agent 任务建议直接上 Coding Plan额度和通道都更稳适合挂后台持续跑https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan。长跑系统最怕的就是跑到一半额度没了或者通道限流Coding Plan 在这块比按量调用省心。最后说一个我踩过的坑别一上来就追求全自动。第一版就做「单任务、单 worker、四个验收钩子、三次返工上限」跑稳了再考虑并发、多 worker、复杂状态机。长跑系统的价值不在于一次能跑多少任务而在于每一轮结束后系统都知道下一步该干嘛。这个「知道下一步」的能力比让一个 agent 一直 self-loop 重要得多。把 OpenClaw 的编排、ClaudeCode 的执行、TaoToken 的通道这三层搭好你的编码 Agent 就能从「单轮工具」变成「长期 worker」夜里跑、失败修、修完验、验完推真正不中断地推进下去。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询