人工智能

生产级 AI 智能体的四层上下文工程:Deep Insight 如何在可运行代码中应用它们

当生产级 AI 智能体处理数据分析和报告生成等任务时,上下文管理可能成为主要瓶颈。200K token 的窗口听起来很宽裕,直到一个真实任务在几分钟内就消耗掉其中大部分。数据分析和报告生成会让智能体在执行中途失败、丢失准确性或推高成本。已有大量已发布的指导文献涉及这一问题,但各项技术读起来容易,应用起来却难。将它们结合起来应用,能带来可衡量的差异:在本文所详述的参考实现中,单个写入并执行工具将每个脚本添加到上下文中的 token 减少了约 95%,而按需加载技能使系统提示词缩小了约 97%。

本系列将这些指导整理成可直接应用的实践。Anthropic 的工程博客文章,加上 Strands Agents SDK 内置的功能,共同归结为四层上下文工程:在架构层面隔离上下文、通过提示词控制上下文、将上下文外置到文件系统,以及用独立智能体和防护措施进行验证。在本文(第 2 部分)中,你将了解每一层如何运作,以及在可运行代码中是什么样子。我们在 Deep Insight中应用了这些技术,这是一个基于 Strands Agents SDK 和 Amazon Bedrock AgentCore 构建的开源多智能体数据分析解决方案,全文将其作为参考实现。

文章系列

第一篇文章定义了生产级多智能体系统必须解决的五个核心挑战。它介绍了 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 是开源的。请审阅代码,并针对你的领域对其进行扩展。


关于作者