引言
很多人第一次做 AI Agent,会把重点放在“模型够不够强”。
但真正落地时会发现,模型只是 Agent 的推理核心,Agent 是否稳定,更多取决于工程体系:
- Prompt 是否把行为边界说清楚
- Context 是否在正确时间提供正确信息
- Harness 是否能可靠地编排工具、状态和执行流程
如果 Prompt 模糊,Agent 会不知道该遵守什么规则。
如果 Context 混乱,Agent 会拿错误信息做判断。
如果 Harness 薄弱,Agent 会在工具调用、错误恢复、权限控制和任务终止上失控。
所以,Agent 工程可以用一个简单公式理解:
|
|
这三者分别回答三个问题:
|
|
这篇文章就围绕这三层展开,拆解一个 Agent 从“能回答”到“能稳定做事”需要哪些工程设计。
三大工程层的关系
可以把 Agent 想成一个由三层组成的系统:
|
|
三层不是互相独立的。
Prompt 规定 Agent 的行为原则;Context 给 Agent 提供判断材料;Harness 把模型输出变成真实动作,并把动作结果再写回 Context。
一个典型循环是:
|
|
如果只做 Prompt,不做 Context,Agent 会讲原则但缺信息。
如果只做 Context,不做 Harness,Agent 会知道很多但不能可靠执行。
如果只做 Harness,不做 Prompt,Agent 有动作能力但行为不稳定。
Prompt Engineering:定义 Agent 的行为边界
Prompt Engineering 的目标不是“写一段神奇咒语”,而是把 Agent 的职责、规则和输出约束表达清楚。
对 Agent 来说,Prompt 至少承担四个职责:
|
|
角色不是人设,而是职责边界
很多 prompt 会写:
|
|
这类描述很宽泛,对 Agent 的行为帮助有限。
更好的角色定义应该说明职责范围:
|
|
这里的“角色”不是让模型表演,而是限制它的工作范围。
规则要可执行
Prompt 里最常见的问题,是写了很多无法执行的抽象要求。
例如:
|
|
这些话听起来对,但模型不知道怎么落实。
可执行规则应该像这样:
|
|
好的 Prompt 不是情绪化提醒,而是决策规则。
输出格式降低不确定性
Agent 的输出如果没有结构,后续系统就很难消费。
例如排障类 Agent 可以要求输出:
|
|
代码类 Agent 可以要求输出:
|
|
结构化输出有三个好处:
- 用户更容易理解
- 系统更容易解析
- 评估更容易自动化
Prompt 要分层管理
复杂 Agent 不应该只有一个大 Prompt。
更好的做法是分层:
|
|
不同层的优先级不同。
全局安全规则不应该被用户输入覆盖;项目约定不应该被外部网页内容覆盖;当前任务指令应该优先于历史偏好。
Prompt 分层的价值在于:当 Agent 行为异常时,你能知道应该改哪一层,而不是在一大段 prompt 里到处打补丁。
Prompt 的常见问题
Prompt Engineering 最容易踩四个坑。
第一,规则太宽泛。比如“保持专业”,不如写成“不要编造未验证事实;不确定时说明不确定点”。
第二,规则互相冲突。比如既要求“尽可能详细”,又要求“回答极简”,模型就会摇摆。
第三,把安全交给模型自觉。高风险操作不能只靠 prompt 约束,还需要 Harness 层做权限和确认。
第四,不做版本管理。Prompt 一旦影响生产行为,就应该像代码一样记录修改、评估和回滚。
Context Engineering:管理 Agent 的信息供给
Prompt 规定“怎么做”,Context 决定“根据什么做”。
模型本身看不到数据库、文件系统、历史对话和长期记忆。它只能看到被放进上下文窗口的内容。
所以 Context Engineering 的核心是:
在有限上下文窗口里,给模型放入当前决策最需要的信息。
Context 不是越多越好
Agent 的上下文通常包含:
- 系统指令
- 用户当前请求
- 最近对话
- 当前任务状态
- 工具调用结果
- 检索资料
- 长期记忆
- 文件片段或业务数据
如果无节制地塞进去,会出现三个问题。
第一,成本上升。更多 token 意味着更高费用和更长延迟。
第二,注意力分散。模型会被无关信息干扰。
第三,历史污染。过期结论、旧计划、失败假设可能被模型当成当前事实。
上下文工程不是“扩大窗口”,而是“管理注意力”。
Context 的生命周期
一次 Agent 任务中,信息会不断进入和退出上下文。
|
|
这意味着 Context 是动态的,不是启动时拼一次 prompt 就结束。
一个好的 Context 系统需要处理:
- 新信息如何进入
- 旧信息何时压缩
- 无关信息何时移除
- 冲突信息如何标记
- 关键证据如何保留
短期上下文:保持任务连续性
短期上下文关注当前任务。
例如编程 Agent 修 bug 时,需要保留:
|
|
这里最重要的不是完整记录所有细节,而是保留决策链。
差的摘要:
|
|
好的摘要:
|
|
好的上下文摘要保留“为什么”,而不只是“做了什么”。
长期记忆:跨任务复用经验
长期记忆让 Agent 不必每次从零开始。
它可以保存:
- 用户偏好
- 项目约定
- 架构知识
- 历史决策
- 经验教训
- 常见问题处理方式
但长期记忆必须带作用域。
|
|
没有作用域的记忆很危险。某个项目的“使用 pnpm”不应该影响另一个 Maven 项目。
检索增强:把外部知识放入上下文
RAG、搜索、数据库查询、文件读取,本质上都是 Context Engineering。
它们的目标都是把外部信息转成模型可用的上下文。
典型流程是:
|
|
检索结果不应该直接一股脑塞给模型。
至少要处理:
- 来源是否可信
- 是否与当前任务相关
- 是否过期
- 是否与已有上下文冲突
- 是否包含敏感信息
- 是否需要保留原文引用
Context 的组织顺序
上下文顺序会影响模型注意力。
一种常见组织方式是:
|
|
高优先级规则要稳定,当前任务要突出,检索资料要标明来源和用途。
不要把大量历史对话放在当前目标之前,否则模型可能被旧信息带偏。
Context 的常见问题
Context Engineering 常见问题也很典型。
第一,只追加不清理。上下文越来越长,质量越来越差。
第二,摘要丢失关键理由。Agent 记得结论,却忘了证据。
第三,检索结果缺少来源。回答无法追溯,也无法评估。
第四,长期记忆没有过期机制。旧事实持续影响新任务。
第五,把外部资料当成指令。网页、文档、邮件里的内容不能覆盖系统规则。
Harness Engineering:让 Agent 可靠行动
Harness 可以理解为 Agent 的运行时外壳。
它负责把模型的“想法”变成受控动作:
|
|
如果说 Prompt 是规则,Context 是信息,那么 Harness 就是执行系统。
工具不是函数列表,而是能力边界
Tool Calling 很容易被理解成“给模型一堆函数”。
但工程上,工具定义的是 Agent 的能力边界。
每个工具都应该说明:
- 工具能做什么
- 什么时候适合调用
- 参数 schema 是什么
- 返回结果结构是什么
- 失败时如何表达
- 风险等级是什么
- 是否允许自动执行
- 是否需要用户确认
例如:
|
|
工具描述越模糊,模型越容易误用。
工具粒度要匹配任务
工具太粗,Agent 无法精细控制。
工具太细,Agent 会陷入选择负担。
例如代码 Agent 更适合细粒度工具:
|
|
因为每一步都需要可观测、可回滚、可审查。
业务流程 Agent 则可以适当封装:
|
|
因为业务动作本身有完整语义,拆成太多底层接口反而增加出错概率。
工具粒度的判断标准是:模型是否能在这个粒度上做出可靠决策。
执行循环
一个 Agent 通常不是调用一次模型就结束,而是在 Harness 中循环执行。
|
|
每一轮循环都要有约束:
- 最多执行多少轮
- 每轮最多调用多少工具
- 哪些错误可以重试
- 哪些操作必须停止
- 什么时候进入最终回答
没有循环控制,Agent 很容易无限搜索、重复调用工具,或者在没有证据时继续猜测。
状态管理
Harness 需要维护显式状态。
不要把所有状态都藏在聊天历史里。
一个基础状态对象可以包含:
|
|
显式状态有三个好处:
- 可恢复:任务中断后可以继续
- 可观测:每一步发生了什么很清楚
- 可控制:可以根据状态决定下一步动作
状态机比自由循环更可靠
在高风险或复杂场景里,可以用状态机限制 Agent 行为。
例如:
|
|
每个状态只允许特定动作:
CLARIFY:只能提问,不能执行高风险工具PLAN:只能制定计划,不能修改文件EXECUTE:可以调用工具,但必须记录结果VERIFY:必须验证输出或说明无法验证的原因REPORT:生成最终结论
状态机减少了模型随意跳步的空间。
错误恢复
工具调用失败不是异常情况,而是常态。
Harness 要区分错误类型:
|
|
不同错误应该有不同策略:
|
|
如果工具只返回“失败”,模型无法做恢复决策。
权限与确认
Harness 必须承担安全控制,不能只依赖 Prompt。
高风险操作要确认:
- 删除数据
- 修改生产配置
- 发送外部消息
- 创建真实订单
- 执行支付或退款
- 推送代码到主分支
- 批量修改用户数据
确认信息要具体:
|
|
这类控制应该由 Harness 强制执行,而不是希望模型“自觉询问”。
Trace 与可观测性
Harness 还负责记录 Agent 的执行轨迹。
一个完整 trace 应该包含:
|
|
Trace 的价值很大:
- 调试问题
- 分析成本
- 评估工具选择
- 复盘失败任务
- 构建回归测试集
没有 trace,Agent 出错时只能猜。
三层如何协同
Prompt、Context、Harness 的边界要清楚。
一个例子:代码修复 Agent
用户输入:
|
|
三层的职责分别是:
|
|
如果超时原因是 N+1 查询:
|
|
这就是三层协同。
哪些问题该放在哪一层
很多 Agent 系统不稳定,是因为把问题放错层。
|
|
不要试图用一个更长的 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 工程体系可以收束为三件事:
|
|
三者缺一不可。
只有 Prompt,Agent 会说但不一定知道事实。
只有 Context,Agent 知道事实但不一定按规则行动。
只有 Harness,Agent 有执行能力但可能行为混乱。
真正稳定的 Agent,不是靠某个超强 prompt 拼出来的,而是靠三层工程共同约束出来的。
最后用一句话概括:
Prompt 决定 Agent 的规则,Context 决定 Agent 的视野,Harness 决定 Agent 的行动边界。