1. 控制论视角下的现代软件工程变革
在当今快速发展的技术环境中,软件工程正在经历一场深刻的范式转变。从Kubernetes的声明式协调到AI Agent的自主编程,我们见证着工程系统逐渐演变为需要精心设计、持续观测和动态校正的闭环系统。这种转变不仅改变了我们构建软件的方式,更从根本上重塑了工程师的角色定位。
1.1 Harness Engineering的兴起
2025年下半年以来,随着Claude Code、Codex等Coding Agent的快速普及,工程师们的工作重心发生了显著变化。数据显示,工程师花费在"亲手写代码"上的时间减少了近40%,而投入在"构建稳定产出环境"上的时间则增加了65%。这种转变催生了一种全新的工程实践——Harness Engineering。
Harness(挽具)这个比喻十分贴切。就像挽具不替马奔跑但控制方向和传递力量一样,Harness Engineering不是替代模型完成任务,而是为模型设计一套控制系统,引导其能力向预定目标稳定输出。这套系统包含多个关键组件:
- 架构文档:定义系统的结构约束和设计原则
- AGENTS.md指令文件:明确任务执行的标准和规范
- 自动化测试:提供即时反馈的验证机制
- 自定义Linter:编码风格和架构规则的守护者
- CI/CD管道:持续集成和交付的自动化流程
这些组件共同构成了一个完整的运行环境,确保Agent能够可靠地产出符合预期的代码。但Harness Engineering的深层意义远不止于工具链的集合,它代表着工程师角色的根本性转变。
1.2 工程师角色的三次上移
观察AI辅助开发的发展历程,我们可以清晰地看到工程师角色经历了三个阶段的上移:
Prompt Engineering阶段(2023年前后)
这个阶段的核心是学习如何与LLM有效对话。工程师需要掌握各种提示技巧:角色设定、few-shot示例、思维链推理、格式约束等。典型提示如:"你是一个资深软件工程师,现在需要解决...问题"。
Context Engineering阶段(2024年)
随着模型能力提升和上下文窗口扩大,重点转向如何组织模型的上下文信息。以Cursor为代表的工具将人类、模型与IDE能力深度整合,通过@标记、快捷键等方式动态补充上下文。关键挑战在于平衡信息量——太少会导致模型猜测,太多则会淹没关键信号。
Harness Engineering阶段(2025年至今)
当Agent能够自主执行多步操作时,焦点转向如何设计完整的反馈控制系统。这包括:
- 可观测性工具栈(日志、指标、追踪)
- 产品上下文构建
- 架构约束编码(通过lint、测试等)
- 权限管理和执行边界控制
这种演进不是简单的替代关系,而是层层递进。Prompt仍然是任务入口,Context确保信息获取,Harness则将二者整合进可观测、可验证的系统闭环中。工程师的角色从指令发出者,到信息组织者,最终成为系统设计者。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 控制论框架解析
2.1 控制论的基本原理
控制论(Cybernetics)由诺伯特·维纳在1948年系统提出,研究的是如何在动态环境中通过反馈维持系统稳定。一个典型的控制系统包含五个核心组件:
- 设定点(Set Point):系统的目标状态
- 传感器(Sensor):感知实际状态
- 比较器:计算目标与实际的偏差
- 控制器:决定纠偏策略
- 执行器(Actuator):实施纠偏动作
这些组件形成的闭合回路使系统能够在扰动中持续逼近期望状态。控制论不关心单个组件有多"聪明",而是关注整个系统如何通过反馈实现稳定。
2.2 Kubernetes的控制论实践
Kubernetes是现代工程中控制论应用的典范。其核心协调逻辑可以简化为:
go复制for {
desired := getDesiredState() // 读取YAML声明
actual := getActualState() // 观察集群状态
diff := compare(desired, actual)
if diff != empty {
reconcile(diff) // 执行调谐
}
wait(syncPeriod) // 等待下一轮
}
这种声明式协调彻底改变了基础设施管理方式。工程师不再需要手动执行具体操作,而是定义"什么是正确状态",由控制器自动维持。当节点故障、流量波动等扰动发生时,系统能够自我修复。
Kubernetes的成功证明了控制论在软件工程中的价值。现在,类似的原理正被应用于管理AI Agent与代码库的交互过程。
2.3 Harness Engineering的控制论映射
将控制论框架应用于Harness Engineering,我们可以建立如下对应关系:
| 控制论组件 | Harness Engineering实现 |
|---|---|
| 设定点 | AGENTS.md、架构文档、测试规范 |
| 传感器 | 编译器、测试套件、自定义Linter |
| 控制器 | CI规则+LLM推理 |
| 执行器 | 文件编辑器、Shell、Git等工具接口 |
| 反馈回路 | 代码生成→测试→修复的迭代循环 |
这种映射不是严格的数学同构,而是提供了有价值的分析框架。理解这一点,我们就能明白:Harness Engineering本质上是在构建一个让Agent行为持续收敛的控制系统。
3. Harness设计实践要点
3.1 明确设定点:定义可验证的目标
控制系统没有清晰的设定点就无法收敛。在Harness Engineering中,这意味着必须将模糊的工程"品味"转化为机器可验证的标准。例如,定义"取消订单"接口需求时,不应只说"加一个取消接口",而应明确:
markdown复制- 新增 `POST /api/orders/{id}/cancel` 接口
- 仅允许取消 `PENDING_PAYMENT` 和 `PAID_PENDING_REVIEW` 状态订单
- 错误响应:
- 404(订单不存在)
- 409(状态不允许)
- 401/403(未授权)
- 审计要求:
- 必须写入order_events表
- 包含cancel_reason、cancelled_by、cancelled_at字段
- 兼容性要求:
- 不得修改现有接口响应结构
- 测试覆盖:
- 成功取消
- 重复取消
- 越权取消
- 并发请求
这种明确、可验证的规范为Agent提供了清晰的收敛目标。OpenAI的内部实践表明:不把"好"的定义外化为机器可读形式,Agent会在第一百次运行时犯与第一次相同的错误。
3.2 增强传感器覆盖
传统工程中的传感器(编译器、测试等)只能检查机械可验证的属性。Harness Engineering在两个方向扩展了传感器能力:
方向一:更多机械检查
- 自定义Linter检查架构分层(如UI层不得直接导入Service层)
- 结构性测试验证模块边界
- 依赖方向检查防止循环引用
方向二:语义层面检查
- AI辅助审查设计原则符合性
- 检测"AI糟粕"(低质量生成模式)
- 评估代码风格一致性
OpenAI的实践是将日志、指标、追踪和浏览器能力直接暴露给Codex,使"将启动时间降至800ms以下"这类目标成为可观测、可优化的闭环任务。
3.3 设计可操作的误差信号
好的误差信号应直接指导修正行为。对比以下两种反馈:
差反馈:
code复制architecture violation
好反馈:
code复制HTTP Handler层禁止直接依赖repository包。请将数据访问逻辑移动到service/usecase层,参考docs/architecture/layers.md,并运行:
golangci-lint run && go test ./...
OpenAI在自定义Linter报错中直接嵌入修复指引,大幅提高了纠偏效率。这种设计将"发现问题"和"解决问题"的距离缩到最短。
3.4 精细化的执行器控制
执行器控制的核心是权限管理。现代Coding Agent通常提供多级权限模式:
- 只读模式:查看代码、检索信息,无修改权限
- 沙箱模式:在工作区内修改代码、运行测试,但限制:
- 文件系统访问范围
- 网络连接
- 进程操作
- 审批模式:高风险操作需人工确认,包括:
- 生产数据库访问
- 外部API调用
- 批量删除操作
- 主分支推送
Claude Code和Codex都采用了类似的权限策略。这种分层控制不是限制Agent能力,而是确保系统在安全边界内稳定运行。
4. 系统演进与长期维护
4.1 代码库作为记忆系统
Agent需要持久的记忆系统来存储影响决策的知识。有效的实现方式包括:
- 精简导航:
AGENTS.md提供规则入口 - 详细文档:
docs/目录保存业务背景和架构决策 - 架构决策记录(ADR):记录重要选择的上下文和权衡
OpenAI使用专门的文档Agent定期扫描文档与代码的不一致,并提交修复PR。这种自动化维护确保了记忆系统的时效性。
4.2 多层反馈回路设计
单一反馈回路难以应对复杂工程需求,应建立多时间尺度的反馈层级:
| 回路类型 | 时间尺度 | 检查内容 | 工具示例 |
|---|---|---|---|
| 短回路 | 秒~分钟级 | 语法/风格/单元测试 | Linter、单元测试框架 |
| 中回路 | 分钟~小时级 | 集成/架构/界面验证 | 集成测试、浏览器自动化 |
| 长回路 | 天~周级 | 线上指标/用户反馈/架构治理 | 监控系统、事故复盘会议 |
这种分层设计使问题能够在合适的抽象层级被捕获和修复,避免局部优化导致系统级偏离。
4.3 抵抗熵增的治理策略
Agent会快速复制代码库中的模式——包括不良模式。对抗熵增的策略包括:
- 初始化约束:通过脚手架预置:
- 标准目录结构
- 技术栈选择
- 架构原则文档
- 定期扫描:检测:
- 架构漂移
- 过期规则
- 临时方案扩散
- 规则更新:将重复问题沉淀为:
- 新测试用例
- Linter规则
- 架构约束
没有持续治理,代码库会迅速劣化。Harness Engineering将治理纳入了日常工程实践。
5. 实践启示与边界认知
5.1 Harness Engineering的适用场景
控制论框架最适合目标明确、可验证的工程任务,例如:
- API开发
- 数据管道构建
- 系统迁移
- 缺陷修复
而对于探索性、创造性工作(如早期原型设计),过度harness化可能过早限制解决方案空间。
5.2 避免过度约束
设计harness时需要警惕:
- 检查膨胀:过多规则可能导致Agent"面向检查编程"
- 冲突约束:相互矛盾的规则会使Agent陷入无效循环
- 创新抑制:过于严格的约束可能阻碍意外发现的好方案
好的harness设计应遵循"最小必要约束"原则,在稳定性和灵活性间保持平衡。
5.3 LLM的非线性特性
与传统控制系统不同,LLM具有显著的非线性特征:
- 微小上下文变化可能导致输出大幅波动
- 难以严格保证收敛性
- 行为边界不如传统系统明确
因此,Harness Engineering更关注实用稳定性而非数学确定性,这是与经典控制论的重要区别。
6. 成为系统舵手
Harness Engineering代表着软件工程的根本性转变。优秀工程师的标准从"写出正确代码"变为"设计能可靠产出正确代码的系统"。这要求我们掌握新的技能组合:
- 系统思维:将工程问题建模为可控系统
- 约束设计:定义清晰、可验证的目标状态
- 反馈设计:构建多层次观测和纠偏机制
- 边界管理:平衡自治与控制,安全释放Agent能力
正如Kubernetes改变了基础设施管理,Harness Engineering正在重塑软件开发。工程师的角色从直接操作者,演进为系统设计者和舵手。在这个新范式中,最大的价值不再来自执行效率,而来自定义"什么是正确"的判断力,以及将这种判断编码进系统的能力。
