从 Prompt Engineering 到 Harness Engineering:Agent 开发为什么越来越像系统工程?

前言:为什么现在又开始讨论 Context Engineering 和 Harness Engineering?

刚开始接触大模型开发的时候,我们经常会遇到一个问题:

这个 Prompt 到底应该怎么写?

于是我们开始研究 Prompt Engineering:

  • System Prompt 怎么设计?
  • Role 应该怎么定义?
  • Few-shot 要不要加?
  • 输出格式怎么约束?
  • 怎么减少模型幻觉?

随着 Agent 应用越来越复杂,我们很快会发现:

很多问题根本不是 Prompt 写得不好。

比如:

Prompt 已经写得很清楚了,
但是模型不知道数据库里的实时数据。

Prompt 已经写得很清楚了,
但是历史对话太长,模型抓不到重点。

Prompt 已经写得很清楚了,
但是工具返回的数据太多,模型反而不知道该看什么。

于是,我们开始关注另外一个问题:

到底应该给模型什么上下文?

这就是 Context Engineering。

但是继续往前做 Agent,又会遇到更加棘手的问题:

模型知道该做什么;
也拿到了正确的信息;

但是:
工具调用失败怎么办?
任务执行到一半怎么办?
状态怎么保存?
结果怎么验证?
失败之后怎么重试?
Agent 能访问哪些资源?

这时候你会发现:

Prompt 和 Context 解决的只是 Agent 的一部分问题。

真正要让 Agent 稳定完成任务,还需要一个完整的运行环境。

于是又出现了 Harness Engineering。

所以,如果把这几个概念放到一起看,我更倾向于把它理解成一个逐渐演进的过程:

Prompt Engineering
        ↓
解决“模型应该怎么做”
        ↓
Context Engineering
        ↓
解决“模型需要知道什么”
        ↓
Harness Engineering
        ↓
解决“模型如何可靠地完成任务”

本文就从 Agent 开发的角度,聊聊这三个概念之间到底是什么关系。


1、Prompt Engineering:先解决“怎么告诉模型做什么”

Prompt Engineering,也就是我们最熟悉的提示词工程

在最早的大模型应用中,系统通常非常简单:

用户输入
   ↓
Prompt
   ↓
LLM
   ↓
回答

例如:

你是一名发动机选型专家。

请根据用户的需求,
从候选发动机中选择最符合要求的型号。

要求:
1. 优先满足用户明确提出的条件
2. 不允许虚构不存在的配置
3. 如果条件无法满足,需要明确告诉用户
4. 最终给出推荐型号以及推荐理由

这里我们实际上是在告诉模型:

  • 你是谁
  • 你要做什么
  • 应该遵循什么规则
  • 最后应该输出什么

这就是 Prompt Engineering 最核心的工作。

可以简单理解成:

Prompt Engineering 解决的是模型的“行为规范”。


2、Prompt Engineering 为什么越来越不够用了?

假设现在我们真的做一个发动机智能选配 Agent。

用户说:

帮我选择一个功率 150kW 以上,
排量不超过 2.5L 的发动机。

Prompt 可以告诉模型:

必须满足用户提出的条件。

但是问题来了:

模型怎么知道现在有哪些发动机?

难道我们把数据库中的所有发动机都写进 Prompt?

比如:

发动机 A:
功率:120kW
排量:2.0L
价格:8000

发动机 B:
功率:150kW
排量:2.5L
价格:10000

发动机 C:
功率:180kW
排量:2.5L
价格:12000

......

如果数据量只有几十条,还可以勉强接受。

但是实际业务系统可能有:

发动机
+
零部件
+
配置参数
+
价格
+
库存
+
车型
+
客户历史选择

数据量很容易达到几万甚至几十万条。

这时候 Prompt 已经不是 Prompt 了。

而变成了一个:

巨大的数据容器。

所以问题开始发生变化:

以前:
Prompt 怎么写?

现在:
模型真正需要哪些信息?

这就是 Context Engineering 出现的原因。


3、Context Engineering:解决“模型需要知道什么”

Context Engineering 可以简单理解成:

围绕当前任务,为模型动态构建高质量上下文。

这里的关键词其实是:

动态。

不是把所有数据都提前塞给模型,而是根据当前任务,找到模型真正需要的信息。

整个过程可能是:

用户请求
   ↓
理解用户需求
   ↓
确定需要哪些信息
   ↓
查询数据库 / 知识库 / API
   ↓
筛选相关数据
   ↓
整理 / 压缩
   ↓
构建 Context
   ↓
发送给 LLM

比如:

用户:
我需要一个功率 150kW 以上、
排量不超过 2.5L 的发动机。

Agent 首先解析出:

power >= 150kW
displacement <= 2.5L

然后去查询数据库:

SELECT *
FROM engine
WHERE power >= 150
  AND displacement <= 2.5;

数据库返回:

A:150kW / 2.5L / 10000元
B:160kW / 2.3L / 12000元
C:180kW / 2.5L / 9000元

然后把这些数据组织成模型需要的 Context:

用户需求:
功率 >= 150kW
排量 <= 2.5L

候选发动机:

A:
功率:150kW
排量:2.5L
价格:10000元

B:
功率:160kW
排量:2.3L
价格:12000元

C:
功率:180kW
排量:2.5L
价格:9000元

这时候 LLM 才真正开始发挥它擅长的能力:

基于已经获取到的信息进行理解、推理和解释。


4、Context Engineering 和 Prompt Engineering 到底有什么区别?

这两个概念其实特别容易混。

我觉得可以用一句话来区分:

Prompt Engineering 解决“怎么告诉模型做事”,Context Engineering 解决“给模型什么信息做事”。

例如:

Prompt

你是一名发动机选型专家。

请选择满足用户要求的发动机。
不得虚构数据。

这是:

模型应该怎么做

Context

用户要求:
功率 >= 150kW

候选发动机:

A:120kW
B:150kW
C:180kW

这是:

模型需要知道什么

因此二者并不是替代关系。

而是:

Prompt
  +
Context
  ↓
LLM

Prompt 负责规则和行为

Context 负责事实和状态


5、Context Engineering 不等于 RAG

这里也有一个比较常见的误区:

Context Engineering = RAG?

其实不是。

RAG 只是 Context Engineering 的一种实现方式。

Context 的来源可以非常多:

                 Context
                    │
       ┌────────────┼────────────┐
       ↓            ↓            ↓
      RAG        Database       API
       │            │            │
       ↓            ↓            ↓
   知识文档      业务数据      实时数据
       
       ┌────────────┼────────────┐
       ↓            ↓            ↓
   Conversation   Memory      Tool Result
       │            │            │
       ↓            ↓            ↓
     历史对话      用户记忆      工具执行结果

所以在实际 Agent 项目中:

Context Engineering
        │
        ├── RAG
        ├── Database Query
        ├── API
        ├── Tool Result
        ├── Conversation History
        ├── Memory
        ├── Task State
        └── Runtime Information

这些都属于 Context Engineering 的范畴。


6、Context Engineering 的核心:不要什么都给模型

这里其实有一个非常重要的思想:

Context 不是越多越好。

以前我们经常有一种思维:

模型不知道?
→ 给它更多信息。

但在 Agent 中,往往不是这样。

信息太多反而会带来:

  • Token 消耗增加
  • 上下文噪声增加
  • 模型注意力分散
  • 无关信息干扰决策
  • Context Window 被快速消耗

所以更合理的方式是:

不是:
把所有信息给模型

而是:
找到当前任务真正需要的信息

也就是:

Just-in-Time Context。

什么时候需要什么信息,就什么时候获取。


7、为什么 Agent 做到后面,又会出现 Harness Engineering?

假设现在 Context 已经解决了。

模型已经知道:

用户需要什么
有哪些候选发动机
当前库存是多少
价格是多少
历史对话是什么

但是 Agent 还需要完成:

查询数据库
 ↓
调用库存接口
 ↓
调用价格接口
 ↓
校验配置
 ↓
生成结果

这时候新的问题来了。

比如:

库存接口调用失败怎么办?

数据库连接超时怎么办?

模型选出的配置不符合业务规则怎么办?

工具返回的数据格式错误怎么办?

Agent 执行到一半用户退出怎么办?

任务执行到一半 Context 太长怎么办?

这些问题已经很难通过 Prompt 解决了。

因为:

它们属于系统运行问题,而不是模型指令问题。

于是,我们开始需要一个更完整的东西:

Harness。


8、Harness Engineering:给 Agent 构建一个“工作环境”

Harness 这个词本身可以理解成“驾驭、控制、约束”。

在 Agent 场景下,可以把 Harness 简单理解为:

围绕 LLM 构建的一套 Agent 运行环境。

它负责让模型不仅“会思考”,而且能够:

获取信息
 ↓
调用工具
 ↓
执行任务
 ↓
观察结果
 ↓
修改计划
 ↓
继续执行
 ↓
验证结果
 ↓
失败恢复

因此一个完整的 Agent 已经不再是:

Prompt
 ↓
LLM
 ↓
Answer

而更像:

                 Agent Harness
                       │
        ┌──────────────┼──────────────┐
        ↓              ↓              ↓
      Context         Tools          State
        │              │              │
        └──────────────┼──────────────┘
                       ↓
                      LLM
                       ↓
                     Action
                       ↓
                  Environment
                       ↓
                    Result
                       ↓
                  Context Update
                       ↓
                      LLM

9、Harness Engineering 主要解决哪些问题?

如果把 Harness 拆开,其实就是我们做 Agent 时经常遇到的那些工程问题。

9.1 Tool:Agent 能做什么?

例如:

query_engine()
query_inventory()
query_price()
validate_config()

模型负责决定:

“我现在需要调用哪个工具?”

Harness 负责:

“这个工具到底怎么执行?”


9.2 State:Agent 现在做到哪里了?

例如:

{
  "task": "发动机选型",
  "status": "validating",
  "selected_engine": "A",
  "inventory_checked": true,
  "price_checked": true
}

如果没有状态管理,复杂 Agent 很容易:

做过的事情重复做
 ↓
上下文越来越混乱
 ↓
Agent 开始“失忆”

所以 State Management 也是 Harness 的重要组成部分。


9.3 Execution Loop:Agent 怎么持续工作?

一个典型 Agent Loop:

Think
 ↓
Act
 ↓
Observe
 ↓
Think
 ↓
Act
 ↓
Observe
 ↓
...

也就是:

LLM
 ↓
Tool Call
 ↓
Tool Result
 ↓
LLM
 ↓
Tool Call
 ↓
Tool Result

Harness 负责把这个循环真正跑起来。


10、Validation:为什么 Agent 不能相信自己?

这是我认为 Harness Engineering 中非常重要的一点。

例如 Agent 修改代码后说:

代码已经修复。

这句话其实没有意义。

真正应该做的是:

修改代码
   ↓
运行测试
   ↓
测试通过?
   ├── 否 → 获取错误信息
   │          ↓
   │        修改代码
   │          ↓
   │        再次测试
   │
   └── 是 → 任务完成

也就是说:

Agent 负责提出行动,Harness 负责验证行动结果。

这也是为什么现在的 Coding Agent 越来越像一个完整的软件工程系统。


11、一个实际的 Coding Agent 就非常典型

比如我们让 Agent:

帮我修复这个 Bug。

一个真正能够工作的 Coding Agent,需要:

读取代码
 ↓
搜索相关文件
 ↓
理解代码
 ↓
修改代码
 ↓
执行测试
 ↓
读取测试结果
 ↓
分析错误
 ↓
再次修改
 ↓
再次测试
 ↓
Git Diff
 ↓
最终验证

这里:

Prompt Engineering

告诉 Agent:

你是一个优秀的软件工程师。
修改代码前先理解现有代码。
不要修改无关文件。
修改后必须运行测试。

解决:

应该怎么工作。


Context Engineering

给 Agent:

项目结构
相关代码
README
CLAUDE.md / AGENTS.md
历史修改
测试结果
Git Diff

解决:

应该知道什么。


Harness Engineering

提供:

File System
Shell
Git
Test Runner
Search
Sandbox
Permission
State
Retry
Validation

解决:

应该怎么真正把事情做完。


12、三者之间到底是什么关系?

现在就可以比较清晰地理解三者了。

Prompt Engineering Context Engineering Harness Engineering
核心问题 怎么告诉模型? 给模型什么信息? 怎么让 Agent 完成任务?
主要对象 Prompt Context Agent Runtime
关注重点 指令、规则、格式 数据、记忆、状态、检索 工具、执行、状态、验证
解决问题 行为 信息 能力与可靠性
典型手段 System Prompt、Few-shot RAG、DB、Memory、Tool Result Tool、Loop、Sandbox、Retry、Validation
类比 工作说明书 工作资料 整个工作环境

所以可以用三个问题快速判断:

模型不知道“应该怎么做”
        ↓
Prompt Engineering

模型不知道“完成任务需要什么信息”
        ↓
Context Engineering

模型知道怎么做,也知道需要什么,
但就是无法稳定完成任务
        ↓
Harness Engineering

13、为什么我认为这是 Agent 开发的一条演进路线?

回过头来看,会发现这三个概念并不是突然出现的。

它其实对应了 AI 应用开发的三个阶段。

第一阶段:Prompt Engineering

最开始:

User
 ↓
Prompt
 ↓
LLM
 ↓
Answer

重点是:

如何让模型回答得更好。


第二阶段:Context Engineering

后来:

User
 ↓
Retrieve / Query / Memory
 ↓
Context
 ↓
LLM
 ↓
Answer

重点变成:

如何让模型获得正确的信息。


第三阶段:Harness Engineering

再往后:

                 Agent
                   │
        ┌──────────┼──────────┐
        ↓          ↓          ↓
     Context      Tools      State
        │          │          │
        └──────────┼──────────┘
                   ↓
                  LLM
                   ↓
                 Action
                   ↓
              Environment
                   ↓
               Observation
                   ↓
              Validation
                   ↓
                Continue

重点变成:

如何让模型在真实环境中持续完成复杂任务。

所以我更愿意把它看成:

Prompt Engineering
        ↓
Context Engineering
        ↓
Harness Engineering
        ↓
Agent Engineering

14、那么现在做 Agent,到底应该重点学什么?

如果是刚开始做 AI 应用,我认为 Prompt Engineering 依然值得学习。

因为:

Prompt

仍然是模型行为控制的基础。

但是如果已经进入 Agent 开发阶段,仅仅研究 Prompt 的收益就会越来越低。

这时候更应该把精力放在:

Context
├── 如何获取
├── 如何筛选
├── 如何压缩
├── 如何组织
└── 如何动态更新

Tools
├── 如何设计
├── 如何调用
├── 如何处理异常
└── 如何控制权限

State
├── Task State
├── Conversation State
└── Agent Memory

Execution
├── Agent Loop
├── Retry
├── Timeout
└── Recovery

Validation
├── Rule Validation
├── Tool Validation
└── Result Validation

也就是说:

Agent 开发正在逐渐从“Prompt 技巧”转向“系统工程能力”。


15、最后总结

如果让我用最简单的方式总结这三个概念:

Prompt Engineering

告诉模型应该怎么做。

Context Engineering

告诉模型完成任务需要知道什么。

Harness Engineering

给模型提供完成任务所需要的工具、环境和运行机制。

三者组合起来就是:

              Agent
                │
       ┌────────┼────────┐
       ↓        ↓        ↓
     Prompt   Context   Harness
       │        │        │
       ↓        ↓        ↓
    怎么做     知道什么    能做什么
       │        │        │
       └────────┼────────┘
                ↓
               LLM
                ↓
           完成真实任务

所以,Agent 真正的工程能力,并不是单纯把一个 LLM API 调通,也不是把 Prompt 写得越来越长。

而是逐渐建立这样一套完整的系统:

用 Prompt 定义规则,用 Context 提供信息,用 Harness 提供能力和运行环境,再通过 Validation 保证最终结果可靠。

这也是为什么现在越来越多的 Agent 产品,看起来已经不像传统意义上的“AI 聊天机器人”,而更像一个围绕 LLM 构建的完整软件系统。

LLM 只是其中的大脑。

真正决定 Agent 能不能把事情做好的,是围绕这个“大脑”构建起来的:

Prompt
+
Context
+
Tools
+
State
+
Execution
+
Validation
+
Environment

而这可能才是 Agent Engineering 真正开始走向工程化的地方。

posted @ 2026-08-28 17:29  LucaJu  阅读(2)  评论(0)    收藏  举报