搞懂 AI Agent 核心术语:Harness、Scaffold 与 Agent 架构

本文想回答的核心问题: 在快速发展的 AI Agent 领域,“Harness” 和 “Scaffold” 到底指什么?它们与模型、Agent 之间是什么关系?如何正确理解并使用这些关键术语?

如果你刚刚接触 AI Agent,或者已经在使用 Claude Code、Codex 这类工具,但依然对社区里五花八门的术语感到困惑——你不是一个人。就连在 ICLR 2026 这样的顶会上,许多研究者也在追问:“你们说的‘harness’和‘scaffold’到底是什么意思?为什么每个人解释得都不一样?”

这种概念模糊并非偶然。当一个领域以天为单位进化时,词汇往往跑得比共识快。有些词被反复借用,有些被短暂热炒后悄然消失,还有些在不同框架中指向完全不同的东西。对于刚入门的开发者,甚至对于每天跟进前沿的工程师,这都构成了实实在在的理解门槛。

本文的目标很简单:不追求给出“唯一正确”的词典式定义,而是基于当前社区最广泛的实践,为你搭建一套清晰、可用的认知模型。我们会从最基础的 模型 开始,逐步拆解 Scaffolding(脚手架)、Harness(执行框架)、Agent 等核心概念,并通过具体的场景和案例,让你真正理解这些词在开发与部署中的实际意义。

反思
在梳理这些术语的过程中,我意识到一个有趣的现象:越是基础的概念,越容易因为“大家都懂”而被随意使用。结果就是,团队内部沟通时反复确认同一句话,读论文时发现同一个词在不同段落里含义迥异。与其抱怨混乱,不如先为自己和团队建立一套清晰的术语表。这可能是提高协作效率投入产出比最高的第一步。


目录


一、模型(Model):一切的原点,但它自己不会动

核心问题:大语言模型本身就是一个 Agent 吗?

不是。一个纯粹的 LLM(比如 Claude、Qwen、GPT、DeepSeek)只是一个文本生成器:你给它一段输入,它吐出接下来的文本。它没有任何记忆(每次调用都是独立的),没有循环,不会主动去调用外部工具。它可以 表达 想要调用工具的意图(比如输出一段结构化的 JSON),但它自身无法执行这个调用。

用一句话概括:模型回答一个提示后就会停止。它需要被包裹在 Scaffolding 和 Harness 里,才能变成一个有持续行为的 Agent。

场景化理解
想象你有一个绝顶聪明的实习生(模型),他知识渊博,能写出完美的解决方案。但如果你只给他一张纸条(一次性的提示),他写完答案就停下来了,不会去查资料、不会运行代码、也不会主动追问。要想让他真正干活,你需要给他一套工作流程(Scaffolding)和一个可以执行任务的办公室环境(Harness)。

实际案例
在 Claude Code 这样的产品中,底层的 Claude 模型负责生成代码和思考过程。但如果只有模型本身,它甚至连“列出当前目录下的文件”都做不到。真正让它能够执行 ls 命令、读取文件、修改代码的,是包在外面的脚手架和执行框架。


二、Scaffolding(脚手架):模型的行为说明书

核心问题:Scaffolding 具体包含哪些东西?它和 Harness 有什么区别?

Scaffolding 是定义模型 行为方式 的层次:系统提示(system prompt)、工具描述、输出格式解析规则、跨步骤的记忆管理——总之,它是模型“看世界”和“行动”的规则说明书。

在训练或推理时,Scaffolding 决定了模型如何理解当前状态、如何决定下一步。许多产品(比如 Claude Code、Codex、Antigravity CLI)将整个非模型部分统称为 Harness。Claude Code 的官方文档就直言:“Claude Code serves as the agentic harness around Claude.” 这是一种粗粒度的用法。当我们需要更精细地讨论训练流水线时,Scaffold 与 Harness 的区别就变得重要了。

典型组成

  • 系统提示:告诉模型“你是一个编码助手”或“你是一个数学解题专家”
  • 工具描述:用自然语言或结构化 Schema 告诉模型每个工具是干什么的、需要什么参数
  • 解析逻辑:模型输出的 {"action": "read_file", "path": "main.py"} 如何被程序识别
  • 上下文管理:在多轮对话中保留哪些历史,舍弃哪些信息

场景示例
假设你在构建一个客服 Agent。Scaffolding 会包含:

  • 系统提示:“你是一个专业、礼貌的客服,只能回答关于产品保修的问题,超出范围请引导至官网。”
  • 工具描述search_kb(query) – 搜索知识库;create_ticket(title, desc) – 创建工单。
  • 解析规则:当模型输出 <tool_call>search_kb(‘保修期’)</tool_call> 时,Harness 要能准确提取工具名和参数。

反思
我在搭建第一个 Agent 时,把大部分精力花在了模型选择和提示词调优上,结果发现 Agent 的行为仍然不可控。后来才意识到,Scaffolding 中的解析逻辑和错误处理才是稳定性的基石。一个好的 Scaffold 可以让一个普通模型表现得像专家,一个糟糕的 Scaffold 则能让最先进的模型变成“胡言乱语”的机器。


三、Harness(执行框架):让模型真正动起来的引擎

核心问题:Harness 具体负责哪些执行层面的工作?为什么它值得单独拎出来讨论?

如果说 Scaffolding 是 做什么 的说明书,那么 Harness 就是 实际执行 的引擎。它负责:

  • 调用模型(发送当前上下文)
  • 处理模型返回的工具调用请求(执行函数、调用 API)
  • 将工具执行结果反馈给模型
  • 决定循环何时停止(任务完成?达到最大步数?出现错误?)

Harness 工程 是一门专门的设计学科,它关注:停止条件设计、错误处理机制、防跑飞护栏。这些在训练和推理阶段都同样重要。

实际案例:Cursor 的迭代
Cursor 团队在博客中分享了他们如何持续改进自己的 Agent Harness。早期版本中,如果模型请求打开一个不存在的文件,Harness 只是简单返回“文件不存在”,模型可能反复尝试同样的错误操作。改进后的 Harness 会检测重复错误,主动提醒模型换一种方式,或者在多次失败后自动停止并通知用户。

评估时的特殊形态:Eval Harness
当你需要评估一个模型在特定任务上的表现时,你可以构建一个 评估框架(eval harness)。它和训练时的 Harness 结构相似,但不收集训练数据,而是运行一组固定的测试场景,记录准确率、成功率等指标。EleutherAI 的 lm-evaluation-harness 就是这方面最经典的实现。

场景化对比

  • 同一个模型(比如 GPT-4)
  • Harness A:允许最多 10 步,错误时直接退出,无重试
  • Harness B:允许最多 30 步,错误自动重试 2 次,并支持中间保存状态

两个 Agent 的最终表现会天差地别。产品体验的差异往往不是模型本身,而是 Harness 的设计质量。


四、Agent(智能体):模型 + Harness 的完整系统

核心问题:究竟什么是 Agent?社区里最常见的公式是什么?

Agent 这个概念源自强化学习:它本质上是一个函数,接收观察(observation),输出动作(action)。环境接收动作,返回新观察,如此循环。LLM Agent 并没有脱离这个基本循环。

在 LLM 语境下,Agent = 模型 + Harness。如果不是模型,那就是 Harness。社区里(例如 @Vtrivedy10 和 Will Brown 的讨论)已经逐渐形成这个共识。

图解

Agent
├── Harness(执行层)
│   ├── 调用模型
│   ├── 执行工具
│   ├── 循环控制
│   └── 错误处理
└── Scaffolding(行为定义)
    ├── 系统提示
    ├── 工具描述
    ├── 解析规则
    └── 上下文管理

产品实例分析

  • Claude Code:Anthropic 提供的编码 Agent,Harness 与 Claude 模型深度绑定,专门为编码任务优化了文件读写、命令执行等工具。
  • Cursor:编辑器内嵌的 Agent,同样依赖底层模型,但它的 Harness 更注重与编辑器 UI 的融合(比如一键应用 diff)。
  • Hermes Agent:允许你插入任意模型(本地或云端),Harness 和 Scaffolding 是通用的。

重点在于:两个产品使用完全相同的底层模型,但体验可能截然不同。同样,把同一个 Harness 里的模型从 3.5 换到 4,体验也会飞跃。模型、Harness、产品是三件不同的事。

反思
过去我总以为“Agent 框架”就是指 LangChain、AutoGPT 这类库。但仔细思考后会发现,真正的 Agent 是模型 + Harness 的运行时实体。框架只是帮你构建 Harness 的工具。理清这一点后,我在调试 Agent 时会更清晰地定位问题:是模型理解错了 prompt(Scaffolding 问题),还是执行循环逻辑有 bug(Harness 问题)。


五、上下文工程(Context Engineering):模型的眼睛和记忆

核心问题:上下文工程具体管理哪些信息?短期记忆和长期记忆有什么区别?

上下文工程是设计 进入模型上下文窗口 的所有内容:每一步模型看到什么、系统提示、工具描述、对话历史、检索到的知识。它不是一个一次性的决策,而是随着 Agent 运行,Harness 动态管理的过程。

短期记忆 vs 长期记忆

  • 短期记忆:在单次运行期间保留在当前上下文中的信息,包括对话历史、工具返回结果、之前推理步骤。一旦运行结束(或上下文窗口溢出),这部分信息就会消失。
  • 长期记忆:跨会话持久化的信息,存储在外部数据库或向量索引中。当需要时,Harness 检索相关片段,注入到当前上下文中。

场景示例
一个代码审查 Agent:

  • 短期记忆:本次审查中已经检查过的文件列表、每份文件的错误报告。
  • 长期记忆:团队过去偏好的代码规范、以前类似 bug 的修复记录。Agent 可以在审查开始前检索这些信息,放入系统提示。

训练 vs 推理的不同代价
在推理阶段,改变上下文只是改一段文本,重新部署即可。但在训练阶段,模型“看”到的上下文会影响权重更新。如果训练时上下文设计有误,就得重新训练,代价极高。

反思
我曾被“上下文工程”这个高大上的词吓到,以为需要复杂的算法。其实很多情况下,它就是“把什么放进 prompt、按什么顺序放、窗口满了该删哪条”。但正是这些看似简单的决策,直接决定了 Agent 会不会“失忆”或“幻觉”。一个实用的建议:在你的 Harness 里加上上下文长度监控和自动截断逻辑,这比任何高级技巧都管用。


六、策略(Policy):智能体的行为准则

核心问题:Policy 和 Agent 是一回事吗?

不是。策略 定义了 Agent 的行为:在任意给定状态下,选择每个可能动作的概率。在 LLM 系统中,策略的一部分被学习在模型权重中,但同时也依赖于外部的 Scaffolding 和 Harness。同一个模型,在不同的 prompt、工具、记忆和执行循环下,可以表现出完全不同的策略。

理解方式

  • Agent 是完整的实体(模型 + Harness),它在环境中行动。
  • 策略是这个 Agent 表现出来的行为模式。你可以把 Agent 部署起来观察它的策略,但不能说策略就是 Agent。

场景
一个数学解题 Agent,如果它的系统提示是“一步步推理,最后给出答案”,它的策略可能是谨慎、步步为营。如果把系统提示改成“直接猜答案”,即使底层模型完全相同,策略也会变得冒进。策略不只是权重里学到的知识,还包括运行时注入的规则。


七、工具使用(Tool Use)与技能(Skills):从动作到能力

核心问题:工具和技能的核心区别是什么?为什么需要区分它们?

工具(Tool):一个具体的、可被调用的函数或 API。例如“运行 ls 命令”、“发送 HTTP 请求”、“查询数据库”。模型通过结构化输出表达使用工具的意图,Harness 负责实际执行,并将结果反馈给模型。

技能(Skill):可复用的、结构化的知识包,用于完成多步骤任务。一个工具是一个 动作(“执行这个命令”),而一个技能则打包了完成某个目标所需的所有步骤、知识和工具调用序列(“调查这个 bug → 形成假设 → 编写修复 → 验证”)。

实际区分

  • 工具:search_web(query) – 一个函数。
  • 技能:investigate_bug(bug_report) – 内部可能包含 search_webread_logsanalyze_stacktrace 等多个工具调用,并带有判断逻辑。

场景
客服 Agent:

  • 工具:get_order_status(order_id)refund(order_id)send_email(to, subject, body)
  • 技能:handle_refund_request(order_id, reason) – 它会先查订单状态,判断是否符合退款条件,执行退款,然后发送确认邮件。整个过程是一个技能,可以跨不同 Agent 复用。

不同框架对工具、技能、子 Agent 的边界划分可能不同。理解概念的本质,而不是死抠字眼,会更实用。


八、子智能体(Sub-agents):分而治之的协作模式

核心问题:子 Agent 和普通工具有什么本质区别?什么场景下该用子 Agent?

子 Agent 是被另一个 Agent 调用、专门处理某个子任务的独立 Agent。它有自己的模型和 Scaffolding,可以独立推理、使用工具、甚至可以调用更深层的子 Agent。调用者不需要知道子 Agent 的内部实现。

子 Agent vs 工具 vs 技能

  • 工具:一个同步的函数调用,无状态,瞬间返回结果。
  • 技能:打包好的流程,但通常由主 Agent 的 Harness 解释执行,没有自己的“大脑”。
  • 子 Agent:有独立的模型、上下文和执行循环。它可以处理复杂的多步推理,甚至能应对预期外的情况。

场景示例
一个主 Agent 负责“开发一个新功能”。它可以把“写单元测试”这个任务交给一个专门的测试子 Agent。这个子 Agent 会自己分析代码、生成测试用例、运行测试、根据失败结果修改测试——整个过程自主完成,最后只把通过的测试代码返回给主 Agent。

为什么需要子 Agent

  • 封装复杂性:主 Agent 的 prompt 不用塞满测试相关知识。
  • 独立上下文:子 Agent 的对话历史不会被混入主 Agent,避免干扰。
  • 可复用:同一个测试子 Agent 可以被不同项目的主 Agent 调用。

反思
我第一次看到子 Agent 设计时觉得“过度工程”,直到尝试把一个超长的、需要十几步的任务塞给单个 Agent,结果上下文爆炸、错误累积。拆成主+子后,每个 Agent 只关心自己的那层任务,成功率明显提升。当然,代价是通信开销和更复杂的调试。建议在任务确实有明确边界、且子任务本身需要多步推理时再考虑子 Agent。


九、训练相关术语:RL环境、Trainer、Rollout 与奖励

核心问题:训练一个 RL Agent 需要哪些核心组件?它们各自做什么?

这部分术语只在训练模型(而非仅仅部署)时才会用到。所有 RL 训练系统都遵循相同的基本流水线。

RL Environment(强化学习环境)

环境是 Agent 可以交互的任何东西:一个有状态的对象,接收动作,更新内部状态,返回观察。在 LLM 场景下,动作通常是工具调用。一个简单的例子是文件系统:动作 touch foo.txt 会改变环境状态(创建文件),观察可以是更新后的文件列表。

一个完整的 RL 环境指南已经发布(这里不再压缩详述),你可以在专门的资料中了解不同类型和框架。

Trainer(训练器)

Trainer 是让 Agent 变好 的组件:它运行多个 Agent 轨迹(episodes),对结果打分,并用这些分数更新内部模型的权重。TRL 的 GRPOTrainer 是一个具体例子:一个类同时处理轨迹生成、奖励计算和权重更新。

Rollout(轨迹)

一个 Rollout 就是 Agent 从开始到结束的一次完整运行:记录了 Agent 每一步看到了什么、做了什么、获得了什么奖励。它也被称作 trajectory(轨迹)或 trace(踪迹)。这是 RL 算法学习的基础数据。

Reward(奖励)与 Rubrics(评分规则)

奖励是一个分数,告诉训练算法模型是否在变好。它可以分为:

  • 可验证奖励:测试通过/不通过,答案是否匹配标准答案。
  • 学习奖励:基于人类偏好或 LLM 作为裁判给出的分数。
  • 稀疏奖励:只在 episode 结束时给一个最终分数。
  • 密集奖励:每一步都给一个分数。

Rubrics(评分规则) 将奖励分解为多个带权重的维度,而不是一个单一数字。例如,一个代码生成 Agent 的 Rubric 可能包含:正确性(60%)、代码风格(20%)、性能(20%)。OpenEnvVerifiers 这类库提供了 WeightedSumSequentialGate 等组合对象,让你可以灵活构建 Rubric。

场景
训练一个购物助手 Agent:

  • 稀疏奖励:最终是否成功帮用户下单。
  • 密集奖励:每正确推荐一件商品得 1 分,每错误引导得 -1 分。
  • 可验证奖励:订单金额、地址格式正确性。
  • 学习奖励:用户确认后给的好评/差评。

十、实用摘要与操作清单

核心问题:作为一个工程师或产品经理,看完这篇文章后应该带走什么?

核心结论

  1. 模型 ≠ Agent。模型只负责文本生成,Agent 是模型 + Scaffolding + Harness。
  2. Scaffolding 定义行为(提示、工具描述、解析规则),Harness 负责执行(调用模型、执行工具、循环控制)。
  3. 同一个模型配不同的 Harness,表现完全不同。产品体验的大头往往在 Harness。
  4. 上下文工程是持续的管理过程,短期记忆(上下文内)与长期记忆(外部存储)要分开设计。
  5. 训练 Agent 时,需要理解 Environment、Trainer、Rollout、Reward 这四个核心组件。

操作清单(适用于新项目)

  • [ ] 明确你的“模型”是什么:选一个基础 LLM,还是支持多个?是否需要本地部署?
  • [ ] 设计 Scaffolding

    • [ ] 写出系统提示(角色、边界、禁止行为)
    • [ ] 列出所有工具及对应的自然语言描述
    • [ ] 定义模型输出格式(JSON、XML、函数调用)
  • [ ] 实现 Harness

    • [ ] 调用模型的函数
    • [ ] 解析模型输出并执行工具
    • [ ] 循环停止条件(最大步数、关键词完成、异常退出)
    • [ ] 错误处理与重试策略
  • [ ] 上下文管理

    • [ ] 哪些历史需要保留?窗口满了怎么截断?
    • [ ] 是否需要长期记忆?如何检索与注入?
  • [ ] 评估与训练(如需要)

    • [ ] 构建 Eval Harness 运行固定测试
    • [ ] 定义奖励(可验证 / 学习 / 稀疏 / 密集)
    • [ ] 选择 Trainer(如 TRL、OpenEnv)

十一、一页速览(One-page Summary)

术语 一句话定义 比喻
模型 纯文本生成器,无状态,无循环 知识渊博但从不主动行动的学者
Scaffolding 行为定义层:提示、工具描述、解析规则 员工手册与工作流程
Harness 执行层:调用模型、执行工具、控制循环 办公室、电脑、工单系统
Agent 模型 + Harness 的完整系统 一个真正能干活的研究员
上下文工程 管理进入上下文的所有信息(短期+长期) 白板上写什么、存档里查什么
策略 Agent 的行为模式,由模型权重 + Scaffolding 共同决定 工作风格
工具 单一动作函数 扳手、螺丝刀
技能 打包的多步知识包 “换轮胎”的标准流程
子 Agent 独立推理、执行子任务的 Agent 外包给专业团队
RL 环境 可交互的状态对象,接收动作返回观察 游戏世界
Trainer 运行轨迹、计算奖励、更新权重的循环 教练+健身房
Rollout 一次完整的 Agent 运行记录 一盘棋的棋谱
奖励 告诉训练算法好坏的分数 得分板

十二、常见问答(FAQ)

Q1:Harness 和 Agent 到底是什么关系?
A:Agent = 模型 + Harness。Harness 是 Agent 的执行引擎,负责调用模型、处理工具调用、控制循环。没有 Harness,模型只是单次文本生成器。

Q2:Scaffolding 和 Harness 的边界在哪里?
A:Scaffolding 定义“做什么”和“按什么格式做”(提示、工具描述、解析规则);Harness 负责“实际执行”(调用模型、运行函数、决定何时停止)。训练流水线中区分它们很有用,但在产品文档中常被统称为 Harness。

Q3:我可以把 Claude Code 的 Harness 用在其他模型上吗?
A:有些产品(如 Hermes Agent)允许切换模型,但 Claude Code 自身是与 Claude 模型深度绑定的。理论上你可以实现一个兼容接口,但这需要大量工作,因为模型输出格式和工具调用 Schema 可能不匹配。

Q4:短期记忆和长期记忆在工程上怎么实现?
A:短期记忆就是保留在上下文中的对话历史,通常使用一个消息列表(messages array)。长期记忆需要外部存储(向量数据库、关系数据库),通过检索(如语义相似度搜索)找到相关片段,然后注入到系统提示或用户消息中。

Q5:什么时候应该用子 Agent,而不是普通工具?
A:当子任务本身需要多步推理、可能遇到预期外情况、且与主 Agent 的上下文可以完全隔离时,考虑子 Agent。如果子任务只是单一函数调用,用工具就够了。

Q6:训练 Agent 时,奖励应该怎么设计?
A:从可验证奖励开始(如测试通过率)。如果任务开放性很强,再考虑学习奖励(LLM 作为裁判)。尽量使用 Rubric 将奖励分解为多个维度,便于调试。

Q7:我是否必须先训练模型,才能构建有用的 Agent?
A:完全不需要。大多数生产 Agent 直接用现有模型(Claude、GPT、Qwen 等),通过精心设计 Scaffolding 和 Harness 就能取得很好效果。训练(微调或 RL)通常是在你已经有稳定流水线后,为了提升特定领域表现才做的优化。

Q8:这些术语的混淆会持续很久吗?
A:随着领域成熟,核心术语会逐渐收敛。但不同框架和产品为了差异化,可能永远保留自己的定义。建议团队内部统一一套词汇表,并理解每个术语背后所指的工程概念,而不是死记定义。