一、为什么需要 Context Engineering?

以前我们写大模型应用时,经常会这样想:

我把用户问题、系统提示词、历史对话、检索结果、工具结果全部塞给大模型,大模型应该就能回答好了吧?

但实际情况并不是这样。

因为大模型的上下文窗口虽然越来越大,但它依然是有限资源。上下文越长,不代表效果越好,反而可能出现几个问题:

1. 信息太多,模型抓不住重点

比如用户只是问:

“帮我分析这个告警是什么原因?”

如果我们把所有历史对话、所有日志、所有知识库内容、所有工具返回结果都塞进去,模型可能会被无关信息干扰。

它不是不知道答案,而是在太多信息里迷路了。


2. Token 成本变高

上下文越长,消耗的 token 越多。

对于一个真实 Agent 系统来说,尤其是多轮对话、多工具调用、多 Agent 协作场景,如果每一步都带上全部上下文,成本会越来越高。


3. 容易引入错误信息

上下文中如果包含过期信息、无关检索结果、错误工具结果,模型可能会把这些内容当成依据,从而产生错误回答。

也就是说:

Agent 幻觉不一定只是模型本身的问题,也可能是上下文组织得不好。


二、什么是 Context Engineering?

我现在对 Context Engineering 的理解是:

Context Engineering 不是简单地写 Prompt,而是设计一套机制,决定 Agent 在每一步推理、调用工具、生成回答时,应该拿到哪些上下文信息。

LangChain 对 Agent 上下文工程的总结比较清晰:常见策略可以分为 Write、Select、Compress、Isolate 四类,也就是写入、选择、压缩和隔离。

换成更容易理解的话就是:

能力 作用
Write 把有价值的信息写入状态或记忆
Select 从大量信息中选择当前最相关的内容
Compress 把长历史、长日志、长文档压缩成摘要
Isolate 把不同任务、不同 Agent、不同会话的上下文隔离开

这四个词其实可以串起我们之前学过的大部分 Agent 技术。


三、Context Engineering 和 Prompt Engineering 的区别

很多人刚开始会把 Context Engineering 和 Prompt Engineering 混在一起。

但它们不是一个层级的东西。

Prompt Engineering 更像是“怎么说”

比如:

你是一个专业的智能运维助手。
请根据告警信息、日志内容和历史排障经验,分析可能原因,并给出解决建议。

这属于 Prompt。

它主要解决的是:

我要让模型以什么身份、什么格式、什么思路回答?


Context Engineering 更像是“给它看什么”

比如在一次 AIOps Agent 调用中,我们要决定:

1. 当前用户问题是什么?
2. 当前 session 的最近几轮对话是什么?
3. 是否需要加载历史摘要?
4. 是否需要检索 RAG 知识库?
5. 是否需要调用 Prometheus 查询告警?
6. 是否需要调用 CLS 查询日志?
7. 工具返回结果是否需要压缩?
8. 哪些信息应该交给 Planner?
9. 哪些信息应该交给 Executor?
10. 哪些信息应该从上下文中移除?

这就是 Context Engineering。

所以我觉得可以这样理解:

Prompt Engineering 是一句话怎么写。
Context Engineering 是整个 Agent 的信息流怎么设计。


四、一个完整 Agent 上下文里通常包含什么?

结合我目前学习的 Agent 项目,一个比较完整的上下文通常不是只有用户输入,而是由很多部分组成。

可以简单拆成下面几类:


1. System Prompt:系统身份和规则

这是最基础的一层。

比如:

你是一个智能运维 Agent。
你需要根据告警、日志、知识库和工具结果进行分析。
如果信息不足,需要说明缺少哪些信息。
不要编造不存在的日志和指标。

它决定 Agent 的角色、边界和输出规范。


2. User Input:用户当前问题

比如:

线上订单服务响应变慢,帮我分析一下原因。

这是 Agent 当前要解决的问题。

但只靠这个问题往往不够,因为它缺少环境信息,比如服务名、时间范围、错误日志、指标变化等。


3. Conversation History:短期对话历史

比如用户前面已经说过:

服务名是 order-service。
时间大概是晚上 8 点到 8 点半。
最近刚发布过一个新版本。

这些信息在后续分析中非常重要。

如果 Agent 不记得,就会反复追问用户。

这就是短期记忆的作用。


4. Long-term Memory:长期记忆

长期记忆更适合保存跨会话仍然有价值的信息。

比如:

用户的项目主要是基于 Spring Boot + Spring AI Alibaba。
用户当前关注 AIOps Agent、RAG、Memory、Tool Calling。
用户希望回答偏向实习面试和项目表达。

长期记忆不是每次都全部塞给模型,而是需要根据当前任务选择性召回。

这就涉及 Context Engineering 里的 Select


5. RAG Retrieved Context:知识库检索结果

比如从知识库中检索到:

order-service 响应变慢可能与数据库慢查询、Redis 缓存击穿、下游接口超时有关。

RAG 提供的是外部知识。

但 RAG 也不能无限塞,通常要控制 TopK,并且要过滤无关内容。


6. Tool Results:工具调用结果

比如 Agent 调用了 Prometheus:

CPU 使用率正常。
接口 P99 延迟从 80ms 上升到 1200ms。
数据库连接池等待时间明显升高。

又调用了日志查询工具:

大量出现 SQL timeout。

这些工具结果往往比模型自己的猜测更可靠。

Anthropic 在工具使用相关内容中也强调,工具定义和工具返回结果会直接影响 Agent 的实际表现,工具本身也需要像 Prompt 一样认真设计。


7. Agent State:当前任务状态

在多 Agent 或 LangGraph 这类编排框架里,通常会维护一个状态对象。

比如:

class AgentState {
    String userQuestion;
    List<String> plan;
    List<String> executedSteps;
    List<String> observations;
    String finalAnswer;
}

这个 State 不是单纯给用户看的,而是 Agent 工作流内部用来记录任务进度的。

比如:

  • Planner 生成了哪些步骤
  • Executor 已经执行了哪些工具
  • Replanner 判断是否需要重新规划
  • Supervisor 决定下一步交给谁

这就是上下文工程里的 “Write to State”。

LangChain 的文档里也提到,工具结果既可以直接返回给模型,也可以更新 Agent 的状态或记忆,使后续步骤可以继续使用这些上下文。


五、Context Engineering 的四个核心动作

下面用更接近项目实现的方式理解这四个动作。


1. Write:把有价值的信息写进去

Agent 在执行过程中会不断产生新信息。

比如:

用户补充了服务名。
工具返回了日志结果。
Planner 生成了执行计划。
Executor 执行了第一步。
Replanner 判断需要重新查询数据库。

这些信息不能丢。

所以需要写入:

  • 短期上下文
  • Agent State
  • 长期 Memory
  • 工具执行记录
  • 任务中间结果

但是这里有一个关键点:

不是所有信息都值得写入长期记忆。

比如:

用户今天问了一个临时问题
某一次工具调用失败
某一次测试日志

这些一般不适合长期保存。

真正适合写入长期记忆的是:

用户的长期偏好
项目固定技术栈
常见排障经验
稳定的业务规则
重复出现的问题处理方案

2. Select:从大量信息中选出当前需要的

这是 Context Engineering 里非常重要的一步。

因为上下文窗口有限,所以 Agent 每一步都应该选择最相关的信息。

比如用户问:

Memory0 是怎么存储数据的?

这时候最相关的上下文应该是:

Memory0
长期记忆
向量数据库
存储后端
RAG 区别

而不是把之前所有关于 Docker、Kafka、软件工程考试的内容都塞进去。

所以 Select 的本质是:

当前任务需要什么,就取什么。

在项目里可以对应这些实现:

根据 sessionId 取最近 N 轮对话
根据用户问题检索长期记忆
根据问题向量检索 RAG 文档
根据任务类型选择工具说明
根据 Agent 角色选择不同上下文

3. Compress:把长内容压缩成可用摘要

多轮对话很容易变长。

比如一个用户连续问了 50 轮,如果每轮都带上,token 会爆炸。

这时候就需要摘要压缩。

常见做法是:

最近 5 轮对话:原文保留
更早的历史:压缩成摘要
关键事实:写入长期记忆
无关内容:丢弃

OpenAI 的 Agents SDK Cookbook 中也提到,短期记忆管理可以使用 trimming 和 compression 等方式来保持 Agent 快速、可靠和更节省成本。

用在项目中,可以这样设计:

public String buildContext(String sessionId, String userInput) {
    String summary = memoryService.getHistorySummary(sessionId);
    List<Message> recentMessages = memoryService.getRecentMessages(sessionId, 5);
    List<Document> ragDocs = ragService.retrieve(userInput, 5);

    return """
        历史摘要:
        %s

        最近对话:
        %s

        检索资料:
        %s

        用户当前问题:
        %s
        """.formatted(summary, recentMessages, ragDocs, userInput);
}

这个逻辑其实就是上下文工程。


4. Isolate:隔离不同任务和不同 Agent 的上下文

这点在多 Agent 系统中特别重要。

比如一个 AIOps 系统里有:

SupervisorAgent
PlannerAgent
ExecutorAgent
ReplannerAgent
ReportAgent

它们不一定都需要看到同样的信息。

Planner 需要看到:

用户问题
可用工具列表
任务目标
历史摘要

Executor 需要看到:

当前执行步骤
工具参数
工具调用规范

Replanner 需要看到:

原计划
已执行步骤
执行结果
失败原因

ReportAgent 需要看到:

最终结论
证据链
处理建议
风险提示

如果所有 Agent 都看到全部上下文,就会混乱。

所以 Isolate 的核心就是:

不同角色,只看自己需要的信息。

这和我们之前学的多 Agent 协作是能接上的。

Supervisor 不是简单地把所有内容扔给每个 Agent,而是根据任务阶段分发不同上下文。


六、结合 AIOps Agent 项目理解

假设用户输入:

order-service 晚上 8 点之后响应很慢,帮我分析原因。

一个比较合理的上下文工程流程可能是:


第一步:解析用户问题

Agent 先从用户输入中抽取关键信息:

服务名:order-service
时间范围:晚上 8 点之后
问题类型:接口响应慢
目标:定位可能原因并给出建议

第二步:选择需要的工具

根据问题类型选择工具:

Prometheus:查询服务指标
CLS / 日志系统:查询错误日志
数据库工具:查询慢 SQL 或连接池状态
RAG:检索历史排障经验

第三步:构造 Planner 上下文

给 Planner 的上下文可以是:

用户问题
已知条件
可用工具
输出要求

Planner 不一定需要看到大量日志原文。


第四步:Executor 调用工具

Executor 根据计划调用工具。

比如:

查询 order-service 在 20:00-20:30 的 P99 延迟
查询同时间段错误日志
查询数据库连接池状态

第五步:压缩工具结果

工具返回的日志可能很多,不能全部塞给模型。

需要压缩成:

1. P99 延迟从 80ms 上升到 1200ms
2. CPU 和内存正常
3. 数据库连接池等待时间升高
4. 日志中大量 SQL timeout
5. 没有明显下游接口错误

第六步:Replanner 判断是否需要补充查询

如果当前证据还不够,Replanner 可以继续规划:

需要进一步查询慢 SQL 列表
需要确认是否有版本发布
需要查询数据库 QPS 和锁等待情况

第七步:生成最终回答

最终回答不能只给结论,还要给证据链:

初步判断 order-service 响应慢主要与数据库访问异常有关。

依据:
1. 接口 P99 延迟明显升高;
2. 应用 CPU、内存没有明显异常;
3. 数据库连接池等待时间升高;
4. 日志中出现大量 SQL timeout。

建议:
1. 优先排查慢 SQL;
2. 检查数据库连接池配置;
3. 回看 20:00 前后的版本发布记录;
4. 如有必要,临时扩容数据库连接池或回滚相关 SQL 改动。

这才是一个比较完整的 Agent 回答。


七、Context Engineering 和 RAG、Memory、Tool 的关系

我觉得可以用一句话概括:

RAG、Memory、Tool 都是在提供上下文;
Context Engineering 是决定这些上下文怎么被组织和使用。

具体来说:

模块 提供什么 Context Engineering 负责什么
Prompt 角色和规则 决定不同阶段用什么 Prompt
Memory 历史和偏好 决定哪些记忆要召回
RAG 外部知识 决定检索什么、取多少、怎么排序
Tool 实时数据 决定何时调用、结果如何压缩
State 中间过程 决定任务进度如何保存
Multi-Agent 分工协作 决定不同 Agent 看哪些上下文

所以它不是一个单独的新技术,而是一种架构能力。


八、面试中怎么表达这个点?

如果面试官问:

你这个 Agent 项目里是怎么管理上下文的?

可以这样回答:

我不是简单把所有历史对话和工具结果都拼到 Prompt 里,而是做了分层上下文管理。

首先通过 sessionId 做会话隔离,避免不同用户或不同任务之间的上下文串扰。

其次,对于短期对话,我保留最近几轮原始消息;对于更早的历史,会压缩成摘要,避免 token 过长。

然后在需要外部知识时,通过 RAG 检索相关文档片段,而不是把整个知识库塞给模型。

对于工具调用结果,比如日志、指标、数据库查询结果,我会先结构化和摘要化,再交给模型做分析。

如果是多 Agent 流程,不同 Agent 看到的上下文也不一样。Planner 更关注任务目标和工具列表,Executor 更关注当前步骤和工具参数,Replanner 更关注执行结果和失败原因。

这样做的目的主要是降低 token 成本,减少无关信息干扰,同时提升 Agent 执行复杂任务时的稳定性。

这段话就比单纯说“我用了 Memory 和 RAG”更高级。

因为它体现的是工程设计能力。


九、今天的理解总结

今天学习完 Context Engineering 后,我感觉 Agent 的核心已经不只是“会不会调用工具”,而是:

能不能在正确的时间,把正确的信息,交给正确的 Agent 或模型。

以前我对上下文的理解比较简单,觉得上下文就是用户输入加历史对话。

现在发现,一个真正的 Agent 系统里,上下文其实包括:

系统提示词
用户当前问题
短期对话历史
长期记忆
RAG 检索结果
工具返回结果
Agent State
执行计划
中间观察结果
错误信息
最终输出约束

而 Context Engineering 要做的,就是对这些信息进行:

写入
选择
压缩
隔离

这也是为什么很多 Agent Demo 看起来能跑,但一到复杂任务、多轮任务、真实项目里就不稳定。

因为 Demo 只解决了“能回答”的问题。

而 Context Engineering 解决的是:

Agent 如何持续、稳定、低成本地完成任务。


十、下一步可以继续学习什么?

后面可以继续往这个方向展开:

1. Agent State 是怎么设计的?
2. LangGraph / Spring AI 中的状态流转怎么理解?
3. 多 Agent 之间如何传递上下文?
4. Tool Result 应该怎么结构化?
5. Memory 和 RAG 如何避免互相污染?
6. 如何设计一个适合面试表达的 AIOps Agent 上下文架构?

如果把这些内容串起来,就能从“会用大模型 API”逐渐过渡到“能设计 Agent 系统”。

这也是我现在学习 Agent 的一个重要转折点:

不只是学单个技术点,而是开始理解 Agent 背后的工程组织方式。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐