Harness Engineering 从零理解到动手实践:用 AGENTS.md 与状态机搭一套可验证的 AI Agent 反馈回路

发布时间:2026/9/27 14:51:31

Harness Engineering 从零理解到动手实践:用 AGENTS.md 与状态机搭一套可验证的 AI Agent 反馈回路 1. 为什么你的 AI Agent 总是“嘴上说做完了”如果你正在用 Claude Code、Cursor 或者自己写的 Agent 跑多步骤任务大概率遇到过这几个场景Agent 说“已完成登录模块修复”你打开文件一看只改了个注释长任务跑到一半它开始重复调用同一个失败命令你让它自己检查代码它永远回复“看起来没问题”。这些问题的根因往往不在模型本身而在于缺少一套外部的运行控制系统。Harness Engineering 就是解决这个问题的工程方法——它不优化模型参数而是给 Agent 搭建“缰绳 马鞍 跑道护栏 反馈镜子”。本文会从零带你搭一套最小可用的 Agent 工程用 AGENTS.md 定义行为边界用状态机锁定任务流转用反馈回路做结果校验最后跑一次端到端验证。适合谁看正在做 AI coding 工具链的后端工程师、想让 Agent 稳定跑长任务的团队、以及被“提前宣布胜利”折磨过的开发者。读完你能拿到一份可复制的 AGENTS.md 骨架、一段状态机配置代码以及一个能立刻跑通的验证动作。2. 前置准备TaoToken 统一 Key 与运行环境在动手之前先把模型调用通道准备好。我试过在多个项目里分别维护不同厂商的 Key切换模型时改配置改到崩溃。TaoToken 在这里的作用是提供统一的 Key/API 通道让你在 Agent 运行层只配置一次后续换模型不用动业务代码。官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 地址https://taotoken.net/api你需要准备的东西不多一个可用的 API Key在控制台创建见下方 deep linkNode.js 18 或 Python 3.10 运行环境一个测试用的代码仓库本文用 Next.js TypeScript 项目举例其他技术栈同理创建 Key 的路径https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite如果你用的是 Claude Code 这类编码 Agent接入文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite注意Key 只放在环境变量里不要写进 AGENTS.md 或任何会被 Agent 读取的文件。后面权限边界那一节会专门讲怎么用代码拦住 Agent 碰密钥文件。3. 可复制配置AGENTS.md 骨架 状态机 反馈回路3.1 AGENTS.md 骨架让 Agent 读得懂你的项目AGENTS.md 的本质是给 Agent 看的项目说明书。README 给人看AGENTS.md 给 AI 看。关键原则是渐进披露——不要把全部文档塞进去只保留最关键的三类信息WHAT项目是什么、HOW怎么跑、RULES什么不能碰。在项目根目录创建AGENTS.md# AGENTS.md ## 项目概览 Next.js 14 TypeScript 全栈项目使用 App Router。 ## 技术栈 - 框架Next.js 14App Router禁止 Pages Router - 语言TypeScript 严格模式禁止 any - 样式Tailwind CSS禁止 CSS Modules - 数据库Prisma PostgreSQL - 测试Vitest Testing Library ## 开发命令 - 安装依赖pnpm install - 开发服务器pnpm dev - 运行测试pnpm test - 类型检查pnpm typecheck - 代码检查pnpm lint ## 架构约束 - API 路由放在 app/api/ 下 - 业务逻辑放在 lib/ 下 - 环境变量通过 env.ts 统一管理禁止硬编码 - 禁止修改 .env、secrets/、config/production/、.git/ ## 验证方式 改完代码后必须依次执行 1. pnpm typecheck 2. pnpm lint 3. pnpm test 三项全部通过才算完成禁止跳过。如果是 monorepo可以在子包目录下再放一份packages/web/AGENTS.mdAgent 在不同目录下读取到的规则更精准。3.2 状态机配置把任务流转锁死在轨道里软约束写在 Prompt 里的“请先做计划”不可靠模型会忘、会跳过。硬约束要写进执行层。下面是一个四阶段状态机用 Python 实现你可以直接复制到自己的 Agent 运行层from enum import Enum class AgentPhase(Enum): RESEARCH research PLAN plan EXECUTE execute VERIFY verify class PhaseStateMachine: ALLOWED_TRANSITIONS { AgentPhase.RESEARCH: [AgentPhase.PLAN], AgentPhase.PLAN: [AgentPhase.EXECUTE, AgentPhase.RESEARCH], AgentPhase.EXECUTE: [AgentPhase.VERIFY], AgentPhase.VERIFY: [AgentPhase.EXECUTE, AgentPhase.PLAN], } PHASE_PERMISSIONS { AgentPhase.RESEARCH: [read_file, search_code, list_files], AgentPhase.PLAN: [read_file, create_plan], AgentPhase.EXECUTE: [read_file, write_file, run_command], AgentPhase.VERIFY: [run_tests, run_lint, run_typecheck], } def __init__(self): self.current AgentPhase.RESEARCH def can_transition(self, target: AgentPhase) - bool: return target in self.ALLOWED_TRANSITIONS[self.current] def can_execute(self, action: str) - bool: return action in self.PHASE_PERMISSIONS[self.current] def transition(self, target: AgentPhase): if not self.can_transition(target): raise PermissionError( f非法状态迁移{self.current.value} - {target.value} ) self.current target这段代码的核心价值Agent 在 RESEARCH 阶段想直接改代码会被can_execute(write_file)拦下想从 RESEARCH 跳到 EXECUTE会被can_transition拒绝。它必须老老实实先出计划。3.3 反馈回路让 Agent 犯错后越来越稳反馈回路分三层从低成本到高成本依次叠加。第一层是自动化验证改完代码强制跑 typecheck lint testclass FeedbackLoop: def run_verification(self, changed_files: list[str]): results [] for cmd in [pnpm typecheck, pnpm lint, pnpm test]: r self.run_command(cmd) results.append({ check: cmd, passed: r.success, output: r.stdout[-500:], errors: r.stderr[-500:] if not r.success else None, }) return { passed: all(r[passed] for r in results), details: results, }第二层是执行与评审分离。让一个 Agent 写代码另一个独立会话按标准审查避免“自己写自己夸”async def dual_agent_review(task, executor, reviewer): MAX_ROUNDS 3 for _ in range(MAX_ROUNDS): result await executor.execute(task) review await reviewer.review( task_descriptiontask.description, code_diffresult.diff, review_criteria[ 是否完成所有要求, 是否有 bug, 是否遵循 AGENTS.md 规范, 是否存在安全隐患, ], ) if review.is_good_enough(): return result task task.with_feedback(review.comments) return {status: escalate_to_human, result: result, review: review}第三层是错误经验持久化。维护一份.harness/lessons-learned.md每次 Agent 犯错后归因并更新约束# .harness/lessons-learned.md ## 2026-03-20: Prisma 迁移必须在测试前执行 - 问题修改 schema 后没跑 migrate测试全挂 - 修复在验证步骤中加入 migrate 检查 - 状态已纳入硬约束 ## 2026-03-18: 不要在 middleware 中直接 throw - 问题导致页面白屏 - 修复补充框架约束说明 - 状态已写入 AGENTS.md3.4 权限边界高风险目录靠代码拦不要把“别碰生产配置”只写在提示词里。下面这段代码直接拦住 Agent 对敏感路径的访问class PermissionBoundary: FORBIDDEN_PATHS [.env, secrets/, config/production/, .git/] def check_file_access(self, file_path: str, operation: str): for forbidden in self.FORBIDDEN_PATHS: if file_path.startswith(forbidden): raise PermissionError( f禁止{operation}文件{file_path} )4. 验证请求跑一次端到端 Agent 任务配置写完了现在跑一次完整流程验证。假设任务是“修复src/login.tsx中的登录 bug”。4.1 启动会话并加载 AGENTS.mdAgent 启动时Harness 读取根目录 AGENTS.md初始化状态机为 RESEARCH 阶段。此时 Agent 只能调用read_file、search_code、list_files。4.2 观察状态迁移与拦截Agent 请求读取login.tsxHarness 检查 RESEARCH 阶段允许read_file放行。接着 Agent 想直接改代码Harness 检查write_file不在 RESEARCH 权限列表拒绝。Agent 转而请求进入 PLAN 阶段状态机校验RESEARCH - PLAN合法允许。4.3 执行与自动验证Agent 在 PLAN 阶段生成修复计划请求进入 EXECUTE。Harness 允许PLAN - EXECUTEAgent 修改login.tsx。文件修改事件触发验证守卫Harness 强制进入 VERIFY 阶段自动执行pnpm typecheck pnpm lint pnpm test如果三项全部通过任务标记完成。如果测试失败错误输出被反馈给 Agent状态回退到 EXECUTE 重试。4.4 成功结果长什么样一次成功的端到端运行你会看到类似这样的日志[Harness] Phase: RESEARCH - PLAN (allowed) [Harness] Phase: PLAN - EXECUTE (allowed) [Harness] File write detected: src/login.tsx [Harness] Auto-trigger verification guard [Harness] Phase: EXECUTE - VERIFY (forced) [Harness] typecheck: PASS [Harness] lint: PASS [Harness] test: PASS (12 passed, 0 failed) [Harness] Task completed with verification关键点Agent 不一定知道状态机代码长什么样但它会真实感受到哪些动作被允许、哪些被拦下、什么才算完成。5. 本篇常见错排查5.1 Agent 不读 AGENTS.md检查文件是否在项目根目录文件名大小写是否精确匹配。部分工具需要显式配置读取路径确认你的 Agent 运行层有没有加载逻辑。如果用的是 Claude Code接入配置参考 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite5.2 状态机迁移报 PermissionError先打印self.current和target确认迁移方向在ALLOWED_TRANSITIONS里。常见错误是 VERIFY 失败后想直接回 RESEARCH但合法路径是VERIFY - EXECUTE或VERIFY - PLAN。5.3 验证命令全部通过但 Agent 仍说没完成检查 Agent 的输出解析逻辑。有些模型会把pnpm test的输出误判为失败因为 stderr 里有 warning。建议在 FeedbackLoop 里只以 exit code 为准不要用文本匹配判断成功。5.4 长任务跑到后面上下文爆炸不要让一个会话死扛到底。设置上下文利用率阈值比如 60%超过就生成 handoff 文档开新会话继续class ContextManager: MAX_CONTEXT_UTILIZATION 0.6 async def run_with_reset(self, agent, task): subtasks self.decompose_task(task) for subtask in subtasks: if agent.context_utilization self.MAX_CONTEXT_UTILIZATION: handoff await agent.generate_handoff( prompt总结1.已完成 2.当前进度 3.下一步 4.注意事项 ) agent agent.fresh_session() agent.load_context(handoff) await agent.execute(subtask)5.5 循环失败检测没生效确认LoopDetector的record_failure在每次工具调用失败后都被调用。常见遗漏是只在异常捕获里记录但 Agent 返回successFalse时没记录。建议在工具调用统一出口处埋点。6. 下一步把反馈回路接进你的编码工作流最小可用版本跑通后下一步是把它接进日常编码。如果你主要用 Claude Code 做长期编码任务可以把状态机和验证守卫配置成 Coding Plan 的一部分让每次代码修改都自动走一遍验证回路https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite想先验证模型对话和工具调用是否正常可以从模型对话入口测试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite接入文档和 API Key 管理分别在这里接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteAPI Keyshttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite最后留一个我踩过的坑AGENTS.md 不要一次写太长。我第一版写了 300 多行结果 Agent 读取后反而忽略了关键约束。后来砍到 60 行以内只保留技术栈、命令、禁区、验证方式四块遵守率明显提升。渐进披露比全量灌输有效得多。
延伸阅读

更多相关文章

2026/9/27 14:46:31

中山做百度网站的公司吗?3个核心注意事项避坑指南

中山做百度网站的公司吗?3个核心注意事项避坑指南 网站上线三个月,后台流量几乎为零,是不是觉得特别心累?很多中山的企业老板或者创业者,手里攥着做好的网站,却苦于没人访问,这就是典型的“建而不用”。在找“中山做百度网站的公司吗”这类服务时,千…

2026/9/27 14:46:31

LangChain 1.0 法务合同审核 Agent 实战:OCR+RAG 源码级配置与验证

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

2026/9/27 15:41:34

去越南做网站0代码起步:搞定服务器与性能优化全攻略

去越南做网站0代码起步:搞定服务器与性能优化全攻略 想自己做网站却一行代码都不会写?别慌,这不是劝退,而是提醒你:选对工具比死磕代码更重要。去越南做网站,核心难点不在技术,而在跨地域的服务器部署、域名解析和合规备案。很多老板卡在“服务器选哪…

2026/9/27 15:41:34

基于Jenkins和Argocd实现CI/CD: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/9/27 15:41:34

避坑指南:服务器安wordpress图解步骤与前端规范实战

避坑指南:服务器安wordpress图解步骤与前端规范实战 域名买好了,服务器也租了,结果一上手就懵:这俩玩意儿到底咋配?很多刚入行做建站的朋友,卡在“域名服务器搞不懂”这一步,看着控制台一堆英文参数,心里直打鼓。别急,今天咱们不整虚的,直…

2026/9/27 15:41:34

个人备案网站名称怎么写?3个坑避开,选对备案主体

个人备案网站名称怎么写?3个坑避开,选对备案主体 域名服务器搞不懂?别慌,这是90%新手第一次接触建站时的噩梦。你手里捏着个域名,服务器也租好了,卡在“个人备案”这一步,盯着“网站名称”输入框发呆:写“我的博客”?写“张三的个人空间”?还是…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/25 20:55:38

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/26 19:58:38

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/25 18:34:56

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑