Human-in-the-Loop:人不能退出架构决策
人必须在 AI 辅助开发中参与目标定义、架构取舍、状态收敛、事实校验和完成判断的循环。
我一开始对 AI 辅助开发的期待很直接:我提出目标,AI 给我方案,最好还能顺手把代码写出来。
在 NeoCode 里做 SubAgent / DAG 方向时,我也走过这条路。我希望把复杂任务拆成 DAG,让多个子任务自动调度、自动执行、最后合并结果。这个方案听起来很完整,也很像一个“高级架构”。
但真正落地时,我很快发现自己失去了对系统的理解。
状态太复杂,模块之间衔接不起来,AI 给出的“最佳方案”看起来合理,却没有经过我自己的校验。结果是:我看不懂它到底在做什么,AI 也无法把方案正确做完,项目反而停滞了。
这次经历让我重新理解了 Human-in-the-Loop。
以前我理解 HITL,很容易把它等同于“人工审批”:AI 要执行命令了,人点一下 allow;AI 要改文件了,人点一下确认。
但现在我更愿意把它理解成:
Human-in-the-Loop 不是让人站在旁边点一个“同意”按钮,而是让人参与 AI 开发过程中的目标定义、方案取舍、状态收敛、事实校验和完成判断。
这篇文章不是想科普一个概念,而是想记录我在 NeoCode 里踩坑之后,对“AI 时代人应该如何参与架构设计和项目实现”的一次反思。
Human-in-the-Loop
在做 Agent 项目之前,我对 Human-in-the-Loop 的理解其实很窄。
我以为它主要解决的是安全问题:模型要执行高风险工具,就让人确认一下;模型要访问敏感资源,就让人审批一下。
这当然是 HITL 的一部分。比如 OpenAI Agents SDK 里,当某个工具调用需要审批时,Agent run 会暂停,返回 pending approval,用户 approve / reject 后再从同一个 RunState 恢复执行。Cloudflare Agents 也把 HITL 放进 workflow approval 里:流程到审批点后暂停,客户端展示批准或拒绝,批准后带着 metadata 恢复,拒绝或超时也需要被工作流处理。
这些工程机制很重要。它们说明 HITL 不是一句口号,而是要和 pause、approve、reject、resume、state 这些真实执行状态绑定起来。
但我后来发现,如果只把 HITL 理解成“工具调用前的审批”,还是太窄了。
因为我在 NeoCode 里真正踩坑的地方,不是某一次 bash 没审批,也不是某个文件改错了,而是我在架构决策阶段没有真正进入循环。
AI 提出了方案,我接受了。
AI 拆了模块,我相信了。
AI 说这是最佳实践,我没有用测试和代码事实校验。
等状态复杂到我看不懂时,项目已经很难往前推了。
那一刻我意识到:人在 AI 开发里的位置,不应该只出现在执行动作之前,而应该出现在整个系统形成判断的过程中。
AI 不能替你形成理解
后来我看了导师对 D2A 架构公开课的总结,对这件事有了更明确的理解。
那场课表面上是用 d2a 工具分析 n8n 架构,实际上讲的是:AI 时代,人到底该怎么学架构。导师在总结里说,现在让 AI 很快生成一份“看起来完整”的架构文档不难,难的是把问题问对,把理解做实,把那些似懂非懂的地方追清楚。
这句话放到写代码和做项目里同样成立。
AI 很擅长给出一个看起来完整的方案。它可以迅速列出模块、状态、接口、异常处理、兜底逻辑和未来扩展。问题是:这些东西是不是真的适合当前项目?它们是不是当前阶段必须?我能不能解释它们为什么存在?它们有没有被测试验证?
如果这些问题没有人参与追问,AI 的“完整方案”很容易变成一种危险的幻觉。
D2A 里很重要的一点是,它不是让 AI 一次性生成一份架构文档就结束,而是把 human-in-the-loop 做进分析过程本身:AI 先抛出内置问题,人补充问题;AI 生成分析文档;AI 再基于文档反向出题,人回答并修正理解。导师总结里说,这不是把 HITL 当成礼貌性的确认按钮,而是把它当成分析流程本身的一部分。
这给我的启发是:好的 AI 辅助学习,不是 AI 给答案,而是 AI 不断把人拉回问题现场。
人要补充问题,回答问题,发现自己答错,重新读代码,再修正理解。
理解不是“看过答案”,而是“参与过答案怎么长出来”。
我接受了一个自己看不懂的“最佳方案”
回到 NeoCode。
我在 SubAgent / DAG 方向上最典型的一次教训,就是太早接受了一个自己还没有能力验证和维护的复杂方案。
一开始,DAG 看起来是很自然的方向:复杂任务可以拆成多个节点,节点之间有依赖关系,SubAgent 可以并发执行,最后再汇总结果。
AI 也很容易支持这个方向。它会告诉你应该有 Scheduler、Task Node、Worker、Result Merge、Retry、Cancel、State Store、Dependency Resolver……每个模块听起来都合理。
问题是,当我没有真正参与这些取舍时,它们很快变成了一套我自己也看不懂的系统。
为了防止失败,AI 会倾向于加更多状态、更多兜底、更多抽象、更多边界判断。表面上看,这是“防御性编程”;但在一个主链路还没跑通的项目里,它只会让架构越来越臃肿。
最后的问题不是“代码不够多”,而是“状态太多”。
Task 有状态,SubAgent 有状态,Permission 有状态,Tool Call 有状态,Run 有状态,Todo 有状态,Result Merge 也有状态。每个状态都像是为了解决一个问题而存在,但当它们叠在一起时,我已经无法清楚回答:
- 这个状态是谁创建的?
- 谁推进它?
- 谁消费它?
- 它的终态是什么?
- 它失败后怎么恢复?
- 它能不能被测试覆盖?
这就是我说的“人退出架构决策”的后果。
不是 AI 没有给方案,而是我没有真正理解方案。不是 AI 没有写代码,而是我没有用工程事实验证这些代码。不是 AI 不努力,而是我把“看起来完整”误当成了“真的可交付”。
后来我把这条线收敛到 inline SubAgent:先让主 Agent 能显式调用一个子任务,子任务在受控边界里执行,再把结构化结果回灌给主 Agent。DAG 和更复杂的编排不一定错,但不应该早于单 Agent 主链路、工具调用、权限边界、状态回灌和测试验证。
我在另一篇文章里专门复盘过这条线:SubAgent 不是多开几个模型:NeoCode 从 DAG 试错到 inline 最小闭环的复盘。
这次经历让我意识到:
复杂自动化不能早于事实、状态、权限和验收能力。
没有这些能力时,自动化只会把不确定性放大。
HITL :人参与目标和边界裁剪
现在我理解的 Human-in-the-Loop,第一层不是审批,而是目标和边界裁剪。
AI 时代做项目,最危险的一句话可能是:
帮我设计一个完整方案。
因为“完整方案”往往意味着更多模块、更多状态、更多兜底和更多抽象。但工程项目不是越完整越好,尤其是在比赛、实训、快速迭代这种场景里,真正重要的是当前阶段什么必须成立。
导师在 D2A 总结里讲架构拆解六步法,第一步就是边界分析与裁剪:先问清楚系统到底是什么、入口在哪里、砍掉 80% 代码以后什么还必须留着。
在 NeoCode 里,如果当时我能先问这些问题,DAG 线可能不会失控得那么快:
- 当前阶段必须保留的核心能力是什么?
- 我们是真的需要 DAG,还是只需要一个可控的子任务执行单元?
- 哪些功能只是看起来高级,但不是当前里程碑必须?
- 如果砍掉 80% 设计,什么仍然必须成立?
- 我能不能解释这个状态为什么存在?
- 我能不能写测试证明它有效?
这些问题不是 AI 不能回答,而是人必须参与判断。
因为架构的核心不是罗列模块,而是取舍。只要涉及取舍,人就不能退场。
HITL 第二层:人参与架构取舍
AI 很容易把“可能有用”变成“应该实现”。
这在架构设计里尤其危险。
比如 DAG 方案里,Scheduler 可能有用,Retry 可能有用,Cancel 可能有用,Result Merge 可能有用,状态持久化也可能有用。但问题不是它们有没有用,而是:
当前阶段是否值得引入这些复杂度?
这就是架构取舍。
我现在会更倾向于让人和 AI 形成这样的循环:
AI 提出方案
-> 人追问目标和边界
-> AI 给出多种路径
-> 人选择当前阶段可验证的路径
-> AI 落地最小闭环
-> 人用测试和事实校验
-> 再决定是否进入下一层复杂度
这才是我理解的 Human-in-the-Loop。
人不是每一行代码都要亲自写,也不是每个工具调用都要手动点确认。人的关键作用是:在系统出现多个方向时,做当前阶段的取舍。
对我来说,DAG 到 inline SubAgent 的收敛,就是一次典型的人机协作决策:长期看 DAG 可能有价值,但当前阶段更应该先做 inline 最小闭环。
HITL 第三层:人参与状态收敛
DAG 让我最痛的地方,是状态复杂度。
状态复杂并不一定是坏事。一个真实系统当然会有状态。但如果人解释不了状态,系统就会变成黑箱。
我后来给自己定了一个判断标准:
如果人无法解释状态机,AI 生成的状态机就不应该进入核心架构。
一个状态至少要能回答:
- 它为什么存在?
- 它由谁创建?
- 它被谁推进?
- 它被谁消费?
- 它有哪些合法转移?
- 它的失败态是什么?
- 它能不能被测试覆盖?
如果这些问题答不上来,那么这个状态再“工程化”,也只是复杂度。
这也是我对 HITL 的第三层理解:人在环不是只参与“同意或拒绝”,还要参与状态收敛。
AI 可以帮我列出状态,但人要决定哪些状态进入核心模型,哪些只是实现细节,哪些暂时不该存在。
在架构设计里,状态是比模块更危险的东西。模块多了还能拆,状态乱了,系统就会变得很难推理。
下面这张图是我对当时 DAG 复杂度的简化回看:
flowchart TD
A[AI 给出 DAG 方案] --> B[Scheduler]
A --> C[Task State]
A --> D[SubAgent State]
A --> E[Permission State]
A --> F[Result Merge]
A --> G[Retry / Cancel]
B --> H[状态复杂度上升]
C --> H
D --> H
E --> H
F --> H
G --> H
H --> I{人能否解释和测试?}
I -->|否| J[暂缓 DAG]
I -->|是| K[进入下一阶段]
J --> L[inline SubAgent 最小闭环]
这张图不是说 DAG 不好,而是提醒自己:如果一个架构形态还没有被人理解、测试和收敛,就不应该太早进入核心实现。
HITL 第四层:人参与事实校验
我现在越来越认同一句话:
Agent 的结论必须绑定 evidence,否则只是看起来很像真的解释。
在 Code Agent 项目里,最重要的 evidence 往往不是模型的自然语言解释,而是测试结果、运行日志、diff、状态变化。
尤其是测试结果。
如果 AI 说“我已经修复了”,但没有测试输出,这个完成就很虚。
如果 AI 说“DAG 调度已经可用”,但没有一个最小任务能从创建、执行、完成、失败恢复跑通,这个架构也只是文档上的可用。
如果 AI 说“模块已经衔接好了”,但没有一条真实链路证明数据能流过去,这个衔接就还没有发生。
这也和 D2A 总结里提到的“代码事实关联”很接近:当分析结果与代码实现不符时,要强制纠偏;若出现冲突,优先以代码为准,并可以用多模型交叉验证。
我想把这件事迁移到 AI 辅助开发里:
当 AI 的架构描述与测试事实冲突时,优先相信测试和代码,而不是相信自然语言解释。
所以 HITL 不是让人凭感觉判断 AI 说得对不对,而是让人追问:证据在哪里?
对不同任务来说,evidence 可以不同:
- 修 bug:复现日志 + 修复后的测试结果;
- 做功能:最小可运行链路;
- 改架构:状态机和模块衔接是否能跑通;
- 写文档:文档描述是否能对应到代码事实;
- 做 Agent:工具调用、权限、状态、结果回灌是否有可验证路径。
没有 evidence 的结论,只是自然语言上的自洽。
HITL 第五层:人参与完成判断
AI 很容易“自我宣布完成”。
在普通问答里,这可能问题不大。但在工程项目里,项目是否完成,不应该由模型一句“已完成”决定。
完成至少要回答:
- 主链路有没有跑通?
- 是否有测试结果?
- 模块之间是否真的衔接?
- 状态是否能解释?
- 失败路径是否可处理?
- 人是否能接手维护?
这些问题是人必须参与判断的。
我以前很容易被 AI 的完成话术影响:它说已经整理好了、实现好了、接好了,我就以为事情差不多了。但后来发现,只要没有测试结果,没有最小闭环,没有可解释的状态流,它说的“完成”就不可靠。

“我会稳稳地接住你”
所以 HITL 的最后一层,是交付验收。
人不需要替 AI 写完所有代码,但人必须判断“这件事是否真的完成”。
这也是我从 NeoCode 里学到的一个工程经验:
AI 可以加速实现,但不能替我承担完成定义。
关于D2A
D2A 不只是生成文档,而是把架构分析变成一个有状态、多 Skill、可恢复的练习流程。它有外层的大 loop,也有每个分析节点内部的小 loop:AI 提问,人补充;AI 分析,人回答;人发现误解,再回到代码和文档修正。
这让我意识到,Human-in-the-Loop 的重点不是“人类是否参与了一次确认”,而是“人是否持续参与了理解的形成”。
这和我做 NeoCode 的教训是一致的。
如果人只是把 AI 当成方案生成器,项目很容易进入一种危险状态:AI 不断补复杂度,人不断被动接受,最后系统看起来越来越完整,但人越来越无法理解。
而真正有效的循环应该是:
人提出目标
-> AI 给出拆解
-> 人裁剪边界
-> AI 给出实现
-> 人校验证据
-> AI 修正方案
-> 人判断完成
这个循环里,AI 很重要,但人不能退出。
AI 当然能提高效率。它能读代码、写草稿、生成方案、补测试、整理文档、解释错误。没有 AI,很多事情我可能根本推不动。
但 AI 越强,人越不能只做旁观者。
因为当 AI 进入架构设计和项目实现时,它不仅在写代码,也在不断替你做隐含决策:
- 要不要引入一个模块;
- 要不要新增一个状态;
- 要不要做一层抽象;
- 要不要加一个兜底;
- 要不要把当前问题推给未来扩展。
如果人不参与这些决策,就会出现我在 DAG 里遇到的问题:AI 看似在推进,实际上在扩大系统的不确定性。
所以我现在更愿意这样定义 AI 时代的开发者角色:
人不是每一行代码的手工劳动者,而是目标定义者、边界裁剪者、架构取舍者、证据校验者和完成判断者。
这不是降低人的价值,反而是把人的价值放到了更核心的位置。
人不能只是 AI 开发流程里的触发器
助教有一句话点醒我了,一个人在使用AI的过程中,不应该只作为Trigger(触发器)。
好的 Human-in-the-Loop 不是让人一直点确认,也不是把 AI 降级成只会执行命令的工具。
- 目标不清时,人要参与定义;
- 边界发散时,人要参与裁剪;
- 架构分叉时,人要参与取舍;
- 状态膨胀时,人要参与收敛;
- 结论出现时,人要追问 evidence;
- Agent 宣布完成时,人要参与验收。
人不是 AI 开发流程里的阻碍。
人是让系统不失控的关键回路。
AI 可以帮人更快地走,但人必须决定往哪里走、为什么这样走,以及走到哪里。
(完)
评论
评论组件加载中…