☰
Agentic Harness Workflow:让AI Coding从随机生成到工程化交付
2026/10/20 3:41:29 网站建设 项目流程

1. 为什么我们需要一个 Agentic Harness Workflow 框架

1.1 从“让 AI 写代码”到“让 AI 按流程交付代码”的认知转变

过去一年多,我一直在折腾各种 AI Coding 工具。最开始的新鲜感过去之后,一个很现实的问题摆在面前:AI 能写代码,但它写出来的东西能不能用、能不能稳定地用、能不能在团队里用,完全是三码事。

我试过让 AI 直接生成一个完整模块,结果它给我返回了 800 行代码,逻辑看起来没问题,但变量命名风格跟项目完全不搭,错误处理用的是它自己习惯的模式,连日志打印格式都跟现有代码库不一致。更麻烦的是,当我让它改一个 bug 的时候,它把之前写好的另一个功能给改坏了。这种“一次性生成”的模式,本质上就是把 AI 当成了一个高级代码补全工具,而不是一个可以协作的工程角色。

后来我开始思考一个问题:人类工程师是怎么保证代码质量的?答案不是“让一个人从头写到尾”,而是靠一套工程化流程——需求拆解、方案设计、编码实现、代码审查、测试验证、集成部署。每个环节都有明确的输入输出,每个环节都有检查点。那为什么 AI Coding 不能套用同样的逻辑?

这就是 Agentic Harness Workflow 框架要解决的核心问题。它不是一个具体的工具,而是一套把 AI Coding 从“随机生成”变成“工程化流程”的方法论和实现框架。Harness 这个词在软件工程里本来就有“约束框架”的意思,在这里它指的是给 AI Agent 套上一套可控的、可观测的、可回滚的工作流约束。

1.2 这个框架到底适合谁用

先说清楚适用人群,免得大家看完觉得“这玩意儿跟我没关系”。

如果你只是偶尔用 AI 写个脚本、生成个正则表达式,那这套框架对你来说太重了,没必要。但如果你符合以下任意一种情况,这套东西就值得你花时间研究:

  • 你是一个独立开发者,正在用 AI 辅助开发一个有一定复杂度的项目,代码量超过几千行,模块之间有依赖关系。
  • 你在团队里负责技术方案,想引入 AI Coding 但担心代码质量不可控、风格不统一、review 成本太高。
  • 你已经用过一些 AI 编程工具,但发现它们“只能写小片段,写不了完整功能”,或者“改一处坏三处”。
  • 你想把 AI Coding 纳入 CI/CD 流程,让 AI 生成的代码也能自动跑测试、自动检查规范。

这套框架的核心价值在于:它把 AI 从一个“代码生成器”变成了一个“可编排的工程节点”。你可以像定义流水线一样定义 AI 的工作步骤,每一步都有明确的输入、输出、校验规则和回退策略。

1.3 核心思路一句话说清楚

Agentic Harness Workflow 的核心思路可以用一句话概括:把 AI Coding 拆解成多个有明确边界的 Agent 任务,每个任务在受控的上下文中执行,任务之间有传递和校验机制,整个流程可观测、可中断、可回滚。

听起来有点抽象,我打个比方。传统的 AI Coding 就像你让一个装修工人直接去你家干活,他可能手艺不错,但他不知道你家整体风格,也不知道水电走线在哪,干到一半发现瓷砖不够了还得停下来。而 Agentic Harness Workflow 就像你先找了设计师出图纸,然后水电工、泥瓦工、木工按顺序进场,每个工种干完都有验收,验收不过就返工,验收过了才让下一个工种进场。

这个框架要解决的核心痛点有三个:第一是上下文管理,AI 每次执行任务时应该看到什么、不应该看到什么,需要精确控制;第二是任务边界,每个 Agent 只负责一个明确的子任务,避免“一口气吃成胖子”;第三是质量门禁,每个环节的输出必须经过校验才能进入下一环节。

2. 框架的整体架构与核心组件拆解

2.1 四层架构设计:从任务定义到结果交付

我在实际搭建这套框架的时候,把它分成了四个层次。这个分层不是拍脑袋想的,而是根据 AI Coding 的实际痛点倒推出来的。

第一层是任务定义层。这一层负责把一个大需求拆解成多个原子任务。比如“实现用户登录功能”可以拆成:定义数据模型、实现密码加密逻辑、编写登录接口、编写登录接口的单元测试、更新 API 文档。每个任务都有明确的输入(比如数据模型定义)和输出(比如加密函数代码)。

第二层是上下文管理层。这一层解决的是“AI 在执行某个任务时,应该看到哪些信息”的问题。我试过直接把整个项目代码扔给 AI,结果它被无关信息干扰,生成的代码引用了不存在的模块。后来我改成按任务动态组装上下文,只把相关的代码片段、接口定义、编码规范传给 AI,效果好了很多。

第三层是执行与校验层。这一层是真正调用 AI 生成代码的地方,但关键在于“校验”。每段生成的代码都要经过静态检查、单元测试、风格检查等多道关卡。校验不通过就触发重试或人工介入。

第四层是编排与观测层。这一层负责控制整个流程的流转,记录每个任务的执行状态、耗时、重试次数、校验结果。出了问题能快速定位是哪个环节卡住了。

2.2 核心组件一:任务拆解器

任务拆解器是整个框架的入口。它的作用是把一个模糊的需求描述转化成结构化的任务列表。我一开始是手动拆解的,后来发现手动拆解有两个问题:一是容易漏掉边界情况,二是拆解粒度不好把握。

后来我设计了一个半自动的拆解流程。先让 AI 根据需求生成一个初步的任务列表,然后我人工审核和调整。审核的重点是看每个任务是否满足“单一职责”——这个任务能不能用一句话说清楚它的输入和输出?如果说不清楚,说明拆得不够细。

拆解的时候有一个关键原则:每个任务应该对应一个可独立验证的代码单元。比如“实现密码加密”这个任务,它的输出应该是一个函数或一个类,这个函数或类可以单独写单元测试来验证。如果拆出来的任务没法独立验证,那说明拆解方式有问题。

我踩过的一个坑是:把“实现登录功能”拆成了“写前端页面”和“写后端接口”,结果前端页面依赖后端接口的返回格式,但两个任务之间没有传递接口定义,导致前端调用的字段名和后端返回的字段名对不上。后来我在拆解的时候强制要求:如果两个任务之间有依赖关系,必须显式定义接口契约。

2.3 核心组件二:上下文组装器

上下文组装器是我花时间最多的一个组件。因为 AI 生成代码的质量,很大程度上取决于它看到的上下文是否精准。

我试过几种上下文组装策略。第一种是“全量注入”,把整个项目的代码都塞给 AI。结果是 AI 经常引用不存在的函数,或者把其他模块的代码风格带进来。第二种是“最小注入”,只给 AI 当前文件的代码。结果是 AI 不知道项目里已有的工具函数,重复造轮子。

最后我采用的是一种“分层注入”策略。上下文分成三个层次:

  • 全局层:项目级的编码规范、目录结构说明、常用工具函数列表。这一层的内容相对固定,每次执行任务时都注入。
  • 模块层:当前任务所属模块的接口定义、数据模型、相关配置文件。这一层根据任务所属模块动态加载。
  • 任务层:当前任务的具体需求描述、输入数据、期望输出格式。这一层每个任务都不一样。

分层注入的好处是,AI 既能了解项目整体规范,又不会被无关信息干扰。实测下来,代码的首次通过率从之前的不到 40% 提升到了 70% 以上。

2.4 核心组件三:执行引擎与校验管道

执行引擎负责调用 AI 接口生成代码,但它的核心价值不在“调用”,而在“校验管道”。

我设计的校验管道包含四道关卡:

第一道是语法检查。这个最简单,用对应语言的解析器检查生成的代码能不能正常解析。很多 AI 生成的代码看起来没问题,但括号不匹配、缩进错误这种低级问题还是会出现。

第二道是静态分析。用 lint 工具检查代码风格、潜在 bug、未使用的变量等。这一步能过滤掉大部分“看起来能跑但质量不行”的代码。

第三道是单元测试。每个任务在定义的时候就应该附带测试用例。AI 生成的代码必须通过所有测试用例才能进入下一环节。如果测试不通过,就把测试失败信息作为反馈重新传给 AI,让它修正。

第四道是集成检查。当多个任务都完成之后,需要检查它们之间的接口是否匹配、依赖是否冲突。这一步我一般是人工 review 加自动化检查结合。

这四道关卡不是每个任务都必须全走一遍,可以根据任务的重要程度灵活配置。比如改个注释这种任务,语法检查过了就行;但改核心业务逻辑,四道关卡都得走。

2.5 核心组件四:状态管理与回滚机制

状态管理解决的是“流程走到哪了、每个任务什么状态”的问题。我用一个简单的 JSON 文件记录每个任务的状态:pending、running、passed、failed、rolled_back。

回滚机制是我觉得最有价值但也最容易被忽略的部分。AI 生成的代码如果校验不通过,不能简单地“删掉重来”,因为可能已经影响了其他文件。我的做法是:每个任务在执行前,先对相关文件做一次快照。如果任务失败且重试超过阈值,就自动回滚到快照状态,然后标记为需要人工介入。

这个机制救过我好几次。有一次 AI 在重构一个工具函数的时候,把调用这个函数的其他文件也改了,但改错了。如果没有回滚机制,我得手动去恢复那些被误改的文件,非常麻烦。

3. 实操过程:从零搭建一个可运行的 Workflow

3.1 环境准备与基础配置

先说环境。这套框架本身不依赖特定的 AI 服务商,你可以用任何提供 API 的 AI Coding 服务。我用的是 Python 作为编排语言,因为它的生态比较成熟,跟各种 AI SDK 的集成也方便。

基础依赖包括:

pip install pyyaml requests gitpython
  • pyyaml用来解析任务定义文件,我习惯用 YAML 来写任务配置,比 JSON 可读性好。
  • requests用来调用 AI 服务的 HTTP 接口。
  • gitpython用来做文件快照和回滚,底层就是 git 的 commit 和 checkout。

目录结构我建议这样组织:

agentic-harness/ ├── tasks/ # 任务定义文件 │ ├── task-001.yaml │ └── task-002.yaml ├── context/ # 上下文配置 │ ├── global.md # 全局规范 │ └── modules/ # 模块级上下文 ├── snapshots/ # 文件快照 ├── logs/ # 执行日志 └── harness.py # 主入口

任务定义文件是核心,我一般这样写:

task_id: task-001 name: 实现密码加密函数 module: auth input: description: 实现一个密码加密函数,使用 bcrypt 算法 interface: | def hash_password(password: str) -> str: pass output: file: src/auth/password.py test_file: tests/test_password.py validation: syntax: true lint: true unit_test: true max_retries: 3

这个配置的意思是:任务编号 task-001,属于 auth 模块,输入是需求描述和接口定义,输出是密码文件和一个测试文件,校验需要过语法、lint、单元测试三关,最多重试 3 次。

3.2 任务拆解的实际操作演示

假设我要实现一个“用户注册”功能。我不会直接让 AI 写整个注册流程,而是先拆解。

拆解的时候我会问自己几个问题:这个功能涉及哪些数据?涉及哪些接口?有哪些边界情况?每个边界情况能不能独立测试?

拆解结果大概是这样的:

  1. 定义用户数据模型(User 类,包含 id、username、email、password_hash、created_at)
  2. 实现密码加密函数(hash_password)
  3. 实现密码验证函数(verify_password)
  4. 实现用户创建接口(create_user)
  5. 实现邮箱格式校验函数(validate_email)
  6. 编写用户创建接口的单元测试
  7. 编写邮箱校验的单元测试

每个任务都对应一个可独立验证的代码单元。比如任务 2 的输出是一个函数,任务 6 的输出是一组测试用例。

拆解完之后,我会检查任务之间的依赖关系。任务 4 依赖任务 1、2、5,任务 6 依赖任务 4。这些依赖关系会记录在任务定义里,编排器会根据依赖关系决定执行顺序。

3.3 上下文组装的具体实现

上下文组装的核心是“按需注入”。我写了一个简单的组装函数,逻辑是这样的:

def assemble_context(task, project_root): context_parts = [] # 全局层 global_context = read_file(f"{project_root}/context/global.md") context_parts.append(global_context) # 模块层 module_context = read_file(f"{project_root}/context/modules/{task.module}.md") context_parts.append(module_context) # 任务层 task_context = f"任务描述:{task.description}\n" task_context += f"接口定义:{task.interface}\n" context_parts.append(task_context) return "\n\n".join(context_parts)

全局层我一般放这些东西:项目的编码规范(比如用 snake_case 还是 camelCase)、日志格式要求、错误处理约定、常用工具函数列表。这些内容每次任务都注入,保证 AI 生成的代码风格一致。

模块层放当前模块的接口定义和数据模型。比如 auth 模块的上下文里会包含 User 类的定义、数据库连接配置、已有的 auth 相关函数列表。这样 AI 在写新函数的时候,知道有哪些现成的函数可以复用。

任务层就是当前任务的具体需求。这里有一个技巧:我会在任务描述里明确写出“不要做什么”。比如“不要修改 User 类的定义”、“不要引入新的第三方库”。这些约束能有效减少 AI 的“自由发挥”。

3.4 执行引擎的调用与校验流程

执行引擎的主循环大概是这样的:

def execute_task(task, context): for attempt in range(task.max_retries): # 调用 AI 生成代码 generated_code = call_ai(task.prompt, context) # 写入文件 write_file(task.output_file, generated_code) # 校验管道 if not check_syntax(task.output_file): context += "\n上次生成的代码有语法错误,请修正。" continue if not check_lint(task.output_file): context += "\n上次生成的代码未通过 lint 检查,请修正。" continue if not run_unit_test(task.test_file): context += "\n上次生成的代码未通过单元测试,请修正。" continue return True return False

这里的关键是“反馈循环”。每次校验失败,不是简单地重试,而是把失败信息追加到上下文里,让 AI 知道上次哪里错了。实测下来,带反馈的重试比盲目重试的成功率高很多。

校验管道的具体实现:

语法检查我用的是对应语言的解析器。Python 用ast.parse,JavaScript 用esprima。这一步很快,基本不耗时。

Lint 检查我用的是flake8(Python)和eslint(JavaScript)。配置里可以指定 lint 规则文件,保证跟项目现有规范一致。

单元测试我用的是pytest。每个任务定义里会指定测试文件路径,执行引擎会自动运行测试并收集结果。

3.5 状态管理与回滚的落地细节

状态管理我用一个 JSON 文件记录所有任务的状态:

{ "task-001": {"status": "passed", "attempts": 1, "duration": 12.5}, "task-002": {"status": "failed", "attempts": 3, "duration": 45.2}, "task-003": {"status": "pending", "attempts": 0, "duration": 0} }

回滚机制依赖 git。每个任务执行前,我会创建一个 git commit:

git add -A git commit -m "snapshot before task-001"

如果任务失败且重试超过阈值,就回滚:

git checkout HEAD~1 -- .

这样能保证失败的任务不会污染后续任务的环境。

我踩过的一个坑是:回滚的时候把其他任务的成果也回滚掉了。后来我改成每个任务在独立的分支上执行,成功后再合并到主分支。这样回滚只影响当前任务的分支,不会影响其他任务。

4. 常见问题与排查技巧实录

4.1 AI 生成的代码风格不一致怎么办

这是最常见的问题。AI 每次生成的代码风格可能都不一样,有的用双引号有的用单引号,有的用 4 空格缩进有的用 2 空格。

我的解决方案是在全局上下文里放一份“代码风格示例”。不是用文字描述规范,而是直接放几段符合规范的代码样例。AI 对代码样例的模仿能力比理解文字规范强得多。

另外,lint 检查要配置成“严格模式”。比如 Python 的 flake8 可以配置max-line-length、indent-size等参数,不通过就直接打回重试。重试几次之后,AI 就会“学会”项目的风格。

4.2 任务拆解粒度怎么把握

拆得太粗,AI 一次要处理太多逻辑,容易出错。拆得太细,任务数量爆炸,编排成本太高。

我的经验是:一个任务对应的代码量在 50 到 200 行之间比较合适。少于 50 行说明拆得太细,可以合并;多于 200 行说明拆得太粗,需要继续拆。

另一个判断标准是:如果一个任务需要 AI 同时考虑三个以上的逻辑分支,就应该拆开。比如“实现登录功能”涉及密码验证、账号存在性检查、登录失败次数限制,这三个逻辑应该拆成三个任务。

4.3 单元测试不通过但 AI 反复改不对怎么办

这种情况我遇到过几次。AI 生成的代码逻辑有问题,但它自己看不出来,反复重试都是同样的错误。

我的处理策略是:重试 3 次还不通过,就自动降级为“人工介入”状态。系统会生成一份报告,包含任务描述、当前代码、测试失败信息、AI 的修改历史。我拿着这份报告人工分析,要么调整任务描述,要么手动修改代码,要么把任务拆得更细。

后来我还加了一个机制:如果某个任务的重试次数超过 2 次,就自动把上下文里的“参考代码”换成更详细的实现示例。有时候 AI 改不对是因为它不知道“正确的样子”是什么,给个示例它就能照着改。

4.4 多个任务之间的接口对不上怎么排查

这是集成阶段最常见的问题。任务 A 生成的函数返回{"user_id": 123},任务 B 期望的是{"id": 123},字段名对不上。

我的解决方案是在任务定义里强制要求写“接口契约”。每个任务的输出如果有对外接口,必须在 YAML 里声明:

interface_contract: function: create_user input: username: string email: string password: string output: user_id: integer username: string created_at: string

编排器会在所有任务完成后,自动检查接口契约是否匹配。如果任务 B 依赖任务 A 的输出,编排器会对比两者的接口定义,不匹配就报错。

4.5 常见问题速查表

问题现象可能原因排查方法解决方案
代码风格不一致全局上下文缺少风格示例检查 global.md 是否包含代码样例添加符合规范的代码样例
任务执行超时任务拆解粒度过粗查看任务对应的代码量拆分成更小的任务
单元测试反复失败AI 不理解测试期望查看测试失败信息在上下文里添加实现示例
接口字段不匹配缺少接口契约定义检查任务定义的 interface_contract补充接口契约并重新校验
回滚后其他任务受影响任务之间共享文件检查任务的文件依赖关系改为独立分支执行
AI 引用不存在的函数上下文注入了无关模块检查模块层上下文精简模块上下文,只保留相关接口

4.6 几个我踩过的坑和对应的技巧

第一个坑是“上下文污染”。有一次我在全局上下文里放了一个“常用工具函数列表”,结果 AI 在生成代码时大量引用这些函数,但有些函数在当前模块里根本不可用。后来我把工具函数列表拆成了“全局可用”和“模块可用”两部分,只在模块上下文里注入当前模块可用的函数。

第二个坑是“重试死循环”。AI 生成的代码一直过不了 lint 检查,但它每次重试都改同一个地方,改来改去还是不符合规范。后来我加了一个机制:如果连续两次重试的失败原因相同,就自动跳过 lint 检查,先让代码通过语法和单元测试,lint 问题留到人工 review 阶段处理。

第三个坑是“快照膨胀”。每个任务都做一次 git commit,任务多了之后 git 历史非常臃肿。后来我改成只在任务开始前做一次轻量级快照(只备份相关文件),任务成功后再做正式 commit。这样既保证了回滚能力,又不会让 git 历史太乱。

第四个坑是“AI 过度设计”。我让 AI 实现一个简单的邮箱校验函数,它给我写了一个包含正则表达式、DNS 查询、SMTP 验证的完整方案。后来我在任务描述里明确写了“只做格式校验,不要做网络请求”,才把范围控制住。所以任务描述里的“不要做什么”和“要做什么”同样重要。

5. 框架的扩展方向与个人实践体会

5.1 从单机脚本到团队协作的演进路径

我最初搭建这套框架的时候,就是一个单机 Python 脚本,跑在我自己的电脑上。后来团队里其他人也想用,我就做了一些改造。

第一个改造是任务定义文件的版本化。所有任务定义都放在 git 仓库里,每个人都可以提交新的任务定义,也可以修改现有的。这样任务拆解的经验可以沉淀下来,不会因为某个人离职就丢失。

第二个改造是执行引擎的服务化。我把执行引擎包装成了一个 HTTP 服务,团队成员可以通过 API 提交任务、查询状态、获取报告。这样大家不需要在本地配置环境,直接调用服务就行。

第三个改造是校验规则的共享化。lint 规则、测试框架配置、接口契约模板都放在共享目录里,保证不同人执行的任务遵循同样的标准。

5.2 跟 CI/CD 流程的集成思路

这套框架最终是要跟 CI/CD 打通的。我的做法是在 CI 流程里加一个“AI 任务执行”阶段。

具体来说,当开发者提交一个 PR 时,CI 会自动检查 PR 描述里是否包含任务定义。如果包含,就自动触发 Agentic Harness Workflow,执行任务定义里的所有任务,跑完校验管道,然后把结果作为 PR 评论发出来。

如果所有任务都通过校验,PR 就可以进入人工 review 阶段。如果有任务失败,PR 会被自动标记为“需要修改”,并附上失败详情。

这样做的好处是:AI 生成的代码在进入人工 review 之前,已经过了一轮自动化校验,人工 review 只需要关注业务逻辑和架构设计,不用再纠结代码风格和低级错误。

5.3 我个人在实际操作中的几点体会

第一点体会是:这套框架的价值不在于“让 AI 写更多代码”,而在于“让 AI 写的代码更可控”。我现在的习惯是,宁可让 AI 写 10 个小任务,每个任务 50 行代码,也不让它一次性写 500 行。小任务容易校验、容易回滚、容易定位问题。

第二点体会是:上下文的质量比 AI 模型的能力更重要。我用过不同能力的 AI 模型,发现只要上下文组装得好,能力稍弱的模型也能生成可用的代码。反过来,如果上下文一团糟,再强的模型也白搭。

第三点体会是:校验管道不是越严格越好。我一开始把 lint 检查配得非常严格,结果 AI 大部分时间都在改格式问题,真正写业务逻辑的时间反而少了。后来我调整了策略:格式问题只在最后统一处理,执行过程中只关注语法和单元测试。这样效率高了很多。

第四点体会是:回滚机制一定要有,但不要滥用。回滚是最后的手段,能通过重试解决的问题就不要回滚。因为回滚会丢失上下文,重新执行的成本很高。我的策略是:重试 3 次不通过才回滚,回滚后标记为人工介入。

第五点体会是:这套框架本身也需要持续迭代。我每个月会 review 一次任务定义和校验规则,看看哪些任务经常失败、哪些校验规则误报率高、哪些上下文配置需要调整。框架不是搭好就完事了,它跟项目一样需要维护。

5.4 后续可以继续扩展的方向

如果你已经跑通了基础版本,可以考虑这几个扩展方向。

第一个方向是“多 Agent 协作”。现在的框架是串行执行任务,一个任务完成再执行下一个。但实际上有些任务是可以并行的,比如前端页面和后端接口可以同时开发。可以引入一个简单的调度器,根据任务依赖关系自动并行化。

第二个方向是“智能重试策略”。现在的重试是固定次数的,可以改成根据失败原因动态调整。比如语法错误重试 1 次就够了,单元测试失败可以重试 3 次,接口不匹配可能需要人工介入。

第三个方向是“知识沉淀”。每次人工介入解决的问题,都可以沉淀成新的上下文片段或校验规则。这样框架会越用越聪明,人工介入的频率会越来越低。

第四个方向是“多语言支持”。现在的校验管道主要是针对 Python 和 JavaScript 的,可以扩展到 Go、Rust、Java 等语言。核心逻辑不变,只需要替换语法检查器和 lint 工具。

第五个方向是“可视化面板”。现在看任务状态要翻 JSON 文件和日志,可以做一个简单的 Web 面板,实时显示每个任务的状态、耗时、重试次数、校验结果。这样排查问题会更直观。

这套框架我用了大概半年时间,从最初的几十行脚本迭代到了现在几千行的规模。最大的感受是:AI Coding 的上限不取决于 AI 本身,而取决于你给它搭的“脚手架”。脚手架搭得好,AI 就能稳定输出高质量代码;脚手架搭得不好,AI 就是一个随机代码生成器。Agentic Harness Workflow 就是那个脚手架,它把 AI Coding 从“碰运气”变成了“可重复的工程流程”。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询