1. 从一次「假完成」说起:Agent Harness 多 Worker 协作里的 Done gate 误判
如果你正在用 Agent Harness 跑多 Worker 协作任务,大概率遇到过这种让人血压升高的场景:看板上任务已经躺在 Done 列,Issue 被自动关闭,status.json里明晃晃写着"status": "done",可你点进线上环境一看,问题原封不动,用户还在催。更诡异的是,Worker 进程居然还活着,但stdout已经二十分钟没吐一个字。
这就是典型的Done gate 误判 + ledger 状态漂移。Agent Harness 本身是一套把复杂工程任务拆给多个 Worker 并行执行的编排框架,Worker 负责改代码、跑测试、发 PR,Supervisor 负责调度和判定完成。问题出在「判定完成」这一步:很多默认配置下,Harness 只认 Worker 上报的status.json,而不去核对 ledger 里有没有对应的阶段完成事件,也不校验 commit、PR、测试报告这些硬证据。于是 Worker 只要本地改了几个文件、把状态一写,任务就被判成完成了。
status.json在这里的角色非常关键——它是整个观测入口。你可以把它理解成 Worker 交给 Supervisor 的「作业本封面」,上面写着「我做完了」。但封面写得漂亮不代表作业真做完了,所以我们需要把status.json、ledger、git 记录、线上 readback 这几路证据串起来交叉验证。这篇就围绕这个思路,给出可复制的 TaoToken 统一 Key/API 通道配置骨架,并完整演示一次从异常复现到 Done gate 校验通过的排查动作。
适合谁看:正在自建或维护 Agent Harness、被假完成和状态漂移坑过的工程师;想把多 Worker 协作的完成判定做扎实的团队。下面所有配置和命令都可以直接抄。
2. 用 TaoToken 统一 Key 打通 Worker 与 Supervisor 的 API 通道
多 Worker 协作最烦的一件事是 Key 管理。每个 Worker 一套 Key,轮换、限流、审计全是坑,而且一旦某个 Worker 的 Key 失效,它的请求会静默失败,status.json却照样上报 done——这本身就是假完成的一个隐蔽来源。我的做法是用 TaoToken 做统一 API 通道,所有 Worker 和 Supervisor 走同一个 Base URL,Key 集中管理。
TaoToken 是一个兼容 OpenAI/Anthropic 接口规范的模型 API 聚合通道,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。它的价值在于:你不需要给每个 Worker 单独配一套上游凭证,只要在 Harness 侧统一注入 Base URL 和 Key,Worker 拿到的就是稳定通道。这样当某个 Worker 因为网络抖动或额度问题请求失败时,错误会明确暴露在 Supervisor 的日志里,而不是被吞掉后伪装成完成。
具体到配置,Harness 里通常有两处需要改:一处是 Worker 侧的模型调用配置(settings.json),一处是 Supervisor 或 CLI 工具侧的config.toml。我建议把 Base URL 和 Key 都抽成环境变量,配置文件里只引用变量名,避免 Key 硬编码进仓库。下面两节给出可直接复制的片段。
需要提前准备的只有两样:一个 TaoToken 的 API Key(在控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 里创建),以及确认你的 Harness 版本支持自定义 Base URL。Key 的创建入口在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,生成后先复制到剪贴板,下一步就要用。
3. 可复制配置:settings.json 与 config.toml 片段
这一节是全文最该动手抄的部分。先看 Worker 侧的settings.json。假设你的 Harness 把每个 Worker 的配置放在~/.agent-harness/workers/<worker-id>/settings.json,那么统一通道的写法如下:
{ "model_provider": { "base_url": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "default_model": "claude-sonnet-4-5", "timeout_seconds": 120, "max_retries": 3 }, "worker": { "id": "worker-03", "heartbeat_interval_seconds": 60, "stdout_silence_threshold_seconds": 900, "step_timeout_seconds": 1800 }, "done_gate": { "require_ledger_event": true, "require_commit": true, "require_pr": true, "require_test_report": true, "require_readback": true } }这里有几个参数直接对应后面的排障。stdout_silence_threshold_seconds设成 900,就是 15 分钟没输出就判定卡死;step_timeout_seconds是单步 30 分钟上限。done_gate那一段是核心,把 ledger 事件、commit、PR、测试报告、readback 全部设为必选,缺一不可。注意api_key_env引用的是环境变量名,真正的 Key 通过export TAOTOKEN_API_KEY=你的Key注入,不要写进文件。
再看 Supervisor 或 CLI 侧的config.toml,路径通常在~/.agent-harness/config.toml:
[api] base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model_id = "claude-sonnet-4-5" [supervisor] poll_interval_seconds = 30 ledger_path = "./ledger/events.jsonl" status_path = "./runtime/status.json" [done_gate] enforce = true evidence_order = ["user_feedback", "readback", "git_pr", "ledger", "test_report", "deploy_log", "status_json"]evidence_order这一行是我踩过坑之后加的。它定义了证据可信度排序,Supervisor 在判定完成时按这个顺序逐项核对,status_json排在最后——也就是说,status.json只是参考,绝不是唯一依据。model_id必须和 Worker 侧default_model保持一致,否则会出现 Worker 用 A 模型、Supervisor 用 B 模型校验的错位。
三件套对齐检查:Base URL 统一为https://taotoken.net/api,Key 统一走TAOTOKEN_API_KEY环境变量,Model ID 统一为claude-sonnet-4-5。这三样在 Worker 和 Supervisor 两侧必须完全一致,任何一处不一致都会导致请求失败被静默吞掉,进而诱发假完成。
4. 验证请求:从异常复现到 Done gate 校验通过
配置改完必须验证,否则你只是换了个地方埋雷。这一节演示一次完整动作:先人为复现假完成,再用 Done gate 拦截,最后修正到校验通过。
第一步,复现异常。手动把某个 Worker 的status.json改成 done,但不产生任何 ledger 事件:
echo '{"worker_id":"worker-03","status":"done","step":"deploy"}' \ > ./runtime/status.json此时如果你直接查看板,任务可能已经显示 Done。但用下面的命令查 ledger,会发现根本没有对应的阶段完成事件:
grep '"event":"step_completed"' ./ledger/events.jsonl | tail -5输出为空,说明 ledger 里没有 deploy 步骤的完成记录。这就是假完成的铁证——status.json说 done,ledger 说没这回事。
第二步,触发 Done gate 校验。调用 Supervisor 的校验接口(不同 Harness 命令名可能不同,核心是走校验逻辑):
agent-harness supervisor verify --task-id T-1024 --strict预期返回类似:
{ "task_id": "T-1024", "gate_result": "rejected", "reason": "ledger_event_missing", "missing_evidence": ["ledger:step_completed:deploy", "git:commit", "pr:link"], "status_json_ignored": true }看到gate_result: rejected就对了,说明 Done gate 生效,status.json被正确忽略。这一步是整个方案的关键验证点:如果这里返回accepted,说明你的done_gate.enforce没打开,或者require_ledger_event没设成 true。
第三步,补全证据后重新校验。让 Worker 真正执行 commit、PR、测试、部署和 readback,ledger 会写入对应事件。再次校验:
agent-harness supervisor verify --task-id T-1024 --strict这次返回:
{ "task_id": "T-1024", "gate_result": "accepted", "evidence_chain": { "user_feedback": "resolved", "readback": "ok", "git_pr": "PR#88 merged", "ledger": "step_completed:deploy", "test_report": "pass_rate=100%" } }gate_result: accepted且evidence_chain五项齐全,才算真正完成。你可以把这两次校验的返回结果对比着看,差异一目了然。实测下来,这套流程能把绝大多数假完成挡在 Done 之前。
5. 本篇常见错排查:401、local proxy failed 与 reading choices
配置和验证跑通后,剩下的坑基本集中在请求层。下面按真实报错逐个拆。
401 Unauthorized。最常见的原因是TAOTOKEN_API_KEY没导出,或者导出在了错误的 shell 会话里。检查:
echo $TAOTOKEN_API_KEY | head -c 8如果输出为空,说明环境变量没生效。注意 Worker 如果是通过 systemd 或容器启动的,环境变量要在对应的 service 文件或 compose 里注入,光在交互式 shell 里 export 是不够的。另外确认 Key 没有多余空格或换行。
local proxy failed / connection refused。这个报错通常不是 TaoToken 侧的问题,而是本机或容器网络配置导致请求发不出去。先确认 Base URL 拼写正确,必须是https://taotoken.net/api,不要多加/v1或漏掉/api。再用 curl 直接探一下通道:
curl -sS -o /dev/null -w "%{http_code}\n" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ https://taotoken.net/api/models返回 200 说明通道正常,问题在 Harness 配置;返回 000 或超时,检查本机 DNS 和出站规则。
reading choices 报错(如cannot read property 'choices' of undefined)。这是响应结构不符合预期导致的,根因往往是 Model ID 写错或 Base URL 指向了不兼容的端点。核对三件套:Base URL、Key、Model ID 是否在 Worker 和 Supervisor 两侧完全一致。如果用的是 Claude Code 类工具,还要确认它走的是 Anthropic 兼容路径,模型名要和通道支持的列表匹配,可以到模型对话页 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 先手动发一条消息验证模型可用。
OAuth 相关报错。如果你用的是 Claude Code 或 Codex 这类带 OAuth 的 CLI,报 OAuth 失败通常是因为它默认走官方登录态,而你要切到统一通道。以 Codex 为例,需要改~/.codex/auth.json,把认证方式从 OAuth 切到 API Key:
{ "auth_mode": "api_key", "api_key": "env:TAOTOKEN_API_KEY", "base_url": "https://taotoken.net/api" }改完重启 CLI。Claude Code 侧则是在settings.json里配置ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,同样指向统一通道。这类工具一旦出现 OAuth 报错,先确认是不是还在用旧的登录态。
排障时如果拿不准,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 有完整的端点说明,对照着核一遍比瞎试快得多。
6. 把 Done gate 做成长期机制:Coding Plan 与回归测试
单次排查解决的是眼前问题,要让 Agent Harness 长期稳定,得把 Done gate 和回归测试固化成机制。我现在的做法是:每次 Harness 版本更新,自动跑一遍回归测试,覆盖假完成、Worker 卡死、状态漂移、证据链缺失、业务目标未达成这五类场景。测试用 pytest 写,模拟 Worker 只改本地文件就上报 done,断言 Done gate 必须返回 rejected。
对于长期跑编码和 Agent 任务的团队,TaoToken 的 Coding Plan 在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 提供了更适合持续调用的通道方案,配合统一 Key 能把多 Worker 的额度管理和审计一起收拢。Claude Code 接入的完整配置可以参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite ,里面有 Base URL、Key、Model ID 三件套的对照写法。
最后留一个实用习惯:每周抽 10% 的已完成任务,人工核对status.json、ledger、git 记录和线上 readback 是否一致。自动化能挡住大部分假完成,但人工抽查是最后一道兜底。把status.json当观测入口而不是判定依据,这个观念转变过来,Done gate 才算真正立住了。