文章定位

这篇文章面向已经了解大模型、Agent、RAG 基础概念的开发者。它想讨论的问题不是“怎么写出一个更漂亮的 Prompt”,而是 AI 应用在真正落地时,为什么会从提示工程逐渐走向上下文工程,再进一步走向 Harness 工程。

我的理解是:提示工程解决的是“怎么问”的问题,上下文工程解决的是“给模型什么信息”的问题,而 Harness 工程解决的是“如何把模型能力变成稳定、可测试、可迭代的系统”的问题。

如果只看一次模型调用,Prompt 似乎就是全部。但只要任务稍微复杂一点,比如需要读取资料、调用工具、修改代码、执行命令、处理异常、保存中间状态,单纯优化提示词就会变得不够用。AI 应用的重心也会从“写好一段输入”转向“设计一个能持续运行的工程系统”。

一、提示工程

1.1 出现背景

大模型应用早期最常见的开发方式,就是围绕 Prompt 做优化。因为 Prompt 是开发者和模型之间最直接的交互接口,我们无法像传统程序那样逐行控制模型内部的计算过程,只能通过输入文本来影响模型的行为。

在这个阶段,很多问题看起来都可以通过“把话说清楚一点”来改善。例如让模型扮演某个角色,告诉它输出格式,给它几个示例,或者要求它一步一步思考。对于摘要、分类、信息抽取、文本改写、简单问答这类任务,提示工程确实能带来非常明显的效果。

所以提示工程的价值并不低。它是大模型应用最早的工程入口,也是开发者理解模型行为的重要方式。只不过,当任务从单轮生成走向复杂流程时,Prompt 本身承载的东西会越来越多,维护难度也会随之上升。

1.2 核心目标

提示工程的第一个目标,是让模型理解任务目标。模型需要知道当前要完成什么事情,最终交付物是什么,哪些内容是重点,哪些内容应该避免。

第二个目标,是约束输出格式。很多 AI 应用并不是只需要一段自然语言回答,而是需要 JSON、Markdown、SQL、代码片段、表格或者固定结构的报告。如果输出格式不稳定,后续程序就很难继续处理。

第三个目标,是降低回答的不确定性。大模型本身具有生成式特征,同一个问题可能产生不同表达。好的 Prompt 会尽量减少歧义,让模型的输出更接近预期范围。

第四个目标,是通过示例引导模型学习任务模式。Few-shot 示例的作用不是给模型灌输新知识,而是让模型在当前上下文中模仿一种输入输出关系。对于格式复杂或者标准比较隐含的任务,示例往往比抽象描述更有效。

1.3 常见提示方法

常见的提示方法包括角色设定、任务拆解、Few-shot 示例、输出格式约束、分步推理引导、反思与自检提示等。

角色设定可以帮助模型进入某种回答风格。例如让模型以“资深后端工程师”的方式分析问题,通常会比单纯说“帮我看看代码”更容易得到结构化的技术回答。

任务拆解适用于复杂问题。与其让模型一次性完成所有步骤,不如把目标拆成若干阶段,例如先分析需求,再设计方案,最后生成代码或文档。

Few-shot 示例适合用来稳定输出模式。比如希望模型把一段文本转换成固定字段,就可以给出几组输入和输出,让模型模仿格式。

输出格式约束则更偏工程化。很多时候我们会要求模型只输出 JSON,或者按照固定 Markdown 标题组织内容,这样后续程序可以继续解析和处理。

分步推理引导和反思提示可以提升复杂任务的质量,但也需要谨慎使用。并不是所有任务都需要长推理,过度要求模型展开思考可能会增加成本,也可能引入无关内容。

1.4 提示工程的局限

提示工程最大的问题,是它对上下文质量高度敏感。同一段 Prompt,在不同上下文中可能表现完全不同。如果输入资料本身混乱、缺失或者相互矛盾,再精巧的提示词也很难让模型稳定输出高质量结果。

第二个问题是难以长期维护。随着业务规则变多,Prompt 很容易变成一大段混杂了角色、规则、示例、格式、异常处理和补充说明的文本。它看起来像配置,实际却承担了代码、文档和策略的多重职责。

第三个问题是对复杂任务的稳定性不足。复杂任务通常不是一次回答就结束,而是需要多轮交互、工具调用、状态更新和结果校验。Prompt 可以影响模型当前这一轮的行为,但很难单独管理整个任务生命周期。

第四个问题是无法单独解决系统问题。例如工具调用失败后如何重试,长任务中如何保留关键状态,输出结果如何自动评估,失败样例如何沉淀,这些都已经超出了提示词本身的范围。

因此,提示工程是必要的,但不是 AI 应用工程化的终点。

二、上下文工程

2.1 出现背景

当 AI 应用从单轮问答走向多轮协作时,开发者会发现:真正影响模型表现的,不只是 Prompt 写得好不好,还有模型在每一轮调用时“看见了什么”。

模型需要处理越来越多的外部信息。比如用户的历史需求、系统规则、检索到的文档、工具返回结果、代码仓库结构、运行错误、任务计划和中间状态。这些信息共同组成了模型的上下文。

Agent、RAG 和工具调用进一步放大了这个问题。RAG 会把外部知识注入上下文,工具调用会把外部系统的返回结果注入上下文,Agent loop 会不断产生新的观察、计划和执行结果。上下文不再是一段静态输入,而是一个动态变化的信息环境。

这时,工程重点就从“如何写 Prompt”扩展为“如何管理上下文”。

2.2 什么是上下文

上下文可以理解为模型在一次调用中能够看到的全部信息。它不仅包括用户当前输入,也包括系统指令、历史对话、检索文档、工具返回结果、任务状态、用户偏好和约束条件。

用户输入告诉模型当前要做什么。系统指令定义模型的角色、边界和行为规范。历史对话提供任务连续性。检索文档提供外部知识。工具返回结果提供来自真实系统的观察。任务状态记录当前进展。用户偏好帮助模型保持长期一致性。约束条件则用于限制模型的行为范围。

这些内容如果组织得好,模型就更容易做出正确判断。如果组织得不好,模型可能会被无关信息干扰,忽略关键事实,甚至把过期信息当成当前状态。

所以,上下文不是简单地“塞更多信息”。上下文工程的重点是选择、组织、压缩和更新信息。

2.3 关注的问题

上下文工程首先要回答:给模型什么信息。不是所有信息都应该进入上下文。相关性低、重复、过期或者噪声很大的内容,会消耗上下文窗口,也会稀释模型注意力。

其次是:什么时候给。某些信息只在任务开始时需要,例如总体目标和输出规范;某些信息只在特定阶段需要,例如检索结果、工具错误、代码片段;还有一些信息需要持续保留,例如用户明确提出的约束。

第三是:给多少。大模型上下文窗口虽然越来越长,但长上下文不等于好上下文。上下文越长,成本越高,延迟越大,模型也越可能遗漏细节。工程上需要在完整性和简洁性之间取平衡。

第四是:以什么结构给。结构化上下文通常比随意拼接文本更稳定。例如把任务目标、已知事实、约束条件、当前状态、可用工具、输出要求分块组织,模型更容易理解每类信息的作用。

最后是:如何过滤噪声、避免上下文污染,并在长任务中保留关键状态。上下文污染常见于多轮对话和工具调用场景,例如早期错误结论没有被清理,过期计划仍然留在上下文里,工具返回的大量日志遮蔽了真正重要的错误信息。

2.4 上下文工程和 RAG、Agent 的关系

RAG 是上下文工程的一种典型方式。它的核心不是让模型“记住”所有知识,而是在用户提问时,从外部知识库检索相关内容,再把这些内容作为上下文提供给模型。

从这个角度看,RAG 的文档切分、索引构建、查询改写、召回、重排、上下文拼装,本质上都在服务于上下文质量。检索到的信息越准确、越结构化,模型生成答案的基础就越可靠。

Agent 对上下文工程的要求更高。因为 Agent 不只是回答问题,还会规划任务、调用工具、观察结果、修正计划并继续执行。每一步都会产生新的上下文,也可能带来新的噪声。

长任务尤其依赖上下文压缩、记忆、状态管理和工具结果整理。否则任务执行到后半段时,模型可能已经忘记最初目标,或者被大量中间日志淹没,导致行为漂移。

所以,RAG 关注的是如何把外部知识变成上下文,Agent 关注的是如何在动态过程中持续管理上下文。二者都离不开上下文工程。

2.5 上下文工程的典型策略

第一种策略是信息筛选。进入上下文的信息应该和当前任务直接相关,必要时需要先对检索结果或工具结果做摘要和过滤。

第二种策略是上下文分层。可以把上下文分为长期稳定信息、当前任务信息、临时工具结果和输出约束。不同层级的内容采用不同的保留策略。

第三种策略是历史摘要。多轮对话不能无限追加,应该定期把历史压缩成任务摘要,保留目标、决策、约束、待办事项和关键事实。

第四种策略是工具结果结构化。工具返回内容往往很长,尤其是搜索结果、命令行日志和网页内容。直接塞给模型容易造成噪声,最好提取关键信息、错误原因和下一步可用线索。

第五种策略是任务状态显式化。复杂任务中,模型需要知道当前做到哪一步、哪些步骤完成了、哪些步骤失败了、接下来要做什么。显式状态比让模型从历史对话里自行推断更可靠。

第六种策略是失败信息保留。失败不是无用信息。工具调用失败、测试失败、构建失败都能帮助模型修正方案。关键是保留失败的核心原因,而不是保留全部冗余日志。

第七种策略是长上下文压缩。随着任务推进,旧信息需要被总结、归档或移出当前上下文,只留下对后续决策仍然有价值的部分。

三、为什么需要 Harness Engineering

3.1 AI 应用不只是一次模型调用

上下文工程解决了模型“看见什么”的问题,但真实 AI 应用还不只是一次模型调用。一个可用的 AI 系统通常包含输入处理、上下文构造、模型调用、工具调用、结果校验、错误恢复、日志记录和效果评估等多个环节。

也就是说,模型只是系统中的一个能力组件。它负责理解、生成、推理和决策,但它不应该独自承担所有工程责任。输入是否合法、工具是否可用、输出是否符合格式、失败是否需要重试、成本是否超限,这些都需要系统层面的设计。

如果没有这一层工程外壳,AI 应用很容易停留在 Demo 阶段:单次演示效果不错,但一旦面对真实用户、复杂输入和持续运行,就会出现不稳定、不可复现、难调试的问题。

3.2 真实系统需要解决的问题

真实系统首先需要组织模型调用流程。不同任务可能需要不同链路:有的只需要一次生成,有的需要先检索再生成,有的需要多次工具调用,有的需要人类确认后继续执行。

其次需要接入工具和外部系统。工具不是简单的函数列表,还涉及参数校验、权限控制、错误处理和返回结果整理。

再次需要处理失败和重试。模型可能生成不符合格式的结果,工具可能超时,外部 API 可能失败,检索结果可能为空。系统需要判断哪些失败可以重试,哪些失败需要降级,哪些失败必须交给用户确认。

系统还需要评估输出质量。没有评估,就很难知道 Prompt 或上下文调整到底是变好了还是变差了。尤其是当 AI 应用进入长期迭代后,评估和回归测试会变得非常重要。

最后,系统需要记录日志和复盘。AI 应用的问题往往不是单点错误,而是上下文、模型、工具和控制流程共同作用的结果。没有 Trace 和日志,就很难定位问题发生在哪一步。

四、Harness Engineering

4.1 简介

Harness Engineering 关注的是 AI 应用的整体运行框架。它把 Prompt、Context、Model、Tool、Evaluation、Observation 这些部分组织起来,让它们形成一个可维护的系统。

如果说提示工程偏向“语言层面的控制”,上下文工程偏向“信息层面的控制”,那么 Harness 工程更偏向“系统层面的控制”。它关心的不只是模型能不能生成答案,还关心这个答案是在什么输入下生成的,经过了哪些工具,是否通过校验,失败时如何恢复,下一次如何改进。

在工程实践中,Harness 可以很简单,也可以很复杂。简单的 Harness 可能只是一个脚本:读取输入、拼接 Prompt、调用模型、检查输出格式。复杂的 Harness 可能包含任务队列、工具编排、自动评测、日志系统、权限系统和人工反馈闭环。

4.2 输入层

输入层负责把用户请求转化成系统可以处理的任务。用户的自然语言输入往往是不完整、不规范甚至有歧义的,系统需要先进行请求规范化。

例如,用户说“帮我写一篇博客”,系统需要进一步识别主题、目标读者、文章风格、输出格式和是否需要引用资料。对于接口型任务,还需要做参数校验,确保必要字段存在,类型正确,取值范围合理。

输入层还可以承担意图识别的工作。不同意图对应不同流程:写文章、改文章、查资料、生成代码、运行测试、总结错误,这些任务的上下文和工具需求都不一样。

任务边界确认也很重要。AI 系统应该知道哪些动作可以直接执行,哪些动作需要用户确认,哪些动作超出了当前能力范围。

4.3 Prompt 与 Context 组装层

这一层负责把系统提示、任务提示、检索内容、工具结果、记忆与状态、输出格式要求组织成模型输入。

系统提示通常比较稳定,用来定义模型的角色、行为边界和全局规则。任务提示更贴近当前请求,用来说明本次要完成什么。检索内容提供外部知识,工具结果提供真实观察,记忆与状态保证任务连续性,输出格式要求则让结果更容易被后续程序处理。

这一层的关键不是简单拼接,而是有意识地组织信息。例如把“任务目标”“已知事实”“约束条件”“当前状态”“可用资料”“输出要求”分开,让模型能清楚地区分不同信息的作用。

如果这一层设计得不好,模型可能会忽略关键约束,误用过期信息,或者把工具错误当成最终结论。很多 AI 应用看似是模型能力问题,实际上是上下文组装问题。

4.4 执行层

执行层负责真正推动任务运行。它可能只调用一次模型,也可能包含多步骤工作流、工具调用和 Agent loop。

在简单任务中,执行层的流程可能是:构造输入、调用模型、返回结果。在复杂任务中,流程可能变成:先分析任务,再选择工具,执行工具后读取结果,然后根据结果继续规划下一步。

Agent loop 是执行层中比较典型的形态。模型不断根据当前状态做出行动决策,系统执行行动并返回观察结果,模型再基于观察结果继续推理和行动。

执行层还需要维护中间状态。比如当前步骤是否完成、工具调用是否成功、已经产生了哪些文件、还有哪些待办事项。这些状态不仅服务于模型,也服务于系统恢复和调试。

4.5 控制层

控制层负责让系统不要失控。大模型应用天然具有不确定性,所以需要在外部建立约束。

超时控制可以避免任务无限运行。重试机制可以处理临时失败,但重试必须有边界,不能无休止循环。安全约束用于限制高风险行为,例如删除文件、访问敏感数据、执行危险命令。

权限边界也很重要。不同工具应该有不同权限,不同任务也应该有不同执行范围。模型可以提出行动建议,但系统应该决定哪些行动允许执行。

输出格式校验是控制层中非常实用的一部分。比如要求模型输出 JSON,就应该在程序里解析并校验,而不是只相信模型“应该会按格式输出”。当格式不符合预期时,系统可以要求模型修复,或者直接返回错误。

4.6 评估层

评估层负责回答一个关键问题:系统到底有没有变好。

自动评测适合用于格式、事实一致性、覆盖率、分类准确率等相对明确的指标。人工反馈适合用于可读性、解释质量、风格一致性等更主观的维度。

回归测试对 AI 应用尤其重要。每次修改 Prompt、上下文策略或工具链后,都可能影响已有任务表现。如果没有测试集,很难判断这次修改是整体提升,还是只是在某个样例上变好。

测试集构建可以从真实失败样例开始。每一次模型答错、工具调用失败、输出格式不符合要求,都是值得沉淀的评估数据。长期来看,失败样例库会成为 AI 应用迭代中非常有价值的资产。

4.7 观测层

观测层负责让系统可调试、可复盘。AI 应用的错误往往不是一句报错就能解释清楚的,而是发生在一个链路中。

日志可以记录输入、输出、工具调用、错误信息和关键状态变化。Trace 可以展示一次任务从开始到结束经过了哪些步骤,每一步的输入输出是什么。

成本统计和延迟统计也很重要。大模型调用通常有成本,复杂 Agent 任务还可能多次调用模型和工具。如果不观测成本和延迟,系统很容易在效果还不错的同时变得昂贵且缓慢。

失败案例分析则用于反向改进系统。一次失败可能来自 Prompt 表述不清,也可能来自检索质量差、上下文污染、工具返回结果太乱、输出校验缺失。观测层的价值,就是帮助我们找到真正的问题位置。

五、提示工程、上下文工程、Harness 工程之间的关系

5.1 三者的递进关系

三者可以看作 AI 应用工程化的三个层次:

1
2
3
4
5
6
7
8
9
10
11
Prompt Engineering
关注:如何写好一次模型输入
解决:让模型更好地理解任务

Context Engineering
关注:如何组织模型所需的信息环境
解决:让模型在正确的信息中工作

Harness Engineering
关注:如何把模型能力变成稳定系统
解决:让 AI 应用可运行、可测试、可迭代

提示工程关注的是一次调用中“怎么表达任务”。上下文工程关注的是一次调用前“应该给模型什么信息”。Harness 工程关注的是整个系统“如何持续可靠地运行”。

从这个角度看,三者的关注范围逐渐扩大:从语言表达,到信息组织,再到系统工程。

5.2 三者不是替代关系

需要注意的是,三者不是替代关系。并不是有了上下文工程就不需要提示工程,也不是有了 Harness 工程就不需要上下文工程。

Prompt Engineering 仍然是入口。模型需要清晰的任务描述、角色边界和输出要求。

Context Engineering 是能力放大的关键。模型是否能做出正确判断,往往取决于它是否获得了正确、足够、干净的上下文。

Harness Engineering 是生产化和长期维护的基础。只有把模型调用放进可运行、可测试、可观测的框架中,AI 应用才有机会从 Demo 走向真实系统。

三者合在一起,才构成比较完整的 AI 应用工程方法。

六、用一个例子理解三者差异

6.1 案例:构建一个技术博客写作助手

假设我们要构建一个技术博客写作助手,目标是根据主题生成一篇符合个人博客风格的技术文章。

这个任务看起来很简单:给模型一个主题,让它生成 Markdown。但如果真正想把它做成稳定工具,就会发现里面包含很多工程细节。

文章需要有合适的标题、清晰的结构、正确的 front-matter、统一的标签和分类,还要符合已有博客的写作风格。如果需要结合资料,还要处理资料检索、引用整理和内容筛选。如果生成后要进入发布流程,还要检查 Hexo 构建是否通过。

6.2 提示工程阶段

在提示工程阶段,我们主要关注如何让模型生成一篇文章。比如编写 Prompt,明确文章主题,约束输出格式,并要求生成 Markdown。

一个简单的 Prompt 可能是:

1
2
请写一篇关于提示工程、上下文工程和 Harness 工程的技术博客,
使用中文,输出 Markdown,结构清晰,适合开发者阅读。

这个阶段的重点是让模型理解写作任务。如果任务比较简单,这样已经能得到一篇看起来不错的文章。但它还不一定符合个人博客的风格,也不一定有正确的 front-matter 和分类规范。

6.3 上下文工程阶段

进入上下文工程阶段后,我们会开始考虑:为了让模型写得更像“我的博客”,应该给它哪些上下文。

例如加入已有博客文章风格,让模型了解平时的表达方式;加入文章分类和标签规范,避免生成不一致的元信息;加入用户历史写作偏好,让文章更符合长期风格;加入相关资料和参考文章,减少空泛表达;加入 Hexo front-matter 规范,保证文章可以被站点正确解析。

这时,模型输入不再只有一句写作要求,而是包含了任务目标、博客规范、已有风格、参考资料和输出约束。模型生成结果的质量,取决于这些上下文是否准确、干净、结构清晰。

6.4 Harness 工程阶段

到了 Harness 工程阶段,我们考虑的已经不只是“生成文章”,而是“构建一个博客写作流程”。

这个流程可以先自动生成大纲,再根据大纲生成 Markdown 文件。生成后检查 front-matter 是否完整,标签和分类是否符合规范。接着可以运行 Hexo 构建,检查文章是否破坏站点生成。如果构建失败,系统读取错误信息,并尝试自动修复。

同时,Harness 还可以保留生成过程和修改记录。比如本次使用了哪些上下文,模型输出了什么,哪些地方经过人工修改,构建是否通过。这样下一次写类似文章时,就可以复用经验,而不是从零开始。

从这个例子可以看出,提示工程解决的是“怎么让模型写”,上下文工程解决的是“给模型哪些写作资料和规范”,Harness 工程解决的是“如何把写作变成一个可重复、可检查、可改进的流程”。

七、总结

提示工程是在学习如何和模型说话。它通过角色、任务、示例和格式约束,让模型更好地理解当前请求。

上下文工程是在学习如何给模型布置工作环境。它决定模型在执行任务时能看到哪些信息、如何看到这些信息,以及哪些信息应该被过滤、压缩或保留。

Harness 工程是在学习如何把模型变成可靠的软件组件。它通过输入处理、上下文组装、执行控制、评估反馈和观测日志,让 AI 应用具备持续运行和持续迭代的能力。

AI 工程的重点正在从“会不会问模型”转向“能不能构建一个稳定的模型运行系统”。Prompt 仍然重要,但真正决定 AI 应用能走多远的,往往是 Prompt 之外的上下文管理和系统工程能力。