Agent Loop、Harness、Runtime 到底是什么关系?
这几年 Agent 讨论里,有几个词特别容易搅在一起:Agent Loop、Harness、Runtime。
很多文章会这么写:
Agent Runtime = 一个 while loop + tools
或者反过来:
Harness 就是 Runtime。
再或者:
有了 MCP,再接一个 agent framework,就差不多是生产级 Agent 了。
我不太赞同。
不是因为这些说法完全错,而是它们都只说中了某一层。工程上最怕这种'局部正确'。局部正确的词一旦进了架构图,后面权限、trace、checkpoint、eval、上下文预算都不知道该挂在哪里。项目越做越大,大家开始用同一个词吵不同的事。
先给我的划分:
Agent Loop 负责让模型一轮轮地想和做。
Harness 负责给这个循环加约束、工具、上下文和评测。
Runtime 负责把一次 Agent 执行变成可恢复、可观测、可治理的系统过程。
这三个词不是同义词。它们像三层不同厚度的系统边界。
为什么现在必须把词讲清楚
以前做 LLM 应用,很多系统就是一次请求、一次回答。最多加 RAG、加函数调用、加缓存。边界相对简单。
Agent 不一样。
它会反复调用模型。会拿工具结果继续决策。会读文件、写文件、执行命令、访问外部系统。长一点的任务可能跑十几步、几十步,中途经历超时、权限确认、上下文压缩、模型降级、工具失败和用户打断。
这时候,如果你把所有东西都叫 'agent',设计会很快失焦。
Anthropic 在 "Building effective agents" 里把 workflow 和 agent 区分得比较清楚:workflow 是预先编排 LLM 和工具的系统;agent 是模型自己动态决定流程和工具使用的系统。这个划分有帮助,但它还没解决工程实现里的另一层问题:当 agent 真要运行起来,谁来管理状态、权限、预算、恢复和观测?
LangChain 生态现在也开始把层次拆得更细。LangGraph 文档里,Deep Agents 被放在 harness 层,LangChain 是 framework,LangGraph 是 runtime,LangSmith 是 platform。这套分层很有意思,至少说明社区已经意识到:光说 agent framework 不够了。
OpenAI Agents SDK 也有类似信号。文档里会区分 'agent loop 由 SDK 管理' 和 'Responses API 让你自己管理每一轮'。这其实就是在提醒开发者:tool call roundtrip 不是一行 API 调用结束的事,循环控制本身是系统责任。
所以今天讲 Loop、Harness、Runtime,不是术语洁癖。是为了让架构能落地。
Agent Loop:最小控制结构
Agent Loop 是最小骨架。
它解决一个问题:模型不是一次性给最终答案,而是可以在多轮中决定下一步。
一个简化版 loop 长这样:
for (let step = 0; step < maxSteps; step++) {
const response = await model.generate({ messages, tools });
if (response.type === "final") {
return response.text;
}
const results = await runTools(response.toolCalls);
messages.push(response, ...results);
}
这段代码已经能演示很多东西。模型可以先读文件,再搜索,再执行测试,最后回答。ReAct 的味道也在这里:reasoning 和 acting 交替出现,工具 observation 会影响下一步。
但它太裸。
裸 loop 通常缺这些东西:
- 工具参数校验。
- 权限判断。
- 工具失败分类。
- 输出截断策略。
- 重复调用检测。
- token budget。
- trace。
- checkpoint。
所以我更愿意把 Agent Loop 定义成:
Agent Loop 是模型、工具和观察结果之间的回合控制结构。
它不天然等于生产系统。它只是生产系统里最中间的那根轴。
Harness:让模型更能干,也更受控
Harness 这个词有点别扭,中文不好翻。直接叫'套件''缰绳''增强层'都差点意思。
我会这样理解:
Harness 是围绕 Agent Loop 的能力和约束层。
它给 loop 提供:
- 工具集合。
- system prompt 和任务约束。
- 上下文装载策略。
- memory。
- planner。
- verifier。
- eval case。
- guardrail。
如果 Loop 是发动机转起来,Harness 就是让发动机能接上车架、仪表、刹车和测试台。
举个 coding agent 的例子。一个裸 loop 只知道模型想调用 read_file。Harness 会决定:
- 当前任务应该暴露哪些工具。
- 文件系统范围是不是限制在 workspace 内。
read_file的输出最多给模型多少字符。- 是否先用 repo map 帮模型找入口。
- 模型最终回答前是否必须引用观察结果。
- 这类任务在 eval 里怎么判定成功。
Harness 往往是体验差异最大的地方。两个系统都用了同一个模型、同样有 tool calling,但一个会像实习生一样乱翻文件,另一个能像熟悉项目的工程师那样先找入口、再读局部、最后改最小 diff。差别通常不只在模型,而在 harness。
不过 Harness 仍然不是完整 Runtime。
Harness 可以让 Agent 更聪明、更稳一点,但它未必负责持久化状态、崩溃恢复、跨 run 审计、成本账单、权限记录、trace 归档和 CI 回归门禁。这些是 Runtime 的地盘。
Runtime:系统责任的边界
Runtime 这个词最容易被说薄。
很多人说 runtime,其实只是在说 loop runner。我的定义更重:
Agent Runtime 是承载用户意图、模型、工具、状态、权限、预算、观测和恢复的运行系统。
它至少要回答这些问题:
- 这次用户请求对应哪个 run?
- 当前 run 到了第几个 step?
- 模型本轮看到了哪些上下文?
- 工具调用经过了哪些校验?
- 用户是否批准了高风险动作?
- 工具失败后是重试、降级、停止,还是让模型重新规划?
- 输出是否被截断,artifact 存在哪里?
- 任务中断后从哪个 checkpoint 恢复?
- 这次失败是模型错、工具错、上下文错,还是策略错?
- 这个改动是否通过 eval harness 回归?
这些问题很无聊。也正因为无聊,demo 里经常没有。
生产系统偏偏就死在这些无聊问题上。
三层放在一张图里
我会把它们画成这样:
Agent Runtime
│
├─ Run / Session / State
├─ Budget / Policy / Permission
├─ Trace / Checkpoint / Eval
│
└─ Harness
│
├─ Context Builder
├─ Memory
├─ Tool Selection
├─ Guardrails
├─ Verifier
│
└─ Agent Loop
│
├─ Model Call
├─ Tool Call
├─ Observation
└─ Stop Reason
也可以换成一句更工程化的话:
Loop 是控制流。
Harness 是能力边界。
Runtime 是执行系统。
这个分法有个好处:出了问题更容易归因。
看到问题时,应该查哪一层
比如 Agent 一直调用同一个工具。
你可以先查 Loop:有没有 max steps?有没有 repeated tool call stop reason?有没有 same error detection?
再查 Harness:工具描述是不是诱导模型反复调用?observation 有没有告诉模型'这个路径不存在'?工具选择是不是每一轮都暴露太多无关工具?
最后查 Runtime:trace 里能不能看到每次调用的 input hash?是否记录了停止原因?eval 里有没有覆盖'重复调用同一工具'的回归用例?
再比如 Agent 读错文件。
Loop 层只能看到它调用了 read_file。Harness 层要看 repo map、文件摘要、context builder 和 tool selection。Runtime 层要看这次 run 的 context debug report:模型到底有没有看见正确文件?有没有被旧摘要误导?有没有因为 token budget 丢掉用户约束?
再比如 MCP 工具越权。
这就不是 Loop 能解决的。MCP Server 负责暴露工具,MCP Client 负责通信,但工具什么时候进入模型上下文、调用前是否审批、调用结果如何脱敏、风险等级如何覆盖远端描述,这些都要回到 Runtime 和 Harness 的边界里。
MCP 不是 Runtime,框架也不是全部
MCP 很重要。我也认为它会长期存在。
但 MCP 解决的是外部能力如何标准化接入,不是这些能力如何安全运行。一个 MCP Server 可以暴露读文件、查数据库、发请求、执行命令。它的工具列表可以动态变化,schema 也可能变化。模型看到这些工具之后,真正的风险才开始。
Runtime 需要把 MCP 工具包进自己的 Tool Registry:
type RuntimeTool = {
name: string;
source: "local" | "mcp";
inputSchema: unknown;
riskLevel: "read" | "write" | "network" | "destructive";
timeoutMs: number;
outputPolicy: ToolOutputPolicy;
approvalPolicy: ApprovalPolicy;
};
这一步不能省。不要因为工具来自某个'标准协议',就默认它安全。协议让连接更顺,治理还是你的责任。
框架也是一样。
LangGraph、OpenAI Agents SDK、Vercel AI SDK、AutoGen、CrewAI,各有自己的抽象。选框架当然重要,但你不能把框架名当架构设计。更实在的问题是:
- 它的 loop 控制在哪里?
- harness 能不能定制?
- runtime 状态能不能持久化?
- trace 能不能还原一次 run?
- 权限系统能不能接你自己的业务策略?
- checkpoint 和 resume 是框架能力,还是要你自己补?
- eval 能不能进 CI?
这些问题问清楚,比'这个框架是不是最火'有用。
我建议团队内部统一一套说法
如果你们正在做 Agent 产品,建议直接把下面这套词写进设计文档。
Agent
面向目标的决策体。它根据上下文选择下一步。
Workflow
预先编排的流程。确定性强的业务路径优先走 workflow。
Tool
Runtime 暴露给模型或 workflow 的外部能力,带 schema、权限、审计和失败语义。
Agent Loop
模型、工具调用和 observation 的多轮控制结构。
Harness
围绕 loop 的增强和约束层,包括上下文、工具选择、memory、guardrail、verifier、eval case。
Agent Runtime
承载 run、state、permission、budget、trace、checkpoint、eval 和 recovery 的执行系统。
然后在设计会上强制多问一句:
这个问题应该在哪一层解决?
模型传错参数?Tool schema 和本地校验。
模型一直重试?Loop stop reason 加 Harness observation。
工具太多导致误调用?Harness tool selection。
超时后副作用不确定?Runtime tool ledger 和 idempotency。
上线后难以复盘?Runtime trace。
长任务中断后重来?Runtime checkpoint。
这样的讨论才会变清楚。
最后
很多 Agent 项目一开始都想做'更聪明的 Agent'。我现在越来越觉得,第一阶段应该先做'更诚实的 Runtime'。
它不需要假装模型永远正确。它承认模型会传错参数、会误解工具、会循环、会忘记约束,也承认工具会超时、会截断、会产生副作用。
承认这些以后,系统设计反而简单了。
Agent Loop 让 Agent 动起来。
Harness 让它有能力,也有边界。
Runtime 让它能被运行、审计、恢复和改进。
参考资料
- Anthropic Engineering: Building effective agents
- LangChain Docs: Deep Agents overview
- LangGraph Docs: Overview
- OpenAI Agents SDK Docs: Agents
- OpenAI API Docs: Function calling
- Model Context Protocol Docs: Architecture
- Model Context Protocol Docs: Tools

