Context Engineering:比 Prompt Engineering 更重要的上下文工程
一、Prompt 只是入口,上下文才是现场 很多人做 AI 应用,第一反应是改 Prompt。 但线上 Agent 出错,往往不是 Prompt 写得不够玄,而是模型看到的上下文不对。 一句话讲透 Context Engineering,就
一、Prompt 只是入口,上下文才是现场
很多人做 AI 应用,第一反应是改 Prompt。
但线上 Agent 出错,往往不是 Prompt 写得不够玄,而是模型看到的上下文不对。
一句话讲透 Context Engineering,就是把正确的信息、正确的工具、正确的记忆、正确的规则,在正确的时间,放进模型的上下文窗口。 |
Prompt Engineering 解决“怎么说”。
Context Engineering 解决“给模型看什么”。
模型不会看见你的数据库。不会看见你的用户画像。不会自动知道权限。不会自动理解刚刚哪个工具失败了。
这些东西,都要被工程系统组织成上下文。
二、为什么它比 Prompt 更重要?
Prompt 再好,也只是上下文的一部分。
真实应用里,模型看到的是一整包东西:
系统指令
用户问题
历史消息
RAG 检索结果
工具返回结果
短期状态
长期记忆
权限配置
输出格式
这包东西只要乱,模型就会乱。
关键判断 如果回答错了,先不要怪模型。先问:这次模型到底看到了什么? |
三、上下文工程管的不是一件事,而是三类上下文
LangChain 官方把 Agent 上下文分成三个层次。
第一层:Model Context。模型调用时临时看到的东西。
第二层:Tool Context。工具执行时可以读取和写入的东西。
第三层:Life-cycle Context。模型和工具之间发生的治理动作。
这三个层次,决定了 Agent 是不是能上线。
三类上下文:模型看到什么,工具能读写什么,生命周期如何治理。
四、上下文从哪里来?三个数据源
上下文不是凭空出现的。
在 LangChain 里,常见来源是三个:
Runtime Context:本次运行配置,比如 user_id、role、env、api_key。
State:当前线程状态,比如 messages、认证状态、上传文件、工具结果。
Store:长期记忆,比如用户偏好、历史洞察、跨会话资料。
这三个来源组合起来,才是完整的上下文工程。
Runtime Context、State、Store 分别解决不同生命周期的数据问题。
五、上下文最终都会落到这条链路上
从源码看,上下文工程不是一个抽象概念。
它最后会落到 AgentState、ModelRequest、Middleware、ToolRuntime、Store 这些对象上。
把源码链路压缩后,就是下面这条线。
上下文工程的核心源码链路。
六、ModelRequest 是一次模型调用的上下文快照
ModelRequest 很关键。
它不是普通参数对象。
它是一次模型调用前的“上下文快照”。
里面装着:模型、消息、系统指令、工具、输出格式、状态、运行时上下文。
ModelRequest 的精简源码结构。
源码里最值得注意的是 override。
它不是直接修改原请求,而是返回一个新请求。
这意味着:中间件可以临时换模型、换工具、换消息、换输出格式,而不污染原始状态。
源码理解 ModelRequest.override(...) 是上下文工程最常见的动刀口。它让“本次模型调用看到什么”变得可控。 |
七、AgentState 是短期上下文的仓库
AgentState 里最核心的字段是 messages。
它不是普通 list。它带有 add_messages reducer。
这意味着:每次模型返回、工具返回,都会被追加进状态。
精简源码 class AgentState(TypedDict): |
所以,聊天历史为什么能一轮轮延续?
答案就在这里:messages 被状态图持续合并。
但这也带来问题:messages 会越来越长。
所以后面必须有裁剪、摘要、过滤。
八、Middleware 是上下文手术刀
Middleware 让你在 Agent Loop 的关键点动手。
常见钩子有四类:
before_model:模型调用前,适合裁剪消息、注入规则、提前结束。
wrap_model_call:包住模型调用,适合换模型、换工具、换 response_format。
after_model:模型返回后,适合校验输出、拦截敏感内容、决定跳转。
wrap_tool_call:包住工具调用,适合鉴权、重试、脱敏、审计。
Middleware 插在 Agent Loop 内部,控制上下文流动。
工程价值 Middleware 的本质,是把“拼上下文”从散乱业务代码里抽出来,变成可复用、可测试、可审计的工程层。 |
九、动态上下文:不是所有用户都该看到同一套 Prompt 和工具
同一个 Agent,不同用户看到的上下文应该不同。
管理员、普通用户、游客,权限不同。
新用户、老用户、高风险用户,策略不同。
短对话、长对话、复杂任务,模型也可以不同。
这就是动态上下文。
典型做法 用 runtime.context 读取用户角色;用 state 读取会话状态;用 store 读取长期偏好;再通过 ModelRequest.override(...) 改 system_message、tools、model、response_format。 |
工具也一样。
不要把所有工具一次性暴露给模型。
工具越多,模型越容易选错。
正确做法是:按权限、意图、阶段动态筛工具。
十、上下文太长:不是扩上下文窗口,而是管上下文质量
长上下文不等于好上下文。
长上下文会带来四个问题:
成本上升:token 越多,越贵。
延迟上升:输入越长,越慢。
注意力分散:无关信息越多,模型越容易跑偏。
冲突增加:旧信息、新信息、工具信息互相打架。
解决思路不是无限塞,而是选、裁、压、隔离。
上下文压缩的四种常见手段。
十一、SummarizationMiddleware 做的是持久压缩
临时裁剪,只影响这一次模型调用。
摘要中间件不一样。
它会把旧消息压成摘要,并写回 State。
以后每一轮都会看到摘要,而不是原始长历史。
精简源码链路 SummarizationMiddleware |
这就是生命周期上下文。
它不是临时改 ModelRequest。
它会真正改变未来会话的状态。
十二、企业级做法:做一个 Context Builder
生产系统不要到处拼 Prompt。
更好的做法是加一层 Context Builder。
它负责统一收集、筛选、压缩、注入上下文。
这一层应该输出一份干净的 ModelRequest。
里面包括:
任务上下文:当前用户到底要做什么。
身份上下文:用户是谁、权限是什么。
记忆上下文:用户偏好、历史偏好。
知识上下文:RAG 检索到的资料。
工具上下文:工具结果、错误状态。
安全上下文:合规规则、敏感词、风险控制。
输出上下文:结构化输出 Schema。
十三、上下文工程常见坑
上下文工程做不好,Agent 就会看起来“不聪明”。
本质上,是你给它的现场太乱。
十四、总结
最终结论 Prompt 只是上下文的一部分。真正决定 Agent 质量的,是你能否控制模型每一步看到的全部信息。 |
要点速读
一、Prompt 只是入口,上下文才是现场 很多人做 AI 应用,第一反应是改 Prompt。 但线上 Agent 出错
- 一、Prompt 只是入口,上下文才是现场 很多人做 AI 应用,第一反应是改 Prompt
- 但线上 Agent 出错
- 更多细节仍在持续更新中