人工智能
生产级 AI 智能体的四层上下文工程:Deep Insight 如何在可运行代码中应用它们当生产级 AI 智能体处理数据分析和报告生成等任务时,上下文管理可能成为主要瓶颈。200K token 的窗口听起来很宽裕,直到一个真实任务在几分钟内就消耗掉其中大部分。数据分析和报告生成会让智能体在执行中途失败、丢失准确性或推高成本。已有大量已发布的指导文献涉及这一问题,但各项技术读起来容易,应用起来却难。将它们结合起来应用,能带来可衡量的差异:在本文所详述的参考实现中,单个写入并执行工具将每个脚本添加到上下文中的 token 减少了约 95%,而按需加载技能使系统提示词缩小了约 97%。
本系列将这些指导整理成可直接应用的实践。Anthropic 的工程博客文章,加上 Strands Agents SDK 内置的功能,共同归结为四层上下文工程:在架构层面隔离上下文、通过提示词控制上下文、将上下文外置到文件系统,以及用独立智能体和防护措施进行验证。在本文(第 2 部分)中,你将了解每一层如何运作,以及在可运行代码中是什么样子。我们在 Deep Insight中应用了这些技术,这是一个基于 Strands Agents SDK 和 Amazon Bedrock AgentCore 构建的开源多智能体数据分析解决方案,全文将其作为参考实现。
文章系列
- 第 1 部分:多智能体系统中的 5 个生产挑战以及 Deep Insight 如何解决它们。
- 第 2 部分:生产级 AI 智能体的四层上下文工程:Deep Insight 如何在可运行代码中应用它们。
- 第 3 部分:实践中的驾驭工程:将 Deep Insight 从开发推向生产。(即将推出!)
第一篇文章定义了生产级多智能体系统必须解决的五个核心挑战。它介绍了 Strands Agents SDK, Amazon Bedrock 和 Bedrock AgentCore, 以及 AWS Fargate 如何各自解决不同层面的问题,并附有代码示例。这第二篇文章承接位于该架构之上的四层上下文工程实践,并展示每一层的实现。第三篇文章将指导你在 Amazon Virtual Private Cloud(Amazon VPC)上的安全私有网络中部署和运行智能体,涵盖真实运营所需的一切。
什么是上下文工程?
上下文工程是一门优化大型语言模型(LLM)有限上下文窗口中信息的学科,目的是让智能体发挥最佳表现。可在 Amazon Bedrock 上使用的 Anthropic Claude Sonnet 4.5 提供 200K 上下文窗口,但复杂的生产任务会很快超出它。例如,一个看似简单的请求,如“分析销售数据并创建 DOCX 报告”,会经历多个阶段:数据加载与探索(5 分钟)、基于类别的销售分析(3 分钟)、生成五张图表用于时间序列分析(10 分钟)、统计验证(3 分钟)以及最终报告生成(5 分钟)。这些阶段在 15 分钟内合计消耗超过 150K token。
在单一上下文中处理此类任务会引发问题:窗口在任务中途溢出、过时的上下文降低性能,而且出错时需要重新运行整个流水线。随着上下文增长,对重要信息的注意力会下降,而低效会在按 token 计费的模式下推高成本。
“随着上下文窗口中 token 数量的增加,模型从该上下文中准确回忆信息的能力会下降(上下文腐化)。”
—— Anthropic,“面向 AI 智能体的有效上下文工程” (2025.09)
上下文工程正是为了解决这些问题,而它并不只是一组技术的集合。它横跨架构设计、提示词编写、工具实现和验证,是一门分层学科,每一层都弥补前几层的不足。本文详细介绍了可用于高效管理上下文的四层方法。
如何处理超出上下文窗口的任务
Anthropic 已发表了多项处理长周期任务的技术。Deep Insight 将这些技术归为四层,每一层都针对其他层的局限性。下表列出了这四层。
| 层级 | 实践 | 核心原则 | 局限性 |
| 第 1 层:架构 | 通过多智能体架构隔离上下文 | 每个智能体在独立的上下文中运行 | 当仅靠隔离不够时 |
| 第 2 层:提示词 | 输出控制与行为规则 | 通过提示词限制上下文输入 | 当仅靠提示词不够时 |
| 第 3 层:工具 | 基于文件的上下文外置 | 将重内容保留在上下文之外的文件中 | 当问题仍然出现时 |
| 第 4 层:验证智能体与防护措施 | 独立验证与防护措施 | 捕获错误并防止上下文溢出 | 最后一道防线 |
接下来的各节将依次介绍每一层,说明该层规定了什么、为什么仅靠前面的层还不够,以及该实践在 Deep Insight 中是如何实现的。
1. 通过多智能体架构隔离上下文
为每个专用智能体提供自己的上下文窗口,并且只将压缩后的结果传递给编排器。Deep Insight 通过 Coordinator、Planner、Plan Reviewer、Supervisor 和 Tool Agents(Coder、Validator、Reporter、Tracker、Auditor)的层级结构来实现这一点。
在单一智能体的情况下,从用户请求到数据探索、分析、图表生成、验证和报告的所有信息都会累积在一个上下文中,很容易超出窗口。为每个智能体提供自己的上下文,可以让使用量最大的 Coder 也保持在总计 25K token 以下。每个智能体只接收自己需要的内容,并通过完成通知和简短摘要向其他智能体发出信号。
隔离的关键在于最小化共享信息。Deep Insight 使用一个 Python 字典 shared_state,它只存储四项内容:
messages: 上一个智能体的最终消息(而非完整对话历史)。clues:从每个智能体收集的压缩摘要。full_plan:由 Planner 生成、由 Tracker 更新的检查清单。history:智能体名称和消息的简要日志。
线索使用固定的 CLUES_FORMAT:不传递每个智能体的完整对话(数万个 token),只传递压缩后的核心结果。
# coder_agent_tool.py -- context passing format
CLUES_FORMAT = "Here is clues from {}:\n\n<clues>\n{}\n</clues>\n\n"
RESPONSE_FORMAT = "Response from {}:\n\n<response>\n{}\n</response>\n\n*Please execute the next step.*"
# After Coder completes: add only compressed result to clues
clues += CLUES_FORMAT.format("coder", response["text"])
这一模式正是 Anthropic 的“我们如何构建多智能体研究系统”一文中推荐的做法,该文描述了编排器—工作者模式:由主智能体向专用子智能体分派任务,每个智能体只在自己的上下文中工作。你无需自行构建它:Strands Agents SDK 中的 agents-as-tools 模式在框架层面提供了这种隔离。
2. 通过提示词控制上下文流入
仅靠第 1 层隔离还不够:即使上下文相互独立,生成冗长响应的智能体也会撑大 Supervisor 的上下文。第 2 层通过提示词限制每个智能体的输出。
对于 Deep Insight,我们使用提示词限制每个智能体返回给 Supervisor 的信息量。正如 Deep Insight 的提示词所示,三条规则承担了大部分工作。
“从最强的模型和简单的提示词开始。然后根据实际观察到的失败案例,逐步添加具体指令。”
—— Anthropic,《Effective Context Engineering for AI Agents》(2025.09)
实现细节 2-1:为每个智能体明确设定输出 token 预算
每个智能体的提示词都规定了最大响应 token 数,防止冗长响应污染 Supervisor 的上下文。
| 智能体 | 输出 token 预算 | 原因 |
| Coder | 1,000–1,500 token | 分析代码保存到文件,因此该智能体只返回状态、已完成任务和洞察的摘要 |
| Validator | 800 token | 验证结果保存到 citations.json。该智能体只返回摘要 |
| Reporter | 1,000 token | 该智能体将报告生成为 DOCX 文件,只返回结果摘要 |
Anthropic 的“ Writing Effective Tools for Agents”一文建议为工具提供 CONCISE 或 DETAILED 响应选项,以提高上下文效率。将同样的思路向上应用一层,即写入每个智能体的系统提示词。在 Deep Insight 中,所有智能体共享一种标准化格式:
## Status
[SUCCESS | PARTIAL_SUCCESS | ERROR]
## Completed Tasks
- [Task 1 from FULL_PLAN -- use exact wording so Tracker can match]
- [Task 2 -- be specific, not generic]
## Key Insights
- [Key finding 1 with numbers and ratios]
- [Key finding 2 with business implications]
## Generated Files
- ./artifacts/chart.png -- brief description
- ./artifacts/calculation_metadata.json -- N calculations
实现细节 2-2:自包含代码理念
Coder 智能体的提示词明确写道“变量不会在脚本之间保留”。每个脚本都必须包含所有必要的导入并直接加载数据。提示词同时给出了错误和正确的示例:
# WRONG -- Attempting to use a variable from Turn 1 in Turn 2
# Turn 1:
df = pd.read_csv('data.csv')
total = df['Amount'].sum()
# Turn 2:
print(f"Total: {total}") # NameError: name 'total' is not defined
# CORRECT -- Every script is self-contained
import pandas as pd
df = pd.read_csv('./artifacts/cache/df_main.csv') # Load from cache
total = df['Amount'].sum()
print(f"Total: {total}")
这条规则与上下文工程相关的原因在于:引用先前脚本中的变量要求智能体“记住”之前的对话,这意味着过去的代码必须保留在上下文中。自包含原则意味着过去的代码可以安全地从上下文中移除。
实现细节 2-3:Supervisor 的分节完成规则
Supervisor 的提示词包含这样一条规则:“在当前智能体分节中的所有检查清单项都被标记为 [x]之前,不要转向下一个智能体。”我们在提示词中表达这条规则,是因为判断 Coder 的工作是否完成,需要 Supervisor 利用 Tracker 更新中的信息来解读计划。这种判断很难仅用代码表达。
3. “上下文中只放指针,实际数据放在文件中”
第 1 层隔离了智能体之间的上下文,第 2 层限制了智能体内部的输出。但当 Coder 智能体生成 100 行 Python 代码时,代码本身会进入上下文。即使有“简短回复”的提示词指令,有些代码也无法写得简短。第 3 层通过工具设计将重内容移出上下文,放入文件系统。如下面的实现细节所示,四项技术带来了大部分收益。
实现细节 3-1:用 Write and Execute Tool 将代码移出上下文
Coder 读取分析计划,编写 Python 并执行以生成可视化。但当代码变长时,常规做法(分开的文件写入工具和执行工具)会让每个脚本直接向上下文添加 100 行,累积超过 1,000 行。
解决办法是将两个步骤合并为一个工具,这样代码永远不会作为消息进入上下文。Deep Insight 的 Coder 智能体为此使用了一个 write_and_execute_tool 。
以下是 write_and_execute_tool 的一部分。写入并执行文件后,它只返回摘要:“写入了 105 行,执行成功,完成了五个类别的分析。”代码留在文件中,上下文中只保留约三行摘要。根据这个例子,这节省了约 95% 的 token。
# write_and_execute_tool.py
def _handle_write_and_execute_tool(file_path, content, timeout=300):
"""Write a Python script and immediately execute it."""
# Step 1: Write file
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
# Step 2: Execute immediately
result = subprocess.run(
f"python {file_path}",
shell=True,
capture_output=True,
timeout=timeout
)
# Return only summary
return f"Written {len(content.split(chr(10)))} lines to {file_path}\n" \
f"Execution successful\n" \
f"Output: {result.stdout[:500]}" # Only first 500 chars
“服务端过滤:在执行层过滤数据,使其在进入上下文之前被处理,token 减少 98.7%(从 150K 降至 2K)。”
—— Anthropic,“Code Execution with MCP” (2025.11)
实现细节 3-2:在 Coder 智能体中将通用逻辑复用为模块
通用模块会在多次分析中重复使用。与其每次重新生成,不如将常用函数定义为一个模块并导入,从而避免 token 浪费和上下文重复。
否则,在每次分析中定义 to_python_type() 或 track_calculation() 之类的函数,会在 10 次分析中产生 200–300 行重复代码。Deep Insight 在第一个任务之前生成一个名为 coder_analysis_utils.py 的模块。它包含转换 numpy 类型、跟踪计算元数据和保存为 JSON 的函数。后续分析导入它,用两行 import 替代 20–30 行重新生成的代码,既节省 token,又提高一致性和可调试性。
# coder_analysis_utils.py -- common module generated before first task
import numpy as np
import json
from datetime import datetime
_calculations = []
def to_python_type(value):
"""Convert numpy/pandas types to Python native types"""
if isinstance(value, (np.integer, np.int64)): return int(value)
elif isinstance(value, (np.floating, np.float64)): return float(value)
elif isinstance(value, np.ndarray): return value.tolist()
return value
def track_calculation(calc_id, value, description, formula,
source_file, source_columns, importance):
"""Track calculation metadata -- Validator independently verifies later"""
_calculations.append({
"id": calc_id, "value": to_python_type(value),
"description": description, "formula": formula,
"source_file": source_file, "source_columns": source_columns,
"importance": importance
})
def save_calculation_metadata(path="./artifacts/calculation_metadata.json"):
"""Save all tracked calculations to JSON"""
with open(path, 'w', encoding='utf-8') as f:
json.dump({"generated_at": datetime.now().isoformat(),
"calculations": _calculations}, f, ensure_ascii=False, indent=2)
实现细节 3-3:通过结构化笔记保存和共享分析结果
我们使用结构化笔记来共享详细分析结果,而无需让它们经过每个智能体的上下文。Deep Insight 将这些结果存储在一个名为 all_results.txt, 的文件中,然后由智能体按需读取。
例如,Coder 智能体在每次分析任务后将结果追加到 all_results.txt :
with open('./artifacts/all_results.txt', 'a', encoding='utf-8') as f:
f.write(f"""
## Category Sales Analysis (completed at: 14:32)
- Top revenue category: Fruit (417,166,008 KRW, 45% of total)
- Top 3 categories: Fruit, Vegetables, Meat (78% of total)
- Generated file: ./artifacts/category_sales_chart.png
""")
Coder 在每次分析后将详细结果记录在该文件中,Reporter 在撰写最终报告时读取它。其他智能体也以同样方式通过 all_results.txt 协作。
如果不做笔记,Coder 在每次任务完成后都会把详细结果传给 Supervisor,这些结果会在其上下文中不断累积。而做笔记时,只会传递一条约 30 个 token 的消息,例如“类别销售分析完成,发现 3 个关键洞察,详细结果已保存到 all_results.txt”,Reporter 在需要时再读取该文件。
这种模式可以推广到单个文件之外。文件系统本身就可以充当智能体之间的通信总线,正如 Deep Insight 中所做的那样:
| 文件名 | 生产者 | 消费者 | 角色 |
| CoderReporter分析结果的累积日志CoderValidator数值计算记录:来源、公式和值(用于验证)ValidatorReporter已验证的引用数据(在报告中以 [1]、[2] 形式插入)AuditorReporter最终报告中发现的引用缺陷(驱动 Reporter 进行针对性重试)Coder所有脚本共享的实用函数(一次编写,反复导入)full_plan(shared_state)Planner/TrackerSupervisor检查清单状态(更新 [x])“按需加载”方法,动态地 | Coder | 记者 | 分析结果的累积日志 |
calculation_metadata.json |
Coder | 验证器 | 数值计算记录:来源、公式和值(用于验证) |
citations.json |
验证器 | 记者 | 已验证的引用数据(在报告中以 [1]、[2] 形式插入) |
audit_findings.json |
审核者 | 记者 | 最终报告中发现的引用缺陷(驱动 Reporter 进行针对性重试) |
coder_analysis_utils.py |
Coder | 所有脚本 | 共享的实用函数(一次编写,反复导入) |
| full_plan(shared_state) | 规划器/跟踪器 | 主管 | 检查清单状态(更新 [x]) |
“按需加载”方法,即在运行时将数据动态加载到上下文中,而不是预先处理所有相关数据,能让上下文保持新鲜、相关,并适应任务不断变化的状态。
—— Anthropic,《为 AI 智能体打造高效的上下文工程” (2025.09)
实现细节 3-4:借助 Skills 仅加载所需知识
这种方法不是把所有专业知识都塞进系统提示词,而是只在需要时才加载。如果把每份技能指南(数据结构检查、README 生成、技能创建、系统提示词编写、工具创建)都包含进去,就会增加超过 20K 个 token,在每次调用时都把不必要的信息加载进 Coder 智能体,并且每新增一个技能都得重新部署。
Deep Insight 的 Skills 系统在启动时仅加载约 500 个 token 的技能目录,技能列表中只包含名称和简要描述。当用户请求“创建 README 文件”时,智能体判断“我需要 readme-generator 技能”,并调用 skill_tool(skill_name="readme-generator")。SkillLoader 读取 readme-generator/SKILL.md,并返回一份约 3K token 的详细指南。
# 1. Skill Discovery (at initialization)
from src.utils.skills.skill_utils import initialize_skills
available_skills, skill_prompt = initialize_skills(
skill_dirs=["./skills"],
verbose=True
)
# 2. Add to System Prompt (~500-token catalog)
system_prompt = base_prompt + skill_prompt
# 3. Runtime -- Agent loads skill when needed
# Agent decides: "This is README generation, I need the readme-generator skill"
# -> skill_tool(skill_name="readme-generator")
# -> Returns full SKILL.md content (~3K tokens)
每项技能都定义为一个 SKILL.md 文件由 YAML frontmatter 和详细的 markdown 指南组成。它包含 name、description、license 和 allowed-tools 等元数据,以及 Overview、When to Use This Skill、详细说明和 Best Practices。要添加新技能,请在 skills/ 下创建一个新目录并编写一个 SKILL.md 文件,它就会被自动发现。
启动时,智能体只加载约 500 个 token 的技能目录,而不是把超过 20,000 个 token 浪费在完整指南上(约减少 97%)。需要时,它可以额外加载几千个 token 的详细技能说明。
4. 通过验证智能体与防护措施验证质量
即使有了第 1 至第 3 层,仍存在一个风险:彼此隔离的智能体无法看到对方的工作成果,因此如果 Coder 计算有误,Reporter 就会把这个错误带入报告中。第 4 层是最后一道防线。
“提供测试工具,让智能体能够自行验证功能并修复仅凭代码无法发现的缺陷。让模型用描述性的提交信息把进度提交到 git,并在进度文件中撰写进度摘要。”
—— Anthropic,“长时运行智能体的有效驾驭框架” (2025.11)
实现细节 4-1:Tracker、Validator 和 Auditor 智能体:进度跟踪与质量保证
Tracker 会实时更新计划的检查清单。当 Coder 完成数据加载后,Supervisor 会调用 Tracker,Tracker 则根据“数据加载完成(1,000 行、5 列)”这类信息把计划项从 [ ] 更新为“已完成” [x] 。这有助于用户和系统准确了解当前进度。
验证器会独立重新执行 Coder 的计算以核实准确性。它读取 calculation_metadata.json,从源数据重新执行每一项计算,并进行比对:误差在 0.01 以内即通过,不一致的则被标记。通过验证的计算会进入 citations.json 供 Reporter 引用。Reporter 完成后,Auditor 会将最终 DOCX 与 citations.json 以及 calculation_metadata.json 而不修改它们。它记录 中的引用缺陷, audit_findings.json 并可向 Reporter 请求最多两次有针对性的重试。
实现细节 4-2:按重要性确定验证计算的优先级
逐一验证每一项计算效率低下,因此应按重要性来确定验证范围。Deep Insight 的 OptimizedValidator 采用以下阈值:
- 超过 50 项计算:激进过滤,验证所有高优先级项,仅验证 10 项中优先级项。
- 超过 20 项计算:适度过滤,验证所有高优先级项以及 15 项中优先级项。
- 20 项或更少计算:验证大部分,即所有高优先级项加上所有中优先级项,再加上 5 项低优先级项。
类型安全的比较:为避免 numpy 与 Python 的类型问题,所有值都会被转换为 float() 并检查绝对差值是否小于 0.01:
# validator.md -- type-safe numerical comparison
try:
match = abs(float(expected) - float(actual)) < 0.01
except:
match = str(expected) == str(actual)
实现细节 4-3:SummarizingConversationManager:最后的安全网
在异常情况下,上下文仍可能溢出,因此要在其他层之下保留一道安全网。Deep Insight 使用 SummarizingConversationManager ,用于此目的。
# strands_sdk_utils.py -- safety net configuration at agent creation
agent = Agent(
model=llm,
system_prompt=system_prompts,
tools=tools,
conversation_manager=SummarizingConversationManager(
summary_ratio=0.5, # summarize oldest 50% on overflow
preserve_recent_messages=10, # always preserve 10 most recent messages
summarization_system_prompt=apply_prompt_template("summarization", {})
)
)
发生溢出时,LLM 会将最旧的 50% 消息总结为一条,同时始终保留最近的 10 条,以维持当前任务的上下文。总结提示词(summarization.md)要求 clues, plans,并 tracking status 逐字保留。
实现细节 4-4:选择性提示词缓存以优化成本
上下文工程涵盖成本优化,而不仅仅是节省 token。根据每个智能体被相同提示词调用的频率,为每个智能体启用提示词缓存。Deep Insight 的按智能体设置如下:
| 智能体 | 提示词缓存 | 工具缓存 | 原因 |
| Supervisor | 是 | 是 | 高频重复调用,同时带有大型系统提示词和工具定义 |
| Coder | 是 | 是 | 依次运行多个分析脚本,每次使用相同的提示词 |
| Reporter | 是 | 是 | 逐节增量生成报告,提示词复用频率高 |
| 审计器 | 是 | 是 | 使用相同的提示词和工具,在多轮对话中检查 DOCX 和 JSON 文件,并在每次 Reporter 重试后重新运行 |
| 协调器 | 否 | 否 | 单次一次性调用,无缓存收益 |
| 规划器 | 否 | 否 | 每次请求调用一次,仅在用户请求修改计划时再次调用 |
| 验证器 | 否 | 否 | 每次调用时数据都不同,缓存命中率低 |
| 跟踪器 | 否 | 否 | 轻量级任务,无需工具,不需要缓存 |
启用缓存的智能体会在系统提示词和工具定义中插入缓存点,在重复调用时将输入 token 成本最多降低 90%。这是 Strands Agents SDK 原生支持的功能。Plan Reviewer 未出现在表中,因为它是一个人在回路中的步骤,负责收集用户批准或反馈,而不是调用模型。
结论
本文详细介绍了四层工程方法,你可以用它来高效地为超出上下文窗口的复杂任务管理上下文。
- 第 1 层(架构级隔离):每个智能体通过多智能体架构在独立的上下文中工作,仅传递压缩后的摘要。
- 第 2 层(基于提示词的控制):输出 token 预算、标准化响应格式和自包含代码理念主动限制上下文流入。
- 第 3 层(文件系统使用):write_and_execute_tool 将代码保留在上下文之外,文件系统充当智能体间的通信总线,知识仅在需要时按需加载。
- 第 4 层(验证与保障):Validator 的独立计算复验、Auditor 对最终报告的只读引用审计、Tracker 的进度跟踪、SummarizingConversationManager 的溢出预防,以及选择性提示词缓存,共同管理质量与成本。
每一层都构成一个防御系统,弥补前几层遗漏的问题。当架构隔离不足时,提示词会限制输出。当提示词不足时,工具会将内容保持在外部。而当问题仍然出现时,验证会将其捕获。
这些层中的每一层都在 Anthropic 的工程博客文章中有所记录, “AI 智能体的有效上下文工程”, “使用 MCP 进行代码执行”,以及 《我们如何构建多智能体研究系统》他们推荐的许多功能已经在 Strands Agents SDK 中提供,而不是需要你自己构建:SummarizingConversationManager、提示词缓存以及智能体即工具模式。
在构建生产级智能体时,仅靠 LLM 的上下文窗口往往不够。运用这些上下文工程技术,可以高效管理上下文,并让智能体扩展到生产工作负载。
本文使用的参考实现 Deep Insight 是开源的。请审阅代码,并针对你的领域对其进行扩展。