
Harness 和 Loop:经常被混为一谈的两个概念

Harness 和 Loop 经常被混在一起说,但它俩管的事差着一层。
用 Addy 的三个动词把界线划出来。
核心差异
┌─────────────────────────────────────────────────────────┐
│ Harness vs Loop 的三层区别 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ 1. 在定时器上跑 │ │
│ │ Harness:你来触发 │ │
│ │ Loop:到点自己醒 │ │
│ └───────────────────┬─────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────────┐ │
│ │ 2. 孵化小帮手 │ │
│ │ Harness:单个 Agent 怎么武装 │ │
│ │ Loop:一群 Agent 怎么协作、谁监督谁 │ │
│ └───────────────────┬─────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────────────┐ │
│ │ 3. 自我喂食 │ │
│ │ Harness:每次运行是独立的 │ │
│ │ Loop:上轮结果 → 下轮输入(跨越对话的记忆) │ │
│ └───────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘第一层区别:在定时器上跑
Harness:你来触发
Harness 武装的是一次运行,得你来触发。
用户:「帮我审查这个 PR」
↓
Harness:执行审查任务
- 读取代码
- 运行静态分析
- AI 审查
- 生成报告
↓
任务结束,等待下一次手动触发Harness 的生命周期:
触发 → 执行 → 输出 → 停止
┌──────────┐
│ 触发 │ ← 用户手动按按钮
└────┬─────┘
↓
┌──────────┐
│ 执行 │ ← Harness 在这里工作
└────┬─────┘
↓
┌──────────┐
│ 输出 │
└────┬─────┘
↓
┌──────────┐
│ 停止 │ ← 等待下次手动触发
└──────────┘Loop:到点自己醒
Loop 给它装了个定时器,到点自己醒、自己开工,不用你按按钮。
这是「自己一遍遍跑」的第一层意思。
Loop 每天凌晨 2 点自动醒来:
↓
步骤 1:扫描所有新增的 PR
↓
步骤 2:对每个 PR 调用 Harness 执行审查
↓
步骤 3:汇总审查结果
↓
步骤 4:生成日报并发送到 Slack
↓
步骤 5:保存进度,等待明天凌晨 2 点Loop 的生命周期:
定时触发 → 执行 → 输出 → 保存状态 → 等待下一次触发
┌──────────┐
│ 定时触发 │ ← Cron / 调度系统自动触发
└────┬─────┘
↓
┌──────────┐
│ 执行 │ ← 调用 Harness 完成任务
└────┬─────┘
↓
┌──────────┐
│ 输出 │
└────┬─────┘
↓
┌──────────┐
│ 保存状态 │ ← 记录进度、结果、待办事项
└────┬─────┘
↓
┌──────────┐
│ 等待 │ ← 等待下一次定时触发
└──────────┘实战对比
场景:自动化代码审查
纯 Harness 方案:
# 手动执行
npx ai-code-review pr-123
# 或者在 GitHub Action 中手动触发Loop 方案:
# 每小时自动扫描
schedule:"
- cron: "0 * * * *"
steps:
- name: 扫描新增 PR
run: python scan_new_prs.py
- name: 批量审查
run: python batch_review.py
- name: 生成报告
run: python generate_report.py
- name: 发送通知
run: python send_notification.py关键区别:
- Harness:每次运行是孤立的,需要你手动触发
- Loop:有调度机制,到点自动运行,并且知道「上次运行到哪里了」
第二层区别:孵化小帮手
Harness:单个 Agent 怎么武装
Harness 关心单个 Agent 怎么武装。
一个 Harness 的典型配置:
┌─────────────────────────────────────┐
│ 单个 Agent 的 Harness │
├─────────────────────────────────────┤
│ │
│ ┌───────────────────────────────┐ │
│ │ 工具集 │ │
│ │ ├── 代码执行沙箱 │ │
│ │ ├── 文件读写 │ │
│ │ ├── Web 搜索 │ │
│ │ └── API 调用 │ │
│ └───────────────┬───────────────┘ │
│ ↓ │
│ ┌───────────────────────────────┐ │
│ │ 权限控制 │ │
│ │ ├── 允许访问的资源 │ │
│ │ ├── 禁止执行的操作 │ │
│ │ └── 需要确认的敏感操作 │ │
│ └───────────────┬───────────────┘ │
│ ↓ │
│ ┌───────────────────────────────┐ │
│ │ 终止条件 │ │
│ │ ├── 任务完成的标志 │ │
│ │ ├── 最大迭代次数 │ │
│ │ └── 超时限制 │ │
│ └───────────────────────────────┘ │
│ │
└─────────────────────────────────────┘Harness 的关注点:
- 给这个 Agent 配什么工具?
- 允许它执行什么操作?
- 什么情况下算任务完成?
- 如何保证单次运行的安全?
Loop:一群 Agent 怎么协作
Loop 关心一群 Agent 怎么协作、谁监督谁。
一个 Loop 转起来,会自己分出子 Agent 去干并行的活。
┌─────────────────────────────────────────────────┐
│ Loop 的多 Agent 协作模式 │
├─────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ 主 Loop(Orchestrator) │ │
│ └──────────────────┬──────────────────────┘ │
│ ↓ │
│ ┌─────────┬──────────┬──────────┐ │
│ ↓ ↓ ↓ ↓ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ 起草 │ │ 审查 │ │ 测试 │ │ 部署 │ │
│ │Agent │ │Agent │ │Agent │ │Agent │ │
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │ │
│ └────────┴────────┴────────┴──┐ │
│ ↓ │ │
│ ┌────────────────┐ │ │
│ │ 结果汇聚 │ │ │
│ │ 汇总报告 │ │ │
│ └────────────────┘ │ │
│ ↓ │ │
│ ┌────────────────┐ │ │
│ │ 质量检查 Agent │ │ │
│ │ (监督者) │ │ │
│ └────────────────┘ │ │
│ ↓ │ │
│ 如果不通过 │ │
│ ↓ │ │
│ 退回重新执行 │ │
│ │
└─────────────────────────────────────────────────┘典型协作模式:
1. 并行分工
主 Loop:帮我写一个技术博客
↓
分支出 3 个子 Agent:
- 起草 Agent:负责写初稿
- 审查 Agent:负责挑问题、提意见
- 配图 Agent:负责生成配图
↓
汇聚:合并初稿 + 修改意见 + 配图
↓
输出:完成的博客文章2. 串行接力
主 Loop:帮我完成一个功能开发
↓
步骤 1:设计 Agent(设计技术方案)
↓
步骤 2:编码 Agent(根据设计写代码)
↓
步骤 3:测试 Agent(写测试用例并运行)
↓
步骤 4:审查 Agent(代码审查)
↓
步骤 5:部署 Agent(打包发布)
↓
输出:完整的功能交付3. 监督反馈
主 Loop:批量处理 100 个文档
↓
分出 10 个处理 Agent(每人处理 10 个)
↓
分出 1 个监督 Agent:
- 检查每个处理 Agent 的输出质量
- 发现不合格 → 退回重做
- 统计完成进度
↓
汇聚:所有处理完成的文档 + 质量报告实战对比
场景:技术博客生产流水线
纯 Harness 方案(手动):
# 步骤 1:手动写大纲
outline_article.sh "AI 工程四层进化"
# 步骤 2:手动起草
draft_article.sh outline.md > draft.md
# 步骤 3:手动审查
review_article.sh draft.md > review.md
# 步骤 4:手动修改
revise_article.sh draft.md review.md > final.md
# 步骤 5:手动配图
generate_images.sh final.md
# 步骤 6:手动发布
publish_article.sh final.mdLoop 方案(自动化):
Loop 配置:
name: "博客生产流水线"
schedule:
- cron: "0 9 * * *" # 每天早上 9 点
steps:
- name: 选题
agent: topic-selector
output: topics.json
- name: 批量起草
agent: article-writer
input: topics.json
parallel: true
output: drafts/
- name: 批量审查
agent: article-reviewer
input: drafts/
parallel: true
output: reviews/
- name: 修改
agent: article-reviser
input: [drafts/, reviews/]
output: articles/
- name: 配图
agent: image-generator
input: articles/
parallel: true
output: articles_with_images/
- name: 质量检查
agent: quality-checker
input: articles_with_images/
on_failure: retry # 不合格则退回修改
- name: 发布
agent: publisher
input: articles_with_images/
output: published/关键区别:
- Harness:你手动协调每个步骤,手动在每个步骤之间传递结果
- Loop:Loop 自己负责调度、分工、汇聚、监督,你只看最终结果
第三层区别:自我喂食
Harness:每次运行是独立的
Harness 的每次运行是独立的,上下文不继承。
第一次运行:
输入:"帮我审查这个文件"
执行:扫描文件 → 发现问题 → 生成报告
输出:审查报告
结束:所有状态清空
第二次运行:
输入:"帮我审查那个文件"("那个"是什么?)
执行:❌ 不知道"那个"是什么,因为上次运行的状态已经丢失问题:
- 每次运行从零开始
- 无法记住上次运行的结果
- 无法基于上次的发现继续工作
Loop:上轮结果 → 下轮输入
Loop 跑出来的结果,会被它自己当成下一轮的输入。
昨天发现的问题写进一个文件,今天醒来先读这个文件,接着干。
它有了跨越单次对话的记忆,所以才叫循环,而不是重复运行了很多次的一次性任务。
这是最关键的一点。
Day 1:Loop 运行
↓
扫描代码库 → 发现 10 个问题 → 写入 issues.json
↓
保存状态:{"found_issues": 10, "last_scan": "2026-06-17"}
Day 2:Loop 运行
↓
读取状态:{"found_issues": 10, "last_scan": "2026-06-17"}
↓
扫描代码库 → 发现 12 个问题(2 个新增)
↓
对比:issues.json vs 新扫描结果
↓
生成增量报告:新增 2 个问题,已修复 3 个问题
↓
更新状态:{"found_issues": 12, "last_scan": "2026-06-18"}
Day 3:Loop 运行
↓
读取状态:{"found_issues": 12, "last_scan": "2026-06-18"}
↓
...(继续基于最新的状态工作)Loop 的状态流转:
┌──────────────┐
│ 第 N 轮运行 │
└──────┬───────┘
↓
┌──────────────┐
│ 读取上次状态 │ ← 从文件/数据库/缓存加载
└──────┬───────┘
↓
┌──────────────┐
│ 执行任务 │
└──────┬───────┘
↓
┌──────────────┐
│ 生成新结果 │
└──────┬───────┘
↓
┌──────────────┐
│ 保存新状态 │ ← 写入文件/数据库/缓存
└──────┬───────┘
↓
┌──────────────┐
│ 第 N+1 轮运行 │ ← 下次运行从这里开始
└──────────────┘实战对比
场景:自动化安全扫描
纯 Harness 方案(无记忆):
# 第一次扫描
npx security-scan > day1-report.txt
# 第二次扫描(无法知道哪些问题是新的)
npx security-scan > day2-report.txt
# 问题:day2-report.txt 包含所有问题,包括 day1 已经发现的
# 无法区分新增、修复、持续存在的问题Loop 方案(有记忆):
Loop 配置:
name: "每日安全扫描"
schedule:
- cron: "0 2 * * *" # 每天凌晨 2 点
state:
type: file
path: security-scan-state.json
steps:
- name: 读取上次状态
run: python load_state.py
- name: 执行扫描
run: python scan.py
- name: 对比差异
run: python diff.py
- name: 生成增量报告
run: python report.py
output: |
新增问题:3 个
已修复:5 个
持续存在:12 个
- name: 保存新状态
run: python save_state.py
- name: 发送通知
run: python notify.py输出示例:
Day 1 报告:
发现问题:20 个
Day 2 报告:
新增问题:3 个
已修复:5 个
持续存在:12 个
净增:-2 个 ✅
Day 3 报告:
新增问题:1 个
已修复:4 个
持续存在:9 个
净增:-3 个 ✅关键区别:
- Harness:每次运行是孤立的,无法知道"上次发生了什么"
- Loop:每次运行都基于上次的状态,能够追踪变化趋势
Addy 的点睛之笔
自动化才让一个 Loop 成为真正的 Loop,
而不是你手动跑过一次的某次运行。
少了「自己醒、自己接力」,
剩下的就只是把 Harness 手动按了很多遍。
三层区别总览
| 维度 | Harness | Loop |
|---|---|---|
| 触发方式 | 手动触发 | 自动定时 / 事件驱动 |
| 运行次数 | 一次 | 多次循环 |
| Agent 数量 | 单个 Agent | 多 Agent 协作 |
| 关注点 | 单个 Agent 怎么武装 | 一群 Agent 怎么协作 |
| 状态管理 | 每次运行独立 | 跨轮次状态继承 |
| 记忆能力 | 无 | 有(跨越对话的记忆) |
| 自主性 | 低 | 高 |
| 调度机制 | 无 | Cron / Event-Driven |
| 监督机制 | 无 | 质量检查 / 退回重做 |
| 输出特点 | 单次任务结果 | 时间序列的增量报告 |
实践建议
什么时候用 Harness?
场景:单次任务,需要人工决策。
- 需要你手动选择输入
- 需要你审查结果
- 需要你决定下一步怎么做
- 任务不是重复性的
例子:
- 审查一个特定的 PR
- 生成一份特定的报告
- 调试一个特定的问题
什么时候用 Loop?
场景:重复性任务,需要自动化。
- 任务是重复性的(每天 / 每小时)
- 需要追踪变化趋势
- 需要多 Agent 协作
- 需要自动重试和恢复
例子:
- 每日安全扫描
- 批量文档处理
- 自动化测试流水线
- 自动化运维
Harness + Loop 的组合
最佳实践:Loop 调用 Harness。
Loop 负责调度和状态管理:
- 定时触发
- 扫描待处理任务
- 分发任务给多个 Harness
- 汇聚结果
- 保存状态
Harness 负责单次任务执行:
- 读取输入
- 调用工具
- 生成输出
- 返回结果
Loop ↔ Harness:
Loop 提供输入 → Harness 执行 → 返回结果 → Loop 汇总架构图:
┌─────────────────────────────────────────────────┐
│ Loop(调度层) │
├─────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ 定时器 / 事件监听 │ │
│ └──────────────────┬──────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────┐ │
│ │ 任务扫描与分发 │ │
│ └──────────────────┬──────────────────────┘ │
│ ↓ │
│ ┌─────────┬──────────┬──────────┐ │
│ ↓ ↓ ↓ ↓ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │任务 1 │ │任务 2 │ │任务 3 │ │任务 4 │ ← Harness 执行层
│ │Harness│ │Harness│ │Harness│ │Harness│
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │ │
│ └────────┴────────┴────────┴──┐ │
│ ↓ │ │
│ ┌────────────────┐ │ │
│ │ 结果汇聚 │ │ │
│ └────────────────┘ │ │
│ ↓ │ │
│ ┌────────────────┐ │ │
│ │ 状态保存 │ │ │
│ └────────────────┘ │ │
│ │
└─────────────────────────────────────────────────┘关键洞察
三层区别,一层比一层深:
在定时器上跑
Harness:你来触发
Loop:到点自己醒
↓ 自己一遍遍跑的第一层意思
孵化小帮手
Harness:单个 Agent 怎么武装
Loop:一群 Agent 怎么协作、谁监督谁
↓ 并行分工、串行接力、监督反馈
自我喂食
Harness:每次运行是独立的
Loop:上轮结果 → 下轮输入
↓ 跨越对话的记忆,持续追踪变化收尾金句:
- 在定时器上跑:Harness 你来触发,Loop 到点自己醒
- 孵化小帮手:Harness 关心单个 Agent 怎么武装,Loop 关心一群 Agent 怎么协作
- 自我喂食:Harness 每次运行独立,Loop 上轮结果成为下轮输入
- 自动化才让一个 Loop 成为真正的 Loop,而不是你手动跑过一次的某次运行
- 少了「自己醒、自己接力」,剩下的就只是把 Harness 手动按了很多遍
Harness 和 Loop:
Harness 是一次运行的能力武装
Loop 是一整套自动跑的循环系统
前者管「做一次」,后者管「持续做」。
Harness vs Loop
经常被混为一谈的两个概念
