Context Engineering:系统化设计模型输入的工程方法论

本文是「Agent 基础与工程」系列专栏的第 13 篇。专栏总览参见:《Agent 基础认知与工程架构全景》。

在早期的大模型应用中,开发者习惯将大量精力投入在“如何写出一段完美的 Prompt”上。但在复杂、长周期的 Agent 系统中,静态提示词能解决的问题非常有限。同一个大模型,在面对同一道业务指令时,表现可能天差地别:

  • 输入 A:仅输入单条用户问题 帮我分析这几个微服务的性能瓶颈,模型往往给出宽泛泛化的教科书套话;
  • 输入 B:在上下文组装期注入当前集群环境元数据、最近 5 分钟的 CPU 异常采样指标、拓扑依赖图、历史成功排障经验,以及当前可用的只读工具 Schema,模型能一针见血地锁定故障根因。

这种差异不是基座模型参数的差异,而是上下文供给质量的差异。Context Engineering(上下文工程)是将大模型的单次推理输入作为动态信息供给链,系统化设计信息的过滤、装配、排序与生命周期流转的工程方法论。


概念升维:从 Prompt 到 Context

Prompt Engineering 与 Context Engineering 处于不同的架构抽象层级:

维度 Prompt Engineering(提示词工程) Context Engineering(上下文工程)
关注范畴 单次调用的自然语言文本(措辞、语气、Few-shot 样例) 支撑整个决策生命周期的动态数据流水线
数据属性 静态居多,通常在代码中硬编码或配置于模板中心 高度动态,根据当前运行期状态、外部环境与权限实时计算装配
信息来源 开发者编写的指令 静态规则 + 运行时元数据 + 状态机进度 + 向量检索切片 + 渐进式技能文档
核心挑战 词不达意、模型不听指令 注意力稀释(Attention Dilution)、Token 预算超限、信息信噪比失衡

静态 Prompt 只是 Context 装配流水线的一个初始片段。Context Engineering 负责调度全局信息流。


生产级上下文的五层黄金结构

为了使大语言模型在多步推理中始终维持高度清醒的决策状态,上下文应遵循清晰的分层布局:

1. 运行时状态栏(Status Line)的注入技巧

大模型不具备对真实物理世界时间的感知能力,也无法原生获知外部系统的资源开销。在 Layer 2 注入一段紧凑的环境元数据,能够极大降低模型的无序探索:

1
2
3
4
5
6
7
8
9
10
11
<runtime_environment>
<current_time>2026-02-26T14:30:00+08:00</current_time>
<os_platform>linux-x86_64</os_platform>
<workspace_root>/data/apps/order-service</workspace_root>
<git_branch>feature/payment-v2</git_branch>
<budget_meter>
<step_used>3</step_used>
<max_steps>10</max_steps>
<tokens_consumed>14200</tokens_consumed>
</budget_meter>
</runtime_environment>

当模型在每轮输入中明确感知到 step_used: 8 / 10 时,它会主动收敛发散的探索行为,倾向于尽快聚合已有信息交付结论。


渐进式披露:Skills 体系的按需挂载

传统设计中,开发者常将几十个业务工具的长篇说明与数百条规章制度全量写入 System Prompt,这会导致两项严重后果:

  1. Prompt Cache 频繁失效:体积庞大且经常变动的 System Prompt 破坏了 KV Cache 的命中率,显著抬高推理成本与 TTFT;
  2. 上下文污染(Context Pollution):大量与当前任务无关的规章切片冲淡了模型的注意力焦点。

工程解法:渐进式披露(Progressive Disclosure)。

系统在初始状态下仅暴露低成本的技能“目录索引”;只有当模型通过意图推断明确需要某一领域的专门能力时,才触发二级工具加载详细规范文档,实现工作集的按需最小化。


U 型注意力曲线治理(Attention Mitigation)

多项学术研究与工程实践均证实,现代 Transformer 模型在处理超长上下文时存在显著的“中间迷失(Lost in the Middle)”效应:模型对**头部(Prompt 起始位置)和尾部(最新输入位置)**的注意力权重极高,而位于上下文躯干中段的信息极易被忽略或检索遗漏。

针对这一特性的工程编排原则包括:

  • 硬性约束头部化:不可违背的安全铁律、禁止调用的高危命令必须牢牢锚定在 Layer 1 头部;
  • 核心目标与最新指令尾部置底:在发送给模型的 messages 最后一项,重新追加一句简明扼要的当前任务强调(例如:请根据上述数据,严格输出格式化 JSON 并退出),确保其处于注意力焦点的最强区域;
  • 中间躯干压缩化:位于中间的历史工具调用输出,超过 3 轮以上的必须做摘要折叠,防止废弃的中间日志占领核心注意区。

生产级 Context Assembler 实现

以下使用 Python 原生实现一个包含分层装配、状态栏元数据注入与长度预算控制的上下文编排器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import datetime
from typing import List, Dict, Any

class ContextAssembler:
def __init__(self, system_anchor: str, workspace_root: str, max_budget_tokens: int = 8000):
self.system_anchor = system_anchor
self.workspace_root = workspace_root
self.max_budget_tokens = max_budget_tokens

def _render_status_line(self, current_step: int, max_steps: int) -> str:
now_iso = datetime.datetime.now(datetime.timezone.utc).isoformat()
return (
f"<system_status>\n"
f" <timestamp>{now_iso}</timestamp>\n"
f" <workspace>{self.workspace_root}</workspace>\n"
f" <progress>Step {current_step}/{max_steps}</progress>\n"
f"</system_status>"
)

def assemble(
self,
current_step: int,
max_steps: int,
active_skills: List[str],
state_summary: str,
recent_history: List[Dict[str, Any]],
user_prompt: str
) -> List[Dict[str, Any]]:
# 1. 装配 Layer 1: 静态安全锚点
system_content = f"{self.system_anchor}\n\n"

# 2. 装配 Layer 2: 运行时状态栏
system_content += f"{self._render_status_line(current_step, max_steps)}\n\n"

# 3. 装配 Layer 3: 动态技能注入
if active_skills:
system_content += "<active_skills>\n" + "\n".join(active_skills) + "\n</active_skills>\n\n"

# 4. 装配 Layer 4: 结构化状态机事实
if state_summary:
system_content += f"<current_facts>\n{state_summary}\n</current_facts>"

messages: List[Dict[str, Any]] = [
{"role": "system", "content": system_content.strip()}
]

# 5. 装配 Layer 5: 清洗修剪后的工作轨迹
messages.extend(recent_history)

# 6. 尾部锚定:再次锁定最终行动诉求
tail_user_msg = (
f"{user_prompt}\n\n"
f"【决策要求】:请依据当前已确认事实,选择调用下一步工具或给出最终结论。"
)
messages.append({"role": "user", "content": tail_user_msg})

return messages

if __name__ == "__main__":
assembler = ContextAssembler(
system_anchor="你是一个遵循极简原则的工程架构助手。涉及写操作必须申请审批。",
workspace_root="/home/deploy/project-alpha"
)

assembled_context = assembler.assemble(
current_step=4,
max_steps=10,
active_skills=["<skill name='db-migration'>执行迁移前必须先检查当前连接数</skill>"],
state_summary="已完成数据库备份;当前阻塞:等待连接数排空。",
recent_history=[
{"role": "assistant", "content": "正在检查连接数..."},
{"role": "tool", "content": "active_connections: 2"}
],
user_prompt="继续推进数据库迁移。"
)

print("--- 动态上下文装配成品预览 ---")
print(assembled_context[0]["content"])
print("\n--- 尾部消息预览 ---")
print(assembled_context[-1]["content"])

系列导航与参考