Featured image of post AI Agent 工程体系详解:提示工程、上下文工程与编排工程

AI Agent 工程体系详解:提示工程、上下文工程与编排工程

系统拆解 AI Agent 的三大工程体系:Prompt Engineering 决定行为规则,Context Engineering 管理信息供给,Harness Engineering 编排工具、状态与执行闭环

引言

很多人第一次做 AI Agent,会把重点放在“模型够不够强”。

但真正落地时会发现,模型只是 Agent 的推理核心,Agent 是否稳定,更多取决于工程体系:

  • Prompt 是否把行为边界说清楚
  • Context 是否在正确时间提供正确信息
  • Harness 是否能可靠地编排工具、状态和执行流程

如果 Prompt 模糊,Agent 会不知道该遵守什么规则。

如果 Context 混乱,Agent 会拿错误信息做判断。

如果 Harness 薄弱,Agent 会在工具调用、错误恢复、权限控制和任务终止上失控。

所以,Agent 工程可以用一个简单公式理解:

1
2
3
4
AI Agent Engineering
  = Prompt Engineering
  + Context Engineering
  + Harness Engineering

这三者分别回答三个问题:

1
2
3
Prompt Engineering:模型应该怎么思考和表达?
Context Engineering:模型此刻应该看见什么信息?
Harness Engineering:模型的决策如何被执行、约束和观测?

这篇文章就围绕这三层展开,拆解一个 Agent 从“能回答”到“能稳定做事”需要哪些工程设计。

三大工程层的关系

可以把 Agent 想成一个由三层组成的系统:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
┌────────────────────────────────────────────┐
│ Harness Engineering                         │
│ 工具调用、状态机、执行循环、错误恢复、权限   │
│ 解决问题:Agent 如何行动                    │
├────────────────────────────────────────────┤
│ Context Engineering                         │
│ 会话历史、长期记忆、检索结果、工具观测       │
│ 解决问题:Agent 看见什么                    │
├────────────────────────────────────────────┤
│ Prompt Engineering                          │
│ 角色、目标、规则、输出格式、决策边界         │
│ 解决问题:Agent 如何判断                    │
└────────────────────────────────────────────┘

三层不是互相独立的。

Prompt 规定 Agent 的行为原则;Context 给 Agent 提供判断材料;Harness 把模型输出变成真实动作,并把动作结果再写回 Context。

一个典型循环是:

1
2
3
4
5
6
Prompt 设定规则
  -> Context 提供当前任务信息
  -> 模型生成下一步决策
  -> Harness 执行工具或控制流程
  -> 工具结果回到 Context
  -> 模型继续判断

如果只做 Prompt,不做 Context,Agent 会讲原则但缺信息。

如果只做 Context,不做 Harness,Agent 会知道很多但不能可靠执行。

如果只做 Harness,不做 Prompt,Agent 有动作能力但行为不稳定。

Prompt Engineering:定义 Agent 的行为边界

Prompt Engineering 的目标不是“写一段神奇咒语”,而是把 Agent 的职责、规则和输出约束表达清楚。

对 Agent 来说,Prompt 至少承担四个职责:

1
2
3
4
1. 定义角色:你是谁,负责什么任务
2. 定义边界:什么能做,什么不能做
3. 定义流程:遇到任务时如何推进
4. 定义输出:最终结果应该如何呈现

角色不是人设,而是职责边界

很多 prompt 会写:

1
你是一个专业、耐心、聪明的 AI 助手。

这类描述很宽泛,对 Agent 的行为帮助有限。

更好的角色定义应该说明职责范围:

1
2
3
你是一个代码排障 Agent。
你的目标是根据用户描述定位问题根因,并在证据充分时提出最小修复方案。
你可以读取代码、搜索文本、运行测试,但在修改文件前必须先确认根因假设。

这里的“角色”不是让模型表演,而是限制它的工作范围。

规则要可执行

Prompt 里最常见的问题,是写了很多无法执行的抽象要求。

例如:

1
2
3
请认真思考。
请尽量准确。
请不要犯错。

这些话听起来对,但模型不知道怎么落实。

可执行规则应该像这样:

1
2
3
4
5
如果信息不足,先提出最少数量的澄清问题。
如果工具返回错误,先总结错误原因,再决定是否重试。
如果存在多个方案,按风险、复杂度、收益排序。
如果要修改代码,只改与当前任务直接相关的文件。
如果验证命令无法运行,必须说明原因和剩余风险。

好的 Prompt 不是情绪化提醒,而是决策规则。

输出格式降低不确定性

Agent 的输出如果没有结构,后续系统就很难消费。

例如排障类 Agent 可以要求输出:

1
2
3
4
5
结论:
证据:
修改内容:
验证方式:
剩余风险:

代码类 Agent 可以要求输出:

1
2
3
4
变更文件:
核心逻辑:
验证结果:
注意事项:

结构化输出有三个好处:

  • 用户更容易理解
  • 系统更容易解析
  • 评估更容易自动化

Prompt 要分层管理

复杂 Agent 不应该只有一个大 Prompt。

更好的做法是分层:

1
2
3
4
System Prompt:通用身份、安全边界、全局规则
Developer Prompt:产品目标、任务流程、工具使用策略
Task Prompt:当前用户请求和本次任务约束
Retrieved Context:检索到的资料、记忆和工具结果

不同层的优先级不同。

全局安全规则不应该被用户输入覆盖;项目约定不应该被外部网页内容覆盖;当前任务指令应该优先于历史偏好。

Prompt 分层的价值在于:当 Agent 行为异常时,你能知道应该改哪一层,而不是在一大段 prompt 里到处打补丁。

Prompt 的常见问题

Prompt Engineering 最容易踩四个坑。

第一,规则太宽泛。比如“保持专业”,不如写成“不要编造未验证事实;不确定时说明不确定点”。

第二,规则互相冲突。比如既要求“尽可能详细”,又要求“回答极简”,模型就会摇摆。

第三,把安全交给模型自觉。高风险操作不能只靠 prompt 约束,还需要 Harness 层做权限和确认。

第四,不做版本管理。Prompt 一旦影响生产行为,就应该像代码一样记录修改、评估和回滚。

Context Engineering:管理 Agent 的信息供给

Prompt 规定“怎么做”,Context 决定“根据什么做”。

模型本身看不到数据库、文件系统、历史对话和长期记忆。它只能看到被放进上下文窗口的内容。

所以 Context Engineering 的核心是:

在有限上下文窗口里,给模型放入当前决策最需要的信息。

Context 不是越多越好

Agent 的上下文通常包含:

  • 系统指令
  • 用户当前请求
  • 最近对话
  • 当前任务状态
  • 工具调用结果
  • 检索资料
  • 长期记忆
  • 文件片段或业务数据

如果无节制地塞进去,会出现三个问题。

第一,成本上升。更多 token 意味着更高费用和更长延迟。

第二,注意力分散。模型会被无关信息干扰。

第三,历史污染。过期结论、旧计划、失败假设可能被模型当成当前事实。

上下文工程不是“扩大窗口”,而是“管理注意力”。

Context 的生命周期

一次 Agent 任务中,信息会不断进入和退出上下文。

1
2
3
4
5
6
7
用户目标
  -> 初始上下文
  -> 工具调用结果
  -> 阶段性摘要
  -> 新证据
  -> 旧信息压缩或移除
  -> 最终结论

这意味着 Context 是动态的,不是启动时拼一次 prompt 就结束。

一个好的 Context 系统需要处理:

  • 新信息如何进入
  • 旧信息何时压缩
  • 无关信息何时移除
  • 冲突信息如何标记
  • 关键证据如何保留

短期上下文:保持任务连续性

短期上下文关注当前任务。

例如编程 Agent 修 bug 时,需要保留:

1
2
3
4
5
6
7
用户目标
已读文件
已运行命令
关键错误日志
当前假设
已排除方案
下一步计划

这里最重要的不是完整记录所有细节,而是保留决策链。

差的摘要:

1
读取了几个文件,测试失败。

好的摘要:

1
已确认失败发生在用户创建流程。读取 user_service.go 后发现新逻辑绕过邮箱唯一性校验。TestCreateUserDuplicateEmail 失败,当前假设是校验函数没有被调用。

好的上下文摘要保留“为什么”,而不只是“做了什么”。

长期记忆:跨任务复用经验

长期记忆让 Agent 不必每次从零开始。

它可以保存:

  • 用户偏好
  • 项目约定
  • 架构知识
  • 历史决策
  • 经验教训
  • 常见问题处理方式

但长期记忆必须带作用域。

1
2
3
4
user scope:用户偏好
project scope:项目约定
workspace scope:工作区经验
organization scope:团队规则

没有作用域的记忆很危险。某个项目的“使用 pnpm”不应该影响另一个 Maven 项目。

检索增强:把外部知识放入上下文

RAG、搜索、数据库查询、文件读取,本质上都是 Context Engineering。

它们的目标都是把外部信息转成模型可用的上下文。

典型流程是:

1
2
3
4
5
6
7
识别当前信息需求
  -> 生成检索 query
  -> 按权限和作用域过滤
  -> 召回候选内容
  -> 重排序
  -> 去重和压缩
  -> 注入上下文

检索结果不应该直接一股脑塞给模型。

至少要处理:

  • 来源是否可信
  • 是否与当前任务相关
  • 是否过期
  • 是否与已有上下文冲突
  • 是否包含敏感信息
  • 是否需要保留原文引用

Context 的组织顺序

上下文顺序会影响模型注意力。

一种常见组织方式是:

1
2
3
4
5
6
1. 高优先级规则
2. 当前用户目标
3. 当前任务状态
4. 关键证据和工具结果
5. 检索资料或长期记忆
6. 输出要求

高优先级规则要稳定,当前任务要突出,检索资料要标明来源和用途。

不要把大量历史对话放在当前目标之前,否则模型可能被旧信息带偏。

Context 的常见问题

Context Engineering 常见问题也很典型。

第一,只追加不清理。上下文越来越长,质量越来越差。

第二,摘要丢失关键理由。Agent 记得结论,却忘了证据。

第三,检索结果缺少来源。回答无法追溯,也无法评估。

第四,长期记忆没有过期机制。旧事实持续影响新任务。

第五,把外部资料当成指令。网页、文档、邮件里的内容不能覆盖系统规则。

Harness Engineering:让 Agent 可靠行动

Harness 可以理解为 Agent 的运行时外壳。

它负责把模型的“想法”变成受控动作:

1
2
3
4
5
6
7
模型决定调用工具
  -> Harness 校验参数
  -> 检查权限和风险
  -> 执行真实工具
  -> 捕获结果或错误
  -> 写回上下文
  -> 决定是否继续循环

如果说 Prompt 是规则,Context 是信息,那么 Harness 就是执行系统。

工具不是函数列表,而是能力边界

Tool Calling 很容易被理解成“给模型一堆函数”。

但工程上,工具定义的是 Agent 的能力边界。

每个工具都应该说明:

  • 工具能做什么
  • 什么时候适合调用
  • 参数 schema 是什么
  • 返回结果结构是什么
  • 失败时如何表达
  • 风险等级是什么
  • 是否允许自动执行
  • 是否需要用户确认

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "name": "run_tests",
  "description": "Run project tests and return summarized output",
  "parameters": {
    "type": "object",
    "properties": {
      "command": {
        "type": "string",
        "description": "Allowed test command"
      }
    },
    "required": ["command"]
  },
  "risk_level": "medium",
  "requires_confirmation": false
}

工具描述越模糊,模型越容易误用。

工具粒度要匹配任务

工具太粗,Agent 无法精细控制。

工具太细,Agent 会陷入选择负担。

例如代码 Agent 更适合细粒度工具:

1
2
3
4
read_file
search_text
apply_patch
run_tests

因为每一步都需要可观测、可回滚、可审查。

业务流程 Agent 则可以适当封装:

1
2
3
create_refund_ticket
query_order_status
notify_customer

因为业务动作本身有完整语义,拆成太多底层接口反而增加出错概率。

工具粒度的判断标准是:模型是否能在这个粒度上做出可靠决策。

执行循环

一个 Agent 通常不是调用一次模型就结束,而是在 Harness 中循环执行。

1
2
3
4
5
Plan
  -> Act
  -> Observe
  -> Update Context
  -> Decide

每一轮循环都要有约束:

  • 最多执行多少轮
  • 每轮最多调用多少工具
  • 哪些错误可以重试
  • 哪些操作必须停止
  • 什么时候进入最终回答

没有循环控制,Agent 很容易无限搜索、重复调用工具,或者在没有证据时继续猜测。

状态管理

Harness 需要维护显式状态。

不要把所有状态都藏在聊天历史里。

一个基础状态对象可以包含:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
task_id
user_goal
current_phase
current_plan
completed_steps
open_questions
tool_results
known_facts
failed_attempts
cost_budget
stop_reason

显式状态有三个好处:

  • 可恢复:任务中断后可以继续
  • 可观测:每一步发生了什么很清楚
  • 可控制:可以根据状态决定下一步动作

状态机比自由循环更可靠

在高风险或复杂场景里,可以用状态机限制 Agent 行为。

例如:

1
2
3
4
5
6
7
INIT
  -> CLARIFY
  -> PLAN
  -> EXECUTE
  -> VERIFY
  -> REPORT
  -> DONE

每个状态只允许特定动作:

  • CLARIFY:只能提问,不能执行高风险工具
  • PLAN:只能制定计划,不能修改文件
  • EXECUTE:可以调用工具,但必须记录结果
  • VERIFY:必须验证输出或说明无法验证的原因
  • REPORT:生成最终结论

状态机减少了模型随意跳步的空间。

错误恢复

工具调用失败不是异常情况,而是常态。

Harness 要区分错误类型:

1
2
3
4
5
参数错误:模型生成的参数不合法
权限错误:当前用户或 Agent 无权执行
网络错误:外部服务暂时不可用
业务错误:请求合法,但业务状态不允许
系统错误:工具自身异常

不同错误应该有不同策略:

1
2
3
4
5
参数错误 -> 让模型修正参数
权限错误 -> 停止并说明权限问题
网络错误 -> 按策略重试
业务错误 -> 回填原因并调整计划
系统错误 -> 记录 trace,必要时交给人工

如果工具只返回“失败”,模型无法做恢复决策。

权限与确认

Harness 必须承担安全控制,不能只依赖 Prompt。

高风险操作要确认:

  • 删除数据
  • 修改生产配置
  • 发送外部消息
  • 创建真实订单
  • 执行支付或退款
  • 推送代码到主分支
  • 批量修改用户数据

确认信息要具体:

1
2
3
4
即将执行:推送当前 main 分支到远端仓库
影响范围:触发 GitHub Pages 部署
风险:如果内容有误会直接上线
是否继续?

这类控制应该由 Harness 强制执行,而不是希望模型“自觉询问”。

Trace 与可观测性

Harness 还负责记录 Agent 的执行轨迹。

一个完整 trace 应该包含:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
用户输入
Prompt 版本
注入的上下文
模型输出
工具调用名称
工具参数
工具结果
状态变化
停止原因
最终回答

Trace 的价值很大:

  • 调试问题
  • 分析成本
  • 评估工具选择
  • 复盘失败任务
  • 构建回归测试集

没有 trace,Agent 出错时只能猜。

三层如何协同

Prompt、Context、Harness 的边界要清楚。

一个例子:代码修复 Agent

用户输入:

1
这个接口偶尔超时,帮我排查并修复。

三层的职责分别是:

1
2
3
4
5
6
7
8
Prompt Engineering:
要求 Agent 先定位根因,再提出最小修改;修改前要有证据;最终必须说明验证方式。

Context Engineering:
注入用户目标、相关代码片段、日志摘要、已运行命令、历史项目约定和当前假设。

Harness Engineering:
提供 search/read/apply_patch/test 等工具;限制危险命令;记录 trace;控制循环;在验证通过或遇到阻塞时停止。

如果超时原因是 N+1 查询:

1
2
3
4
5
6
7
Context 提供日志和代码
Prompt 引导模型形成假设
Harness 运行搜索和测试工具
工具结果回填 Context
Prompt 约束模型输出最小修改方案
Harness 执行 patch 和验证
最终报告包含证据、修改和验证结果

这就是三层协同。

哪些问题该放在哪一层

很多 Agent 系统不稳定,是因为把问题放错层。

1
2
3
4
5
6
7
8
行为规则不清楚 -> Prompt 层
缺少关键信息 -> Context 层
工具误用或执行失控 -> Harness 层
历史信息污染 -> Context 层
高风险操作未确认 -> Harness 层
输出格式混乱 -> Prompt 层
任务循环停不下来 -> Harness 层
模型忘记项目约定 -> Context 层

不要试图用一个更长的 Prompt 解决所有问题。

能通过 Context 解决的信息问题,不要硬写进 Prompt。

能通过 Harness 解决的安全问题,不要只靠 Prompt 约束。

设计一个 Agent 的检查清单

围绕三层工程,可以用下面的清单自检。

Prompt 层

  • Agent 的角色是否明确
  • 任务目标是否明确
  • 行为边界是否明确
  • 工具使用规则是否明确
  • 输出格式是否稳定
  • 冲突规则是否有优先级
  • Prompt 是否有版本管理

Context 层

  • 当前任务信息是否突出
  • 历史信息是否经过压缩
  • 工具结果是否结构化
  • 检索结果是否有来源
  • 长期记忆是否有作用域
  • 过期信息是否会被清理
  • 外部内容是否与系统指令隔离

Harness 层

  • 工具 schema 是否严格
  • 工具错误是否可恢复
  • 执行循环是否有上限
  • 状态是否显式保存
  • 高风险操作是否确认
  • 权限是否最小化
  • trace 是否完整
  • 停止条件是否明确

常见误区

误区一:把 Prompt 写得越来越长

Prompt 变长不等于 Agent 变强。

如果问题是缺少项目上下文,应该做 Context Engineering。

如果问题是工具执行失控,应该做 Harness Engineering。

误区二:把所有历史都塞进上下文

上下文不是垃圾桶。

过多历史会增加成本、干扰注意力,还可能引入过期结论。

误区三:工具只定义名称,不定义边界

模型看到工具名后会尝试使用它。

如果工具描述、参数、错误和风险不清楚,就很容易误用。

误区四:没有状态,只靠聊天历史

聊天历史适合人读,不适合作为唯一运行状态。

复杂 Agent 需要显式状态,才能恢复、观测和控制。

误区五:把安全寄托给模型自觉

Prompt 可以提醒模型,但不能替代权限系统。

高风险动作必须由 Harness 强制检查。

总结

AI Agent 工程体系可以收束为三件事:

1
2
3
Prompt Engineering:定义行为规则,让模型知道应该如何判断和输出。
Context Engineering:管理信息供给,让模型在每一步看到正确上下文。
Harness Engineering:编排执行系统,让模型决策变成可控、可观测、可恢复的动作。

三者缺一不可。

只有 Prompt,Agent 会说但不一定知道事实。

只有 Context,Agent 知道事实但不一定按规则行动。

只有 Harness,Agent 有执行能力但可能行为混乱。

真正稳定的 Agent,不是靠某个超强 prompt 拼出来的,而是靠三层工程共同约束出来的。

最后用一句话概括:

Prompt 决定 Agent 的规则,Context 决定 Agent 的视野,Harness 决定 Agent 的行动边界。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计