如何进行 AI Agent 的上下文工程管理?
作者:🧑🚀 deadmau5v 发布于 2025/10/17
如何进行 AI Agent 的上下文工程管理?
最近AI Agent很火啊。但真正动手做过的人都知道。最大的坑不是模型不够聪明,而是Agent运行时间一长,上下文就爆了,然后性能急剧下降。
今天聊聊在构建生产级AI Agent时,那些看似简单实则要命的工程决策。
上下文爆炸
先说问题的本质。Agent和普通的ChatLLM最大的区别是什么?自主性。它会在一个循环里不断调用工具,每次调用都会产生结果,这些结果都要塞回上下文。
举个例子:一个研究型Agent,比如Deepsearch、Manus等,可能需要:
- 搜索20次
- 读取10个网页
- 分析5个文档
- 生成3个图表
每个操作的结果少则几百tokens,多则上万。50次工具调用后,你的上下文可能已经突破100K tokens。然后模型开始”犯傻”:重复操作、忘记之前的结果、甚至开始胡言乱语。
Anthropic把这个现象叫”Context Rot”(上下文腐烂),很形象。
搜索结果:存还是不存?这是个问题
我们用网络搜索这个最常用,token较大的案例作为演示。
这是我见过争议最大的问题之一。搜索工具返回了10个网页的摘要,每个1000 tokens,你怎么办?
方案一:全部保留
# 反面教材
search_results = search_tool.search(query)
messages.append({
"role": "tool",
"content": search_results # 10000 tokens进入上下文
})
优点:信息无损,Agent随时可以引用
缺点:上下文快速膨胀,3-5次搜索就爆了
方案二:激进压缩
# 只保留标题和URL
compressed = [{"title": r.title, "url": r.url} for r in results]
messages.append({
"role": "tool",
"content": json.dumps(compressed) # 只有200 tokens
})
优点:极度节省空间
缺点:Agent看不到内容,可能需要重复读取
方案三:混合策略(推荐)
# 方案一:全部塞进上下文
messages.append({
"content": search_results # 10000 tokens
})
# 方案二:只保留标题
messages.append({
"content": json.dumps(titles_only) # 200 tokens
})问题:要么浪费上下文,要么丢失信息
# 完整结果写文件,上下文只放摘要
file_path = f"search_{timestamp}.json"
save_to_file(search_results, file_path)
summary = summarize(search_results, max_tokens=500)
messages.append({
"role": "tool",
"content": f"搜索完成,结果已保存至 {file_path}\n摘要:{summary}"
})精髓:让Agent既能看到关键信息,又能在需要时读取完整内容
智能体间通信
多Agent协作听起来很美好,实际上是个大坑。核心问题:信息同步。
反模式:全量共享
# 错误示范:每个子Agent都带着完整历史
def spawn_sub_agent(full_context):
sub_agent = Agent(
context=full_context, # 包含所有历史消息
task=specific_task
)
return sub_agent.run()
问题:
- 预填充成本极高
- 子Agent被无关信息干扰
- KV缓存无法复用
正确姿势:按需传递
# 方式一:任务导向的最小上下文
def delegate_task(task_description, required_files=[]):
context = {
"task": task_description,
"files": required_files,
"output_schema": {...} # 约定输出格式
}
return sub_agent.execute(context)
# 方式二:共享存储,独立上下文
def parallel_research(topics):
shared_workspace = create_workspace()
agents = []
for topic in topics:
agent = Agent(
task=f"研究{topic},结果写入workspace",
workspace=shared_workspace,
context=[] # 空白上下文
)
agents.append(agent)
return run_parallel(agents)
关键原则:
- 能通过文件共享的,不要放上下文
- 定义清晰的输入输出契约
- 子任务要高度独立
延伸阅读:如果你在构建多Agent系统,可以关注一下 Google A2A 协议 和 Anthropic MCP。A2A 解决 Agent 间的标准化通信,MCP 解决 Agent 与工具的标准化连接。不过说实话,除非你在做平台级产品,否则直接写代码可能更快。
“智能体即工具”设计模式
核心思想:把复杂的子任务封装成一个工具,但背后是另一个Agent,类似于Google的A2A协议。
class AgentTool:
def __init__(self, agent_config):
self.agent = Agent(agent_config)
def execute(self, instruction):
# 对外表现为简单工具
result = self.agent.run(instruction)
# 只返回结构化结果
return result.to_dict()
# 主Agent眼中就是一个普通工具
tools = [
search_tool,
file_tool,
AgentTool(deep_research_config), # 实际是个Agent
AgentTool(code_review_config) # 这也是
]
优势:
- 主Agent的上下文保持简洁
- 复杂逻辑被封装,可独立迭代
- 可以用不同的模型(省钱)
适用场景:
- 深度研究某个特定问题
- 多步骤的数据处理
- 需要特殊prompt的任务
数据格式:Plain Text vs Structured
这是个被忽视但很重要的细节。
原则一:优先使用基于行的格式
# 好的格式
logs = """
2024-01-15 10:00:00 | 开始搜索
2024-01-15 10:00:05 | 找到10个结果
2024-01-15 10:00:10 | 开始分析第1个结果
"""
# 不好的格式
logs = {
"entries": [
{"time": "10:00:00", "action": "search"},
{"time": "10:00:05", "results": 10}
]
}
为什么?因为Agent可以用grep、sed等工具快速定位,而JSON需要解析。
原则二:结构化数据用Schema约束
# 定义明确的Schema
SUMMARY_SCHEMA = {
"files_modified": List[str],
"key_findings": List[str],
"next_steps": List[str],
"blockers": Optional[List[str]]
}
# 强制Agent按格式输出
def summarize_with_schema(content, schema):
prompt = f"按以下格式总结:{schema}"
return structured_output(prompt, content)
原则三:大数据不进上下文
# 反面教材
df = pd.read_csv("huge_file.csv") # 100MB
context.append(f"数据:{df.to_string()}") # 疯了
# 正确做法
stats = df.describe()
sample = df.head(10)
context.append(f"""
数据统计:{stats}
样本预览:{sample}
完整数据:huge_file.csv ({len(df)} rows)
""")
架构设计的几个关键决策
1. 工具数量控制
- 不要超过30个工具(经验值:10-20个最佳)
- 用代码执行来扩展能力,而不是无限增加工具
- 原子化 + 可组合 > 大而全
2. 缓存策略
- 利用好模型商的KV缓存(能省很多钱)
- 稳定的系统提示词放最前面
- 频繁变化的内容放后面
3. 压缩时机
- 设置”腐烂阈值”(通常100-200K tokens)
- 先压缩,后摘要
- 保留最近N轮完整对话
4. 简化原则
- 能用文件系统解决的,不要用数据库
- 能用grep的,不要用向量检索
- 能单Agent搞定的,不要多Agent
最重要的教训
做了这么多Agent项目,最大的感悟是:大部分时候,你不需要那些花哨的技术。
几个反直觉的事实:
- 模型升级带来的提升,往往大于你所有的工程优化
- 简单粗暴的方案,往往比精巧的设计更稳定
- 过早优化真的是万恶之源
写在最后
上下文工程本质上是个资源管理问题。就像操作系统管理内存一样,我们在管理Agent的”认知资源”。
记住最重要的原则:保持简单。工程师的价值在于选择合适的技术,而不是追逐最新的技术。
能跑起来的糙代码,胜过设计完美但跑不起来的架构。
评论