跳转至

Agent 的 Context Engineering 应该怎么做?

  • ID:Q005
  • 难度:进阶 / 系统设计
  • 标签:Context Window、压缩、检索、状态、长任务、Coding Agent

同义问法

  • Agent 上下文太长怎么解决?
  • 长对话如何动态压缩和遗忘?
  • 为什么上下文窗口很大,Agent 仍会丢失信息?
  • Coding Agent 如何理解大型代码仓库?
  • Memory 能不能解决 Prompt 过长?

来源

真实面试来源

  1. 阿里 AI Agent 应用开发二面:长对话中如何实现上下文的动态压缩和遗忘?
  2. 查看原文
  3. 美团大模型工程一面:记忆能解决 Prompt 过长吗?
  4. 查看原文
  5. 阿里淘天 Agent 面经:是否尝试过 Prompt 压缩?
  6. 查看原文

面试官真正考察什么

不是看你会不会说“摘要、向量库、滑动窗口”,而是看你是否理解:

Context Engineering 的目标不是塞进更多内容,而是在当前决策点提供最少但足够、可信且结构清晰的信息。

它涉及信息选择、状态建模、证据保真、成本和错误恢复,是 Agent 工程的核心问题。

可视化图解

flowchart LR
  S[完整 Runtime State] --> F[相关性过滤]
  M[长期 Memory] --> F
  K[检索知识与工具结果] --> F
  F --> B[Token Budget 分配]
  B --> C[压缩与摘要]
  C --> A[Context Assembly]
  A --> L[LLM]
  L --> T[决策或工具调用]
  T --> S

先建立直觉

上下文窗口像工作台,不是仓库。

把所有聊天、日志、代码、工具输出都堆上工作台,会出现:

  • 关键指令被淹没;
  • 旧信息和新信息冲突;
  • 模型重复分析;
  • Token 成本和延迟上涨;
  • 截断时随机丢失重要内容。

正确方式是:原始数据放在外部存储,工作台只保留当前步骤真正需要的内容。

Context 不等于聊天记录

生产级 Agent 的上下文通常至少分为:

  1. 目标与约束:用户要什么、不能做什么。
  2. 当前状态:任务处于哪个阶段,哪些步骤完成。
  3. 工作记忆:当前推理需要的少量事实和假设。
  4. 工具目录:当前阶段可使用的相关工具。
  5. 检索证据:按需取回的代码、文档、日志和历史经验。
  6. 最近交互:保持局部连续性的消息。
  7. 产物引用:文件、日志、Diff、测试结果的地址和摘要。

关键是把“状态”从自然语言历史中抽出来,结构化保存。

为什么大窗口不能自动解决问题

更大的 Context Window 主要提高容量,但不能保证:

  • 模型能正确注意到中间的重要信息;
  • 冲突信息自动消解;
  • 工具结果可信;
  • 历史噪声不会影响决策;
  • 成本和延迟可接受;
  • 长任务中目标不会漂移。

容量问题只是 Context Engineering 的一部分,选择和组织通常更重要。

推荐的分层架构

对应流程使用 Mermaid 图解展示。

原始层

必须保留可追溯的完整数据,避免摘要丢失后无法恢复。

状态层

结构化保存:

{
  "goal": "定位发布失败根因",
  "constraints": ["只读", "不得重启生产服务"],
  "stage": "dependency_analysis",
  "completed_steps": ["fetch_build_log"],
  "hypotheses": [
    {"name": "依赖仓库不可用", "confidence": 0.7}
  ],
  "open_questions": ["其他项目是否同时失败"]
}

摘要层

摘要不是简单缩写聊天,而应保留:

  • 已确认事实;
  • 尚未确认的假设;
  • 决策及原因;
  • 用户明确约束;
  • 关键产物引用;
  • 未完成事项。

检索层

根据当前任务检索,而不是把所有历史做一次向量相似度查询。

可以结合:

  • 关键词检索;
  • 语义检索;
  • 文件路径和代码符号;
  • 时间范围;
  • 任务阶段;
  • 最近修改;
  • 权限和数据来源。

压缩策略

1. 滑动窗口

保留最近消息,适合局部对话连续性。

缺点:可能丢失早期目标和约束,所以必须将关键内容提升到状态层。

2. 阶段摘要

每完成一个阶段生成摘要,再进入下一阶段。

比每轮都重新总结更稳定,也便于中断恢复。

3. 事件压缩

把多条低价值事件合并,例如连续 20 次日志分页读取,最终只保留关键错误、时间范围和原始引用。

4. 语义去重

不同工具可能返回重复信息,应按实体、时间和事实去重。

5. 按需展开

上下文先放摘要和引用,模型确实需要细节时再读取原文。

这类似操作系统的分页,而不是一次把全部数据装进内存。

“遗忘”应该怎么做

遗忘不是删除一切旧内容,而是降低不再相关信息进入当前上下文的优先级。

不能遗忘:

  • 用户目标和硬约束;
  • 已执行的有副作用动作;
  • 关键证据和结论来源;
  • 安全和权限信息;
  • 未完成承诺。

可以衰减:

  • 已失效的中间猜测;
  • 重复工具输出;
  • 已解决阶段的细节;
  • 与当前任务无关的闲聊。

Coding Agent 的特殊处理

大型代码库不能靠把仓库全部塞进 Prompt。

更合理的路径是:

  1. 解析仓库结构和构建入口;
  2. 通过文件名、符号、调用关系、搜索结果定位候选范围;
  3. 读取相关文件和必要邻接代码;
  4. 修改后通过 Diff、编译和测试反馈继续迭代;
  5. 将生成产物保存在工作区,Context 中只保留摘要和引用。

代码检索也不能只用 Embedding:精确符号、路径、grep、语言服务器和依赖图通常更可靠。

摘要的风险

摘要会产生信息损失甚至错误归纳。

防护方法:

  • 摘要中的事实附原始引用;
  • 区分 confirmed fact 与 hypothesis;
  • 关键数字、错误码、文件路径尽量原样保留;
  • 重要决策可由规则校验;
  • 允许从原始层重新构建摘要;
  • 不让摘要覆盖原始记录。

Context 污染与 Prompt Injection

外部网页、日志、代码注释都可能包含类似指令的文本。

系统应明确:

  • System / Developer 指令;
  • 用户目标;
  • 外部不可信数据;
  • 工具结果。

外部内容只能作为数据,不应自动改变权限和系统规则。

如何评估 Context Engineering

不能只看 Token 是否减少。至少关注:

  • 任务成功率;
  • 关键约束保留率;
  • 证据召回率;
  • 摘要事实错误率;
  • 平均输入 Token;
  • P95 延迟;
  • 重复工具调用率;
  • 长任务目标漂移率;
  • 中断恢复成功率。

压缩 80% Token 但成功率下降,不能算优化。

常见低质量回答

回答 1

超长后做摘要。

问题:没有说明摘要什么、保留什么、如何追溯和何时触发。

回答 2

使用向量数据库做长期记忆。

问题:向量库是检索工具,不等于状态管理,也无法保证召回关键约束。

回答 3

换一个更大上下文的模型。

问题:只缓解容量,不解决噪声、冲突、成本和目标漂移。

可直接口述的回答

Context Engineering 的目标不是尽量把信息塞满,而是让模型在当前决策点看到最少但足够、可信且结构清晰的信息。我通常把完整对话、日志和代码保存在外部原始层,把目标、约束、计划、进度和假设抽成结构化状态;阶段完成后生成带引用的摘要;本轮根据任务阶段按需检索原文。最近消息用滑动窗口维持局部连续性,但关键目标和约束不能依赖窗口保留。对于 Coding Agent,还要结合文件路径、符号搜索、调用关系和测试反馈,而不是只靠向量检索。评估时不仅看 Token,还要看任务成功率、约束保留、证据召回、摘要错误和目标漂移。

结合个人项目怎么回答

我们在 CI/CD Agent 中遇到过把流程说明、源码和大量日志一次性塞给模型,最终 Prompt 超长且模型反复关注次要错误。更合理的做法是先用脚本提取时间线、异常链和关键错误,把完整日志放在文件中;Agent 根据假设按需读取前后文。任务状态单独记录已确认事实和待验证项,阶段结束后压缩上下文,但保留原始日志引用。这样上下文变小的同时,证据链仍可追溯。

可能追问

什么时候触发压缩?

可以结合 Token 水位、阶段边界、工具结果体积和任务停滞触发,不建议仅按固定轮次。

Memory 和 Context 有什么区别?

Memory 是跨轮或跨任务保存的信息;Context 是本轮实际提供给模型的信息。Memory 必须经过选择才能进入 Context。

如何处理新信息与旧记忆冲突?

记录来源、时间和可信度,优先使用更新且权威的数据;不要静默覆盖,必要时把冲突暴露给模型或用户。