第十一章:三大工程范式(Prompt/Context/Harness Engineering)对比
Prompt Engineering ⊂ Context Engineering ⊂ Harness Engineering,三大工程范式嵌套递进。理解它们的关系,是从”会写Prompt”到”能构建生产级Agent系统”的关键跃迁。
三个工程范式,嵌套而非并列:Prompt ⊂ Context ⊂ Harness
理解它们的关系,是从”会写 Prompt”到”能构建生产级 Agent 系统”的关键跃迁。
11.1 三大范式总览
graph TD
subgraph Harness["Harness Engineering 线束工程"]
direction TB
subgraph Context["Context Engineering 上下文工程"]
direction TB
Prompt["Prompt Engineering<br/>提示词工程"]
end
end
style Harness fill:#f3e5f5,stroke:#7b1fa2
style Context fill:#fff9c4,stroke:#f9a825
style Prompt fill:#e3f2fd,stroke:#1565c0
| 维度 | Prompt Engineering | Context Engineering | Harness Engineering |
|---|---|---|---|
| 核心问题 | 表达 — 如何写好指令 | 信息 — 给 Agent 看什么 | 执行 — 系统如何不出错 |
| 范围 | 一段文本字符串 | 动态的信息管道 | 完整的基础设施和编排 |
| 关注点 | 用词、措辞、示例 | 信息质量、时机、格式 | 可靠性、安全性、可观测性、恢复 |
| 性质 | 静态 | 动态(每轮变化) | 架构性(跨运行持久) |
| 技能要求 | 写作能力 | 系统设计能力 | 工程架构能力 |
| 失败模式 | 指令不好 → 输出差 | 缺少上下文 → 幻觉/错误动作 | 系统崩溃/失控/无法恢复 |
11.2 Prompt Engineering(提示词工程)
定义
Prompt Engineering 是编写和组织给 LLM 的文本指令,以引导其产生期望输出的学科。它关注的是”如何写好指令“ — 提示词中的措辞、结构和示例。
核心技术
| 技术 | 描述 | 适用场景 |
|---|---|---|
| Zero-shot | 直接给指令,不提供示例。依赖模型预训练知识 | 简单分类、格式转换、翻译 |
| Few-shot | 提供 2-5 个输入/输出示例 | 格式不直观的任务 |
| Chain-of-Thought (CoT) | 让模型”一步步思考”,先推理再回答 | 数学、逻辑推理 |
| Tree-of-Thought (ToT) | 并行探索多条推理路径,评估选最优 | 复杂规划、创意任务 |
| ReAct | 推理与行动交替:思考 → 行动 → 观察 → 循环 | 需要工具调用的 Agent |
| Self-consistency | 采样多条 CoT 路径,取多数投票 | 高风险推理 |
在三大框架中的代码体现
LangChain — ChatPromptTemplate:
1 | from langchain_core.prompts import ChatPromptTemplate |
LangGraph — State 中的系统消息:
1 | from langgraph.graph import StateGraph, MessagesState, START |
DeepAgents — system_prompt 参数:
1 | from deepagents import create_deep_agent |
最佳实践
- 清晰胜于聪明 — 简洁直接的指令优于花哨的措辞
- 结构化格式 — 用 XML 标签(
<instructions>、<examples>)或 Markdown 标题组织 - 恰当的抽象层级 — 不要太模糊(无指导),也不要太具体(变成脆弱的 if-else)
- 精选示例 — 少量多样化的典型示例 > 大量边界用例
- 最小化起步 — 先写最简单的能用的 Prompt,只在失败时增加指令
局限性
- 静态 — Prompt 写好就不变了,不会适应新信息
- 无视上下文 — 不能检索外部数据、管理历史、处理记忆
- 规模脆弱 — 加更多指令修 Bug → 不可维护的”意大利面条式” Prompt
- 单轮思维 — 为一次性交互设计,不适合多轮 Agent 工作流
11.3 Context Engineering(上下文工程)
定义
Context Engineering 是设计、策划和交付正确信息的学科 — 在正确的时机、以正确的格式,让 LLM 能可靠地完成任务。
“我更喜欢’上下文工程’这个词,而不是’提示词工程’。它更好地描述了核心技能:为任务提供所有必要的上下文,让 LLM 有可能解决它。”
— Tobi Lütke,Shopify CEO
“上下文工程是在不断演化的信息宇宙中,策划什么进入有限上下文窗口的艺术和科学。”
— Anthropic
关键洞察:大多数 Agent 失败不是模型失败 — 而是上下文失败。模型没收到错误指令;它根本没收到正确的信息。
Prompt Engineering vs Context Engineering
| 维度 | Prompt Engineering | Context Engineering |
|---|---|---|
| 范围 | 写一段指令文本 | 管理整个上下文状态 — 系统提示词 + 工具 + 检索数据 + 记忆 + 对话历史 |
| 本质 | 一个静态模板 | 一个动态系统的输出 |
| 思维模式 | “写一个更好的 Prompt” | “构建一个更好的上下文管道” |
| 时机 | 一次性 | 每轮迭代 — 每次调用前都要策划 |
| 关注点 | 用词和措辞 | 信息质量、工具可用性、交付时机、格式 |
完整的上下文栈
模型生成响应前看到的所有内容:
graph BT L1["1. 系统提示词(指令)"] L2["2. 用户提示词(当前任务)"] L3["3. 状态/历史(对话记录)"] L4["4. 长期记忆(用户偏好)"] L5["5. 检索信息(RAG)"] L6["6. 可用工具定义(Function Schema)"] L7["7. 结构化输出约束(JSON Schema)"] L1 --> L2 --> L3 --> L4 --> L5 --> L6 --> L7 style L1 fill:#e3f2fd style L2 fill:#e3f2fd style L3 fill:#fff9c4 style L4 fill:#fff9c4 style L5 fill:#f3e5f5 style L6 fill:#ffebee style L7 fill:#ffebee
每一层都是一个工程决策 — 包含什么、排除什么、用什么格式。
核心模式
模式一:RAG(检索增强生成)
上下文栈中的一个组件。从文档、数据库或 API 中动态检索外部知识:
1 | from langchain_core.vectorstores import InMemoryVectorStore |
模式二:上下文窗口管理
40% 利用率阈值(Dex Horthy 的发现):
| 区域 | 上下文占用率 | Agent 行为 |
|---|---|---|
| 聪明区 | 0-40% | 聚焦推理、准确的工具调用、高质量输出 |
| 愚蠢区 | >40% | 更多幻觉、兜圈子、格式混乱、质量下降 |
LangGraph — 消息裁剪:
1 | from langchain_core.messages.utils import trim_messages, count_tokens_approximately |
LangGraph — 对话摘要:
1 | from langgraph.graph import MessagesState |
模式三:即时检索(Just-in-Time Retrieval)
Agent 维护轻量级标识符(文件路径、存储查询、URL),运行时按需加载数据。类似人类认知 — 我们不会记住一切,而是使用索引系统。
1 | # ❌ 坏做法:把所有文件预加载到系统提示词 |
模式四:工作记忆 vs 长期记忆
| 类型 | 作用域 | 实现方式 | 示例 |
|---|---|---|---|
| 工作记忆 | 当前对话(会话级) | 上下文窗口、检查点状态 | 当前任务、最近工具结果 |
| 长期记忆 | 跨会话持久化 | 外部存储、文件系统、向量 DB | 用户偏好、项目历史 |
在 DeepAgents 中的体现
DeepAgents 是上下文工程的最佳实践集合:
1. 上下文压缩(85% 阈值自动触发)
| 阶段 | 触发条件 | 机制 |
|---|---|---|
| 工具结果卸载 | 工具响应 > 20,000 tokens | 完整结果保存到文件系统,替换为文件路径 + 前 10 行预览 |
| 工具输入卸载 | 上下文超过模型窗口 85% | 旧的文件写入/编辑工具调用截断,替换为文件系统指针 |
| 对话摘要 | 卸载用尽后仍超阈值 | LLM 生成结构化摘要(会话意图 + 产出物 + 下一步);完整历史保留在文件系统中 |
1 | # DeepAgents 内置,无需手动配置 |
2. write_todos 规划上下文
write_todos 工具把复杂任务拆解为可追踪的子任务。它同时服务于规划和上下文持久化 — 待办列表作为结构化工作记忆,在上下文压缩后仍能存活。
3. 文件系统后端扩展上下文
文件系统同时充当持久存储和上下文管理 — 大输出保存到文件而非占用上下文,Agent 可以按需重新读取。
4. 子 Agent 隔离上下文
task 工具委派工作给具有隔离上下文窗口的子 Agent — 它们不共享父 Agent 的对话历史,防止上下文污染。每个子 Agent 只返回浓缩的摘要。
5. 五类上下文总览
| 上下文类型 | 控制方 | 作用范围 |
|---|---|---|
| 输入上下文 | 开发者 | 系统提示词、记忆、技能(启动时加载) |
| 运行时上下文 | 调用者 | 用户元数据、API Key(每次 invoke 传入) |
| 上下文压缩 | 框架自动 | 大内容卸载 + 历史摘要(到达阈值时触发) |
| 上下文隔离 | 子 Agent | 每个子 Agent 独立上下文,不污染主 Agent |
| 长期记忆 | 开发者 + 框架 | 跨会话持久化存储 |
11.4 Harness Engineering(线束工程)
定义
Harness Engineering 是为 LLM 构建基础设施、工具和编排层的工程,使其达到生产可用级别。
核心公式:Agent = Model + Harness
模型只是一个 text-in/text-out 的函数。Harness 是其他一切 — 系统提示词、工具调用、文件系统、沙箱环境、编排逻辑、中间件、反馈循环、约束机制、错误恢复。
类比:Model = CPU,Harness = 操作系统。再强的芯片配一个崩溃频发的操作系统,体验也不如老芯片配稳定系统。
“模型决定天花板,Harness 决定地板。与其纠结选哪个模型,不如先把 Harness 做好。”
模型不能做什么 → Harness 必须补偿什么
| 模型不能做 | Harness 如何补偿 | 对应组件 |
|---|---|---|
| 记住多轮历史 | 维护并注入历史 | 记忆系统 |
| 执行代码或运行命令 | 提供 Bash + 执行环境 | 通用执行 |
| 获取实时信息 | 搜索、MCP 工具 | 外部知识 |
| 操纵文件和环境 | 文件系统抽象 + Git | 文件系统 |
| 知道自己做得对不对 | 沙箱 + 测试工具 + 浏览器自动化 | 验证循环 |
| 长任务中保持一致 | 上下文压缩、记忆文件、进度追踪 | 上下文管理 |
六层架构
flowchart TD L1["L1 信息边界<br/>Agent 该/不该知道什么<br/>━━━━━━━━━━<br/>岗位描述 — 关注什么"] L2["L2 工具系统<br/>Agent 如何与外部世界交互<br/>━━━━━━━━━━<br/>办公工具 — 用什么工作"] L3["L3 执行编排<br/>如何串联多步任务<br/>━━━━━━━━━━<br/>标准操作流程 — 按什么步骤"] L4["L4 记忆与状态<br/>如何管理中间结果<br/>━━━━━━━━━━<br/>项目管理 — 如何记住做过的事"] L5["L5 评估与可观测性<br/>Agent 如何知道自己做得对<br/>━━━━━━━━━━<br/>质检流程 — 如何验证正确性"] L6["L6 约束、验证与恢复<br/>出错了怎么办<br/>━━━━━━━━━━<br/>红线和应急预案 — 绝不能发生"] L1 --> L2 --> L3 --> L4 --> L5 --> L6 style L1 fill:#e3f2fd style L2 fill:#e3f2fd style L3 fill:#fff9c4 style L4 fill:#fff9c4 style L5 fill:#f3e5f5 style L6 fill:#ffebee
| 层级 | 名称 | 解决的问题 | 关键设计 |
|---|---|---|---|
| L1 | 信息边界 | Agent 该/不该知道什么 | 定义角色和目标、裁剪无关信息、结构化组织任务状态 |
| L2 | 工具系统 | Agent 如何与外部世界交互 | 工具选择、调用时机、结果精炼与反馈 |
| L3 | 执行编排 | 如何串联多步任务 | 遵循”理解→判断→分析→生成→检查”循环 |
| L4 | 记忆与状态 | 如何管理中间结果 | 当前任务状态、中间产物、长期记忆 |
| L5 | 评估与可观测性 | Agent 如何知道自己做得对 | 独立于生成过程的验证 |
| L6 | 约束、验证与恢复 | 出错了怎么办 | 错误拦截、重试、失败回滚 |
类比新员工入职:
- L1 = 岗位描述(关注什么)
- L2 = 办公工具(用什么工作)
- L3 = 标准操作流程(按什么步骤)
- L4 = 项目管理系统和笔记本(如何记住做过的事)
- L5 = 质检流程(如何验证正确性)
- L6 = 红线和应急预案(什么绝不能发生、出了事怎么办)
实操建议:先做 L1(信息边界)和 L6(约束与恢复)— ROI 最高。中间层随复杂度增长再补。
在 DeepAgents 中的体现
create_deep_agent() 本身就是 Harness 的组装器:
1 | from deepagents import create_deep_agent |
DeepAgents 的 Harness 组件与六层对应:
| 组件 | Harness 层级 | 说明 |
|---|---|---|
create_deep_agent 配置 | L1, L3 | 模型选择、系统提示词、编排循环 |
| 工具绑定 | L2 | 预配置工具(文件系统、Shell、搜索、子 Agent) |
| 权限系统 | L6 | 沙箱隔离、工具级访问控制 |
| 中间件 | L3, L6 | 上下文压缩中间件在 Agent 轮次间运行 |
| 结构化输出 | L5 | 工具返回结构化、已验证的数据 |
write_todos | L4 | 规划和进度追踪 |
task(子 Agent) | L3, L4 | 任务委派与上下文隔离 |
| 自动摘要 | L4, L6 | 防止上下文溢出 |
| 文件系统后端 | L4 | 超出上下文窗口的持久存储 |
| HITL 中断 | L6 | 敏感操作的人类审批 |
在 LangGraph 中的体现
LangGraph 提供了构建 Harness 的底层原语:
1 | from langgraph.graph import StateGraph, MessagesState, START, END |
实证:瓶颈在 Harness,不在模型
| 来源 | 只改了什么 | 结果 |
|---|---|---|
| Can.ac 实验 | 同一个模型,只改工具调用接口格式 | 得分 6.7% → 68.3%(10 倍提升,模型完全没换) |
| LangChain Terminal Bench 2.0 | 优化 Agent 运行时(文档组织、验证循环、追踪) | 排名 #30 → #5,得分 52.8% → 66.5%(模型完全没换) |
11.5 三大范式如何协同工作
以构建客服 Agent为例:
flowchart TD
subgraph PE["Layer 1 — Prompt Engineering"]
P1["系统提示词定义"]
P2["'你是一个有帮助的客服代表<br/>回复要简洁且共情<br/>如果用户问账单问题<br/>先要他们的账户 ID'"]
P1 --> P2
end
subgraph CE["Layer 2 — Context Engineering"]
C1["从数据库检索用户最近的订单"]
C2["加载用户账户历史到上下文"]
C3["搜索知识库中的相关 FAQ"]
C4["裁剪对话历史以适应上下文窗口"]
C5["对话过长时进行摘要"]
C1 --> C2 --> C3 --> C4 --> C5
end
subgraph HE["Layer 3 — Harness Engineering"]
H1["工具列表:<br/>lookup_order / process_refund / escalate_to_human"]
H2["Checkpointer 持久化状态"]
H3["interrupt_before=process_refund<br/>人类审批"]
H4["错误处理:<br/>API 超时重试,降级到转人工"]
H5["可观测性:<br/>记录每次工具调用,追踪解决率"]
H6["限流:<br/>每会话最多 5 次退款尝试"]
H1 --> H2 --> H3 --> H4 --> H5 --> H6
end
PE --> CE --> HE
style PE fill:#e3f2fd
style CE fill:#fff9c4
style HE fill:#f3e5f5
成熟度模型
flowchart LR
subgraph L0["Level 0<br/>无 Harness"]
L0D["直接 Prompt 到 Agent<br/>无结构约束"]
end
subgraph L1["Level 1<br/>基础约束"]
L1D["AGENTS.md + 基础检查<br/>+ 手动测试"]
end
subgraph L2["Level 2<br/>反馈循环"]
L2D["CI/CD + 自动测试<br/>+ 进度追踪"]
end
subgraph L3["Level 3<br/>专业 Agent"]
L3D["多 Agent 分工<br/>+ 分层上下文<br/>+ 持久记忆"]
end
subgraph L4["Level 4<br/>自主循环"]
L4D["无人值守并行<br/>+ 自动熵管理<br/>+ 自愈"]
end
L0 -->|添加约束| L1
L1 -->|自动化| L2
L2 -->|多Agent| L3
L3 -->|自治化| L4
style L0 fill:#ffebee
style L1 fill:#fff9c4
style L2 fill:#e3f2fd
style L3 fill:#f3e5f5
style L4 fill:#e8f5e9
| 阶段 | 特征 | 工程师角色 |
|---|---|---|
| Level 0:无 Harness | 直接 Prompt 到 Agent,无结构约束 | 手动编码 + 偶尔 AI 辅助 |
| Level 1:基础约束 | AGENTS.md + 基础检查 + 手动测试 | 主要编码,AI 辅助 |
| Level 2:反馈循环 | CI/CD + 自动测试 + 进度追踪 | 规划 + 审查为主 |
| Level 3:专业 Agent | 多 Agent 分工 + 分层上下文 + 持久记忆 | 环境设计 + 管理 |
| Level 4:自主循环 | 无人值守并行 + 自动熵管理 + 自愈 | 架构师 + 质量守门人 |
11.6 在你的代码中如何体现
Prompt Engineering 的代码体现
1 | # 1. system_prompt 参数 — 最直接的 Prompt Engineering |
Context Engineering 的代码体现
1 | # 1. 记忆配置 — 始终加载的上下文 |
Harness Engineering 的代码体现
1 | # 1. 权限控制 — L6 约束 |
11.7 何时需要哪一层
| 场景 | 只需 Prompt | 需要 Context | 需要 Harness |
|---|---|---|---|
| 单轮问答 | ✅ | ||
| 简单分类 | ✅ | ||
| 文本转换 | ✅ | ||
| 多轮对话 | ✅ | ||
| RAG/知识依赖 | ✅ | ||
| 需要用户记忆 | ✅ | ||
| 超长文档 | ✅ | ||
| 生产部署 | ✅ | ||
| 长时间自主 Agent | ✅ | ||
| 错误恢复和重试 | ✅ | ||
| 安全护栏 | ✅ |
核心原则:
- Prompt Engineering 是必要但不充分的 — 它是基础,但无法应对动态信息需求和生产问题
- Context Engineering 是新兴学科 — 随着 Agent 能力增强和任务复杂化,管理”什么进入上下文窗口”比”怎么措辞”更重要
- Harness Engineering 是生产力的乘数 — 模型决定天花板,Harness 决定地板
- 它们是嵌套的,不是替代的 — 你不会选一个弃其他。你分层构建:写好 Prompt(L1)→ 构建上下文管道(L2)→ 包装生产基础设施(L3)
本章小结
1 | 你的代码里每天都在用这三种工程: |
一句话总结:Prompt Engineering 教你怎么说话,Context Engineering 教你怎么给信息,Harness Engineering 教你怎么让系统不崩溃。三者嵌套,缺一不可。