十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

将 LongHorizon-Harness 的检查点接到 TaoToken 后端

将 LongHorizon-Harness 的检查点接到 TaoToken 后端 1. 从「失败清零」到「可续跑」Harness 的检查点卡在哪一步你在本地把 LongHorizon-Harness 跑起来任务拆到第 40 步时终端抛出一个连接超时前面的抓取结果全在内存里进程一退进度归零。这时候你会发现检查点机制写得再漂亮只要模型后端每次连接的鉴权和地址不一致恢复链路就断在第一跳。所以先把后端入口固定下来到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_checkpoint 申请一个 Key后面所有 Harness 的执行步骤、验证步骤、恢复步骤都走同一个 Base URL检查点里记录的base_url才不会今天记 A、明天跑 B。LongHorizon-Harness 这类长任务框架本质上是给现成 agent 套一层执行循环规划 → 执行 → 验证 → 落检查点或回滚 → 继续循环直到目标达成。它不训练模型也不替换 Claude Code、Codex 这些执行体它管的是这几十小时怎么不断电。原文强调过一点每一步用全新上下文执行避免前文污染每一步只接受已验证的进度失败不从头再来从最近一个检查点恢复。这三个特性听起来是调度问题实际落地时会立刻变成配置问题——因为全新上下文执行意味着每一步都要重新建立一次模型连接如果这一步的连接配置散落在环境变量、项目配置、CLI 参数三个地方那么你恢复出来的第 41 步和第 40 步极可能不是同一个后端。工作流编排开发者最容易踩的坑不是逻辑写错而是状态漂移检查点文件里写着用自己的 key 跑了 40 步恢复时 shell 里 export 的是另一个 key鉴权通过但落到了不同的账户或不同的模型别名上验证器判定结果不一致于是整个恢复流程判为失败又回到失败清零的原点。这篇就以把 Harness 的检查点稳定接到 TaoToken 后端为主线给出一套可复制、可恢复、可审计的配置。先明确三个事实后面所有命令都基于它们模型后端统一走https://taotoken.net/api这是 Base URL不加任何查询参数工具配置里填的就是它密钥统一用环境变量注入代码里只出现占位符YOUR_API_KEY不把 key 写进检查点正文检查点文件里要冗余记录当次执行所用的 Base URL 和模型名恢复前先做一致性校验。2. 先拿 Key、再定 Base URLTaoToken 接入的最小准备不管你的 Harness 最终调用的是 Claude Code、Codex 还是自己封的 OpenAI 兼容客户端接入顺序都是一样的先有 Key再配 Base URL最后才动 Harness 的调度配置。Key 在控制台创建地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_key 创建时按用途拆开长任务执行一个 key、验证环节一个 key、调试另一个 key。拆开的好处是当 Harness 跑了几十小时之后你要审计到底哪一步调用了什么可以直接按 key 维度看用量归属而不是所有步骤混在一张账单里。拿到 Key 之后先在 shell 里做最小验证不要一上来就改 Harness 的调度器。用一个最普通的 OpenAI 兼容调用确认网络和鉴权都通export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYYOUR_API_KEY curl -sS $TAOTOKEN_BASE_URL/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json | head -c 400这一步的目的是把网络层 / 鉴权层 / 模型层三个可能出错的环节先分开。如果这里返回 401问题在 Key返回 404通常是 Base URL 多写了/v1或者少写了路径注意https://taotoken.net/api是工具里填的完整前缀不要再拼/v1/v1如果一直超时先检查本机代理和 DNS不要在 Harness 里调参浪费时间。确认连通后把这两个变量写进一个独立的 env 文件便于 Harness 每个子进程都继承到同一份配置# ~/.config/taotoken/harness.env export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYYOUR_API_KEY export TAOTOKEN_DEFAULT_MODELclaude-sonnet-4-5 export TAOTOKEN_VERIFY_MODELclaude-haiku-4-5执行长任务前用source加载例如在 Harness 的启动脚本里第一行就写set -a source ~/.config/taotoken/harness.env set a python -m harness run --task tasks/research.yamlset -a的作用是把 source 进来的变量自动 export 给子进程这一点很关键Harness 拆步骤时往往会 fork 新的执行进程如果变量只在当前 shell 里存在子进程拿不到恢复时就会退化成没有配置的默认后端前面 40 步的检查点等于白建。3. Claude Code 三件套settings.json、项目级配置与 CC Switch 的一致性如果你的 Harness 把 Claude Code 当作执行体配置就要按 Claude Code 自身的三层逻辑来组织不能混用。第一层是全局~/.claude/settings.json第二层是项目级.claude/settings.json第三层是运行时的环境变量。三者优先级从低到高Harness 恢复时如果用不同层级的配置就会出现同一份检查点、两条连接路径的问题。全局配置示例{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY, ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4-5, ANTHROPIC_DEFAULT_HAIKU_MODEL: claude-haiku-4-5, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1 } }项目级.claude/settings.json只保留与任务相关的模型选择不要在这里重复写 key避免 Harness 打包检查点时把密钥一并落盘{ env: { ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4-5 }, permissions: { allow: [Bash(python:*), Read, Write] } }至于 CC Switch 这类多配置切换工具它的三件套一般指三份可切换的配置源Claude Code 的settings.json、Codex 的config.toml、以及一份共用的密钥/环境文件。用 CC Switch 做切换本身没问题但接入 Harness 时要保证三件事第一三份配置里的 Base URL 都是https://taotoken.net/api不能用某一份走旧的中转地址第二共用密钥文件只保留一份 key避免切换后实际调用方发生变化第三切换动作不要发生在恢复过程中间否则检查点里的provider字段会和运行时不符。简单说CC Switch 负责的是你想换的时候换Harness 负责它想恢复的时候稳定两者职责不能交叉。Claude Code 这一层的更多细节包括环境变量优先级、模型别名映射、权限白名单写法可以参考官方接入文档https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_cc_doc 文档里的字段名和本文保持一致照着填即可。4. Codex 的 config.toml不要把 ANTHROPIC_* 套过来这是最容易出错的一节。Codex 走的是 TOML 配置体系字段是model_provider/base_url/env_key/wire_api这一套不是ANTHROPIC_*。把 Claude Code 的配置直接复制到 Codex表现通常是配置解析通过但请求打到错误的端点或者鉴权头格式不对报 401 但 key 明明是对的。正确写法示例# ~/.codex/config.toml model gpt-5-codex model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api responses [profiles.longtask] model_provider taotoken model gpt-5-codex approval_policy on-request关键点有三个base_url只写到https://taotoken.net/api不要在后面拼/chat/completions路径由 Codex 自己按wire_api拼接env_key指向环境变量名不写 key 本身Harness 恢复时只要环境变量在鉴权就能重建高位长任务建议单独开 profile把approval_policy设成on-request避免执行体在某一步卡在交互确认上让整个循环超时、误判为步骤失败。验证 Codex 配置是否被正确加载可以先用一次最小调用codex exec --profile longtask reply with the single word: ready如果返回正常说明 Codex 侧已接通。这里要强调一句同一台机器上Claude Code 和 Codex 可以共用同一个环境变量文件但配置文件必须各写各的Claude Code 用 JSON 的ANTHROPIC_*Codex 用 TOML 的model_providers禁止交叉粘贴。Harness 在恢复时按检查点里记录的harness_backend字段选择加载哪一份所以检查点里也要把这一项写清楚。5. 给 Harness 写一个可复现的检查点模块Harness 本身可能有自己的检查点实现但作为编排开发者你至少要知道它落在哪、写了什么、恢复时按什么字段校验。下面是一个可直接运行的最小检查点模块用 OpenAI 兼容客户端调 TaoToken把每一步的状态、摘要、所用后端起止信息都落盘。它不是替代 Harness而是给你一个可对照、可审计的落地样本。# harness_checkpoint.py import hashlib import json import os import time from pathlib import Path from openai import OpenAI BASE_URL os.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api) MODEL os.environ.get(TAOTOKEN_DEFAULT_MODEL, claude-sonnet-4-5) client OpenAI(base_urlBASE_URL, api_keyos.environ[TAOTOKEN_API_KEY]) CKPT_DIR Path(./.harness/checkpoints) CKPT_DIR.mkdir(parentsTrue, exist_okTrue) def digest(step_id: int, payload: dict) - str: raw json.dumps({step: step_id, payload: payload}, sort_keysTrue) return hashlib.sha256(raw.encode(utf-8)).hexdigest()[:16] def save_checkpoint(step_id: int, state: dict, verified: bool) - Path: record { step: step_id, digest: digest(step_id, state), verified: verified, created_at: time.time(), backend: { base_url: BASE_URL, model: MODEL, }, state: state, } path CKPT_DIR / fstep-{step_id:04d}.json path.write_text(json.dumps(record, ensure_asciiFalse, indent2)) return path def latest_verified_checkpoint() - Path | None: files sorted(CKPT_DIR.glob(step-*.json)) for path in reversed(files): record json.loads(path.read_text()) if record.get(verified): return path return None def run_step(step_id: int, instruction: str, state: dict) - dict: # 每一步用全新上下文执行不携带前文消息历史 resp client.chat.completions.create( modelMODEL, messages[ {role: system, content: You are a bounded task executor.}, {role: user, content: instruction}, ], timeout120, ) output resp.choices[0].message.content new_state {**state, last_output: output} save_checkpoint(step_id, new_state, verifiedTrue) return new_state这段代码对应 Harness 循环里的三个关键动作执行用全新消息列表不复用历史、每步结束立刻落检查点、检查点里冗余记录base_url与model。恢复时只要读最后一个verified true的文件即可不需要自己去猜进度。目录结构建议保持稳定方便审计脚本扫描.harness/ ├── checkpoints/ │ ├── step-0038.json │ ├── step-0039.json │ └── step-0040.json ├── audit.log └── resume.json6. 恢复实操从最近一个已验证检查点续跑的三条命令检查点有了恢复命令就不该是重跑一遍。下面三条命令分别对应三种常见恢复场景按实际入口替换命令名即可逻辑是通用的。第一条列出所有检查点确认最近一个已验证步骤在哪。python - PY import json from pathlib import Path for path in sorted(Path(.harness/checkpoints).glob(step-*.json)): rec json.loads(path.read_text()) flag OK if rec.get(verified) else BAD print(f{flag} {path.name} backend{rec[backend][model]} at{rec[backend][base_url]}) PY第二条从指定检查点恢复执行只重做失败的那一步及其后续。set -a source ~/.config/taotoken/harness.env set a python -m harness resume \ --from-checkpoint .harness/checkpoints/step-0040.json \ --task tasks/research.yaml \ --max-retries 3 \ --backend claude-code第三条恢复前做一致性校验避免用新 key 跑旧检查点。python - PY import json import os from pathlib import Path rec json.loads(Path(.harness/checkpoints/step-0040.json).read_text()) expected os.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api) assert rec[backend][base_url] expected, base_url 与当前环境不一致拒绝恢复 print(checkpoint backend consistency: ok) PY第三条命令看起来多余但它是防状态漂移的最后一道闸。很多 Harness 恢复失败的案例根因不是逻辑而是环境A 环境写的检查点B 环境去恢复base_url一样但 key 归属不同验证器给出的判定和之前不一致循环就反复失败。把校验前置能省掉大量排查时间。恢复之后再跑一次审计确认每一步的输入输出都可追溯python -m harness audit \ --dir .harness/checkpoints \ --since 24h \ --output .harness/audit.log审计日志里至少要能看到步骤号、摘要、是否验证通过、所用模型、所用 Base URL 的 host 部分不记录 key。能在事故后回答第 37 步为什么被判定失败你的循环才算真正可运维。7. 排障清单与边界说明把常见故障按层拆开比在 Harness 里加日志更快。鉴权层。401 基本只有三种可能key 没注入进子进程、key 拼写/换行有问题、请求头格式不对。Claude Code 用ANTHROPIC_AUTH_TOKENCodex 用env_key指向的环境变量两者不要互相复制。检查方式是把 Harness 启动脚本里的env | grep -i taotoken打出来确认每个 fork 出来的进程都能看到。路由层。404 通常来自 base_url 拼错典型是https://taotoken.net/api/v1或https://taotoken.net/api/chat/completions。Base URL 就填https://taotoken.net/api路径交给工具自己处理。超时则优先检查本机网络和并发数长任务里一步超时不等于任务失败Harness 应该按重试策略处理而不是直接把整条链判死。状态层。恢复后行为异常先怀疑两件事检查点里记录的模型和当次环境里的模型不一致或者上一步verified为 false 却被当成可恢复点。恢复命令里指定检查点时务必使用最近一个verified true的文件。上下文层。全新上下文执行意味着每一步都看不到前文这对减少污染有好处但也要求检查点里的state字段足够完整——凡是下一步需要的信息都必须显式落盘不能指望模型记得。这是排查恢复后胡干的第一切入点。最后说清楚边界。这层循环解决的是执行的持久性和可恢复性不是能力本身。执行体不会操作的软件套上检查点也不会突然会它在长任务里的价值是把失败清零变成从最近一个已验证点继续。也正因为它控制的是连接、状态和恢复后端配置的一致性才如此关键——把 Base URL 固定成https://taotoken.net/api、把 key 收进环境变量、把检查点写全这三件事做到位几十小时的连续执行才有可复盘的基础。8. 下一步把执行、验证、恢复都统一到同一条链路上如果你正准备把 Harness 的循环接到实际项目上建议按下面的顺序走一遍每一步都有对应的入口可以对照第一想先确认模型侧行为是否符合预期用模型对话页面直接试一次长指令观察返回结构https://taotoken.net/models/detail/chat?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_chat 。第二长任务涉及大量步骤和并发先了解 Coding Plan 的配额与限流规则再决定检查点间距https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_plan 。第三按用途分别创建 key把执行 key、验证 key、调试 key 分开https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_keys 。第四回到 Claude Code 接入文档核对settings.json字段与环境变量优先级https://taotoken.net/doc/ClaudeCodeAnthropic?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_doc 。把官网入口留在这里方便你按需回看https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentlonghorizon_footer 。执行这条链路时记住三句话Base URL 固定写https://taotoken.net/apikey 只放环境变量占位符用YOUR_API_KEY检查点必须冗余记录后端信息恢复前先校验。做到这三点Harness 的检查点 / 恢复才真正接得上长任务也才有可能从干几分钟走到连续扛几十小时。
返回列表