Agent Harness、Loop与Graph:AI Agent开发中的三重境界,你理解了吗?
1. 从一次 Agent 失控说起Harness、Loop、Graph 到底各管什么如果你正在搭 Agent 系统大概率遇到过这种场面模型在本地 Notebook 里跑得好好的一旦接上真实文件系统、真实 API、真实审批流就开始丢状态、重复调用、无限重试甚至在没有完成任务时自信地说“已完成”。问题往往不在模型本身而在于你把三层不同的工程决策混成了一件东西。Agent Harness、Loop、Graph 是 AI Agent 开发中的三重境界分别回答三个问题模型在什么环境里干活Harness、干完一轮之后系统怎么判断继续还是停Loop、多个步骤之间允许谁在什么时候运行Graph。一句话概括就是环境 → 反馈 → 流程。三者不是同义词也不能互相替代。Harness 丢了状态Graph 画得再漂亮也没用Loop 没有证据和停止规则只会持续烧钱Graph 缺失时多 Specialist 协作会变成一团乱麻。这篇面向正在搭建 Agent 系统的开发者交付可复制的 Harness 配置模板、Loop 调度伪代码与 Graph 编排示例并给出逐层验证 Agent 行为是否符合预期的具体检查动作。你可以边读边对照自己的项目看看到底卡在哪一层。2. TaoToken 前置准备给 Harness 一个稳定的模型入口在写 Harness 之前先把模型入口固定下来。Agent 系统最怕的就是模型调用层不稳定——今天换个 endpoint明天换个 KeyTrace 全乱。我习惯把模型访问统一收敛到一个兼容 OpenAI 协议的入口这样 Harness 里的 Model Routing、Retry、Budget 都能围绕同一套配置写。TaoToken 提供的就是这样一个统一入口官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 。它的作用是让你在 Harness 里用一套 Base URL Key Model ID 就能切换不同模型而不用改业务代码。对 Agent 开发来说这一点很关键你的 Loop 和 Graph 逻辑不应该和某个具体模型绑定。先拿到 API Key。进入控制台创建密钥https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建后复制保存后面 Harness 配置里要用。如果你还不确定该选哪个模型可以先在模型对话页面试一下https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 确认工具调用、长上下文表现符合预期再写进 Harness。这里要强调一个原则Harness 里的模型配置必须是声明式的不能散落在代码各处。下面是一个最小可用的环境变量模板你可以直接复制到.env或 CI Secret 里# .env —— Harness 模型入口配置 TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的密钥 TAOTOKEN_MODEL_IDclaude-sonnet-4-5 TAOTOKEN_TIMEOUT_MS60000 TAOTOKEN_MAX_RETRY2为什么把 Timeout 和 Max Retry 也放进 Harness 配置因为它们属于执行控制层不是业务逻辑。Loop 里的重试策略应该建立在 Harness 的底层重试之上而不是混在一起。底层负责网络抖动上层负责语义失败两者分开排障时才不会互相甩锅。如果你打算长期跑编码类 Agent建议直接看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 它更适合多 Session、长任务的场景。接入细节可以对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。Claude Code 用户可以直接参考 Anthropic 接入页https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 。3. 可复制配置Harness 模板 Loop 伪代码 Graph 编排这一节是全文的核心三层各给一份能直接抄的片段。先说 Harness。Harness 的本质是“模型之外的一切”所以配置要覆盖上下文注入、行动界面、持久化、执行控制、安全治理、可观测性六块。下面是一份 JSON 配置模板路径放在config/harness.json{ harness_version: 1.0, model: { base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model_id: claude-sonnet-4-5, timeout_ms: 60000, max_retry: 2 }, context_injection: { system_prompt_file: prompts/system.md, skills_dir: skills/, retrieval_top_k: 5 }, action_surfaces: { tools: [read_file, write_file, run_shell, http_get], sandbox: workspace/, allowlist: [*.py, *.md, *.json] }, persistence: { checkpoint_dir: .agent/checkpoints, progress_file: .agent/progress.md, git_tracking: true }, execution_control: { budget_usd: 2.0, max_steps: 40, approval_gate: [write_file, run_shell] }, observability: { trace_dir: .agent/traces, log_tool_io: true } }这份配置里approval_gate是关键写文件和跑 Shell 必须人工确认避免 Agent 在生产环境乱来。progress_file配合checkpoint_dir解决跨 Session 丢状态的问题——每个新 Context 先读 progress再决定下一步。接着是 Loop 调度伪代码。Loop 的核心不是while True而是“触发 → 目标 → 状态 → 行动策略 → 证据 → 反馈 → 停止规则”。下面这段伪代码可以直接翻译成 Python# loop_scheduler.py —— 带证据的验证循环 def run_loop(harness, task, max_attempts3): state harness.load_state(task.id) for attempt in range(max_attempts): result harness.invoke_model(task, state) if result.tool_calls: observation harness.execute_tools(result.tool_calls) state harness.update_state(state, observation) continue evidence harness.run_grader(result.output) if evidence.passed: harness.persist(state, statussuccess) return result.output feedback evidence.summarize_failure() state harness.update_state(state, feedback) if harness.budget_exhausted(): harness.escalate_to_human(task, state) return None harness.escalate_to_human(task, state) return None注意run_grader必须是确定性的跑测试、校验 Schema、检查链接可达而不是再问一遍模型“你觉得对吗”。写作者和评分者共享盲点这是最常见的坑。最后是 Graph 编排示例。用 LangGraph 风格写一个“研究 → 校验 → 发布”的图# graph_orchestrator.py —— 显式控制流 from langgraph.graph import StateGraph, END def build_graph(): g StateGraph(AgentState) g.add_node(research, research_node) g.add_node(verify, verify_node) g.add_node(revise, revise_node) g.add_node(publish, publish_node) g.add_node(human_gate, human_review_node) g.set_entry_point(research) g.add_edge(research, verify) g.add_conditional_edges(verify, route_after_verify, { pass: human_gate, fail: revise, max_retry: END }) g.add_edge(revise, verify) g.add_conditional_edges(human_gate, route_after_human, { approve: publish, reject: revise }) g.add_edge(publish, END) return g.compile(checkpointercheckpoint_saver)checkpointer是持久化关键中断后能从最近的 Node 恢复。route_after_verify里要写清楚重试上限否则revise → verify会变成死循环。4. 逐层验证怎么确认 Agent 行为符合预期配置写完不代表能跑三层都要有独立的验证动作。先说 Harness 验证。最直接的办法是“拿掉模型看剩下什么”把模型调用替换成一个返回固定 JSON 的 mock然后跑一遍流程。如果工具调用、状态持久化、权限拦截都正常说明 Harness 是独立的。具体检查动作第一检查状态恢复。手动中断进程重启后读.agent/progress.md和最近的 checkpoint看 Agent 是否能说出“上次做到哪、还剩什么”。如果它一脸茫然说明持久化没接好。第二检查权限边界。故意让 Agent 尝试写一个不在 allowlist 里的文件比如config/secrets.yaml。正确行为是拒绝并记录到 trace而不是默默写进去。第三检查可观测性。打开.agent/traces/下的 trace 文件确认每次工具调用的输入输出、耗时、成本都有记录。没有 trace 的 Harness 等于黑盒出问题只能靠猜。再说 Loop 验证。核心是“证据驱动”四个字。你可以构造一个必然失败的场景让 Agent 生成一个引用了不存在文件的 Markdown然后看 Grader 是否返回明确失败证据以及 Loop 是否在 max_attempts 后升级给人工而不是无限重试。检查动作包括看 feedback 是否具体“第 3 行链接 404”而不是“质量不够”、看预算耗尽后是否触发 escalate、看成功时是否真的通过了确定性检查而不是模型自评。最后是 Graph 验证。重点是分支和恢复。你可以人为让verify节点返回 fail观察是否走到revise再回到verify再让human_gate返回 reject看是否回到revise而不是直接 publish。检查动作在 checkpointer 里查每个 Node 的进入次数确认没有意外循环在 trace 里对齐 Graph Node 和 State Transition确认失败位置能定位到具体节点。三层验证做完你会得到一张清晰的“故障归属图”状态丢失找 Harness重试失控找 Loop顺序错乱找 Graph。这就是三层架构最大的价值——它让排障有抓手而不是每次都归咎于“模型不行”。5. 常见报错排查401、local proxy failed、reading choices、OAuth实际跑起来报错基本集中在模型入口和配置层。下面按真实报错逐个拆。401 Unauthorized最常见。先确认TAOTOKEN_API_KEY是否真的注入到进程环境里而不是只写在.env却没加载。用curl直接测curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -20如果这里就 401说明 Key 无效或没带上如果这里通、代码里不通说明 Harness 读取环境变量的路径写错了。注意 Base URL 是https://taotoken.net/api不要多加/v1后缀导致路径重复。local proxy failed通常出现在你本地配了转发但目标不可达。检查 Harness 配置里的base_url是否被某个本地代理覆盖以及timeout_ms是否太短。把TAOTOKEN_TIMEOUT_MS调到 60000 再试。如果用了 Claude Code确认ANTHROPIC_BASE_URL指向正确地址参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 。reading choices这类报错一般是响应体解析失败常见原因是模型返回了非预期结构或者流式响应被中途截断。检查 Harness 里是否对返回做了严格 Schema 校验以及max_retry是否生效。如果每次都在同一位置失败把该次请求的原始响应存到 trace 里对比。OAuth相关报错多出现在用 CLI 工具登录的场景。如果你用 Codex 或类似工具auth.json里要写全三件套Base URL、Key、Model ID。缺任何一个都会导致鉴权失败。示例{ base_url: https://taotoken.net/api, api_key: sk-你的密钥, model_id: claude-sonnet-4-5 }如果你用 Cline MCP 或 CC Switch同样要确认这三项一致。MCP 配置里 Base URL 和 Key 分开写时最容易出现 Key 对了但 Model ID 写错的情况报错往往伪装成“模型不存在”。排障时先固定一个已知可用的 Model ID再逐个替换。还有一个隐蔽的坑Harness 里同时配了底层max_retry和 Loop 层重试导致一次失败被放大成 N×M 次调用。排查时看 trace 里的调用次数如果远超预期就是两层重试叠加了。解决办法是底层只管网络抖动语义失败交给 Loop。6. 三层协同的落地建议与下一步把三层放在一起设计才是可靠的 Agent 系统。我的经验是先用最小 Harness 跑通真实任务收集 Trace观察模型实际怎么解决问题等稳定路径浮现出来再把它形式化成 Graph。反过来一上来就画几十个 Node往往是在冻结还没验证的假设。具体落地顺序可以这样第一步用第 2 节的配置把模型入口固定跑通一次带工具调用的任务第二步加上 progress 文件和 checkpoint验证跨 Session 恢复第三步引入确定性 Grader把“模型说完成”换成“测试通过才算完成”第四步当出现多 Specialist、审批、并行需求时再上 Graph。如果你还在选模型或验证工具调用能力先去模型对话页面实测https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。长期跑编码和 Agent 任务用 Coding Plan 更省心https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入过程中遇到配置问题对照文档和 API Keys 页面逐项核对https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 、https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。最后留一个检查清单你可以贴到项目 README 里Harness 层工具是否聚焦、状态是否持久、权限是否最小、能否暂停恢复Loop 层成功证据是什么、失败反馈是否具体、重试上限多少、预算耗尽怎么办Graph 层哪些路径必须确定、哪些可并行、人工 Gate 在哪、中断后从哪恢复。三层都答得上来你的 Agent 才算真正从 Demo 走向生产。

相关新闻

Android Framework 常见解决方案(03)android系统 资源文件添加:TaoToken 统一 Key 通道下的编译验证

Android Framework 常见解决方案(03)android系统 资源文件添加:TaoToken 统一 Key 通道下的编译验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 12:53:04 阅读更多 →
一键卸载 OpenClaw:一条命令清空所有数据与服务,TaoToken 环境同步清理

一键卸载 OpenClaw:一条命令清空所有数据与服务,TaoToken 环境同步清理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 12:52:03 阅读更多 →
Python数学建模实战:PDF解析、遥感代理建模与指标链构建

Python数学建模实战:PDF解析、遥感代理建模与指标链构建

简介:本资源为2022年美国大学生数学建模竞赛(MCM/ICM)C题F奖获奖项目完整复现包,面向数学建模初学者、金融数据分析学习者及机器学习实践者,聚焦比特币交易策略建模这一典型时序优化问题。包内含可运行代码、原始与预处…

2026/10/12 12:52:03 阅读更多 →

最新新闻

website-rebuild-skill 源码化阶段:如何把逐字移植的机器产物重构成人能读的工程

website-rebuild-skill 源码化阶段:如何把逐字移植的机器产物重构成人能读的工程

【免费下载链接】website-rebuild-skill 复刻网站的 Agent Skill:抓只读镜像、从压缩代码逐行还原、自动比对验收。An agent skill that mirrors a website, rebuilds it from the minified code, and verifies the result with automated diffs. 项目地址&#xff…

2026/10/12 13:41:54 阅读更多 →
基于SpringBoot的大健康养老公寓管理系统:从毕设选题到答辩全攻略

基于SpringBoot的大健康养老公寓管理系统:从毕设选题到答辩全攻略

1. 为什么选“大健康养老公寓管理”这个题目每年到这个时间点,总有同学来找我聊毕业设计的事,问得最多的就是:有没有合适的题目推荐?要求还五花八门——好过审、工作量够、技术栈主流、最好还能润色到简历里。我通常会反问一句&am…

2026/10/12 13:41:54 阅读更多 →
CAD二次开发中点在多边形内的高精度实时判断方案

CAD二次开发中点在多边形内的高精度实时判断方案

1. 这不是数学题,是CAD里每天都在发生的“位置判断”实战在CAD二次开发的实际项目中,“点是否在多边形内”绝不是教科书里一个画个示意图就能打发的几何问题——它是某高校土木系BIM协同平台里构件自动归类的触发条件,是某工业设计公司电缆布…

2026/10/12 13:41:54 阅读更多 →
动态规划空间压缩实战:前缀和与后缀最大值求解两段不重叠子数组最大和

动态规划空间压缩实战:前缀和与后缀最大值求解两段不重叠子数组最大和

1. 从一道“数学考试”题看动态规划的空间压缩技巧“数学考试”这个标题乍一看像是讲备考策略,实际上它是一道经典的算法题,出现在某在线编程平台的每日一题栏目中。题目的核心是:给定一个长度为 n 的整数序列,要求选出两个不重叠…

2026/10/12 13:41:54 阅读更多 →
NGS-GNN:面向临床响应预测的图神经网络实战

NGS-GNN:面向临床响应预测的图神经网络实战

简介:本资源是一个面向生物信息学初学者与机器学习实践者的轻量级教学项目,聚焦于下一代测序(NGS)数据分析与Python建模的交叉实践。项目以Jupyter Notebook为核心载体,提供可复现的端到端分析流程,涵盖环境…

2026/10/12 13:41:54 阅读更多 →
C语言播放《下山》:从Beep到WAV的音频编程全解析

C语言播放《下山》:从Beep到WAV的音频编程全解析

前段时间在编程群里看到有人甩了个标题:「疯狂的往左」用 C 语言播放《下山》。一看名字就知道,这是典型的整活向练手题——不用图形界面,不用现成的音乐库,纯粹拿 C 语言的朴素能力让电脑把这首国风歌“唱”出来。我第一次见这种…

2026/10/12 13:40:52 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →