BLOG / POST
多智能体架构
多智能体的三种架构模式(监督者、点对点、层级化)、五层记忆系统设计,以及面向 Agent 的工具设计原则。
- context-engineering
- multi-agent
来源:Agent-Skills-for-Context-Engineering。
模块1: 多智能体架构模式
核心概念
为什么需要多智能体架构?
单智能体的天花板:
[错误] 推理能力有限
[错误] 上下文管理受限
[错误] 工具协调复杂
随着任务复杂化:
- 上下文窗口被历史、文档、工具输出填满
- 性能下降: lost-in-middle、注意力稀缺、上下文污染
关键洞察:
子智能体存在的主要目的是隔离上下文,而不是拟人化角色分工!
[错误] 错误思维: 模拟组织角色 (像公司部门)
[正确] 正确思维: 分区上下文窗口
每个子代理在专注于其子任务的干净上下文中操作,
而不携带来自其他子任务的累积上下文。
Token经济学现实
生产数据显示:
| 架构 | Token倍数 | 使用场景 |
|---|---|---|
| 单智能体聊天 | 1x 基线 | 简单查询 |
| 单智能体 + 工具 | ~4x 基线 | 工具使用任务 |
| 多智能体系统 | ~15x 基线 | 复杂研究/协调 |
研究发现 (BrowseComp评估):
三个因素解释95%的性能方差:
1. Token使用 (80%方差)
→ 更多tokens = 更好性能
2. 工具调用数量
→ 更多工具使用
3. 模型选择
→ 更好模型 > 加倍token
关键洞察:
升级到更好的模型 (Claude Sonnet 4.5, GPT-5.2思考模式)
通常比加倍token预算提供更大性能提升
→ 模型选择和多智能体架构是互补策略
并行化优势:
单智能体: 顺序执行
任务A → 任务B → 任务C
总时间 = A + B + C
多智能体: 并行执行
[任务A] [任务B] [任务C]
总时间 = max(A, B, C)
加速 = 3倍 (3个任务)
实际案例:
研究任务需要搜索多个独立源、分析不同文档、比较方法
单智能体: 顺序处理, 上下文累积
多智能体: 同时工作, 协调者聚合结果
专业化优势:
不同任务受益于不同代理配置:
- 不同系统提示词
- 不同工具集
- 不同上下文结构
通用代理必须携带所有可能配置
→ 上下文臃肿
专业化代理仅携带所需
→ 精简上下文
三种架构模式
模式1: 监督者/编排器 (Supervisor/Orchestrator)
结构:
用户查询 → 监督者 → [专家, 专家, 专家] → 聚合 → 最终输出
监督者职责:
- 维护全局状态和轨迹
- 分解用户目标为子任务
- 路由到合适的worker
- 综合worker结果
优势:
[OK] 严格控制工作流
[OK] 易于实现人工在环干预
[OK] 确保遵循预定义计划
[OK] 清晰的责任分配
劣势:
[错误] 监督者上下文成为瓶颈
[错误] 监督者失败级联到所有worker
[错误] "电话游戏"问题
电话游戏问题及解决方案:
LangGraph基准发现监督者架构初期性能差50%, 原因是监督者错误转述子代理响应, 失去保真度。
解决方案: forward_message工具
def forward_message(message: str, to_user: bool = True):
"""
将子代理响应直接转发给用户, 无需监督者综合。
使用时机:
- 子代理响应最终且完整
- 监督者综合会丢失重要细节
- 响应格式必须完全保留
返回:
- to_user=True: 直接响应用户
- to_user=False: 输入监督者
"""
if to_user:
return {"type": "direct_response", "content": message}
return {"type": "supervisor_input", "content": message}
效果:
无forward_message:
监督者性能 = 基准 - 50%
有forward_message:
群体架构略优于监督者
(子代理直接响应用户, 消除翻译错误)
何时使用监督者模式:
[OK] 有明确分解的复杂任务
[OK] 需要跨域协调的任务
[OK] 人工监督重要的任务
[OK] 需要严格工作流的任务
实现示例:
class SupervisorAgent:
def __init__(self, workers):
self.workers = workers
self.state = {}
def delegate(self, task):
# 分解任务
subtasks = self.decompose(task)
# 路由到workers
results = []
for subtask in subtasks:
worker = self.route(subtask)
result = worker.execute(subtask)
results.append(result)
# 聚合结果
return self.synthesize(results)
def route(self, subtask):
# 基于子任务类型选择worker
if subtask.type == "research":
return self.workers["researcher"]
elif subtask.type == "analysis":
return self.workers["analyzer"]
# ...
模式2: 点对点/群体 (Peer-to-Peer/Swarm)
结构:
无中央控制
代理A ⇄ 代理B ⇄ 代理C
基于预定义协议直接通信
实现:
def transfer_to_agent_b():
"""通过函数返回值转移控制"""
return agent_b
agent_a = Agent(
name="Agent A",
functions=[transfer_to_agent_b]
)
# Agent A可以在任何时候将控制转移给Agent B
优势:
[OK] 无单点故障
[OK] 有效扩展广度优先探索
[OK] 允许可emergent问题解决行为
[OK] 灵活的工作流
劣势:
[错误] 协调复杂度随代理数量增加
[错误] 无中央状态保持者时存在分歧风险
[错误] 需要健壮的收敛约束
[错误] 难以预测行为
何时使用点对点模式:
[OK] 需要灵活探索的任务
[OK] 刚性规划适得其反的任务
[OK] 有emergent需求的任务
[OK] 无法预先分解的任务
收敛约束:
# 防止无限循环和分歧
constraints = {
"max_iterations": 10,
"convergence_threshold": 0.95,
"timeout": 300 # 秒
}
# TTL限制
agent.ttl = 100 # 100步后停止
模式3: 层级化 (Hierarchical)
结构:
战略层 (目标定义)
↓
规划层 (任务分解)
↓
执行层 (原子任务)
三层示例:
战略层:
CEO Agent
- 定义高层目标
- 设置约束
- 分配资源
- 监控进度
示例:
"进入新市场, 在6个月内达到100万用户"
规划层:
Manager Agents
- 分解目标为计划
- 协调资源
- 跟踪里程碑
示例:
"市场计划需要:
- 产品本地化
- 营销活动
- 销售渠道建立"
执行层:
Worker Agents
- 执行原子任务
- 报告状态
- 完成具体工作
示例:
"翻译UI文案为西班牙语"
"设置Facebook广告"
"联系分销商"
优势:
[OK] 镜像组织结构
[OK] 关注点清晰分离
[OK] 不同层级有不同上下文结构
[OK] 可扩展到大型项目
劣势:
[错误] 层间协调开销
[错误] 战略和执行可能错位
[错误] 复杂的错误传播
[错误] 信息可能失真
何时使用层级化:
[OK] 有清晰层级结构的大型项目
[OK] 有管理层的企业工作流
[OK] 需要高层规划和详细执行的任务
[OK] 复杂的多阶段项目
上下文隔离作为设计原则
为什么上下文隔离是主要目的:
多智能体系统通过分布解决单智能体上下文限制
每个代理在专注于其子任务的干净上下文中操作,
结果在协调层聚合,
没有任何单个上下文承担完整负担。
隔离机制:
1. 完整上下文委托 (Full Context Delegation)
用于: 复杂任务, 子代理需要完整理解
过程:
- 规划者共享其整个上下文
- 子代理有自己的工具和指令
- 但接收决策的完整上下文
权衡:
[OK] 最大能力
[错误] 违背子代理目的 (上下文仍大)
示例:
规划者: "分析这个5M token代码库的架构"
→ 将所有上下文传给架构分析代理
2. 指令传递 (Instruction Passing)
用于: 简单、明确定义的子任务
过程:
- 规划者通过函数调用创建指令
- 子代理仅接收其特定任务所需的指令
权衡:
[OK] 维持隔离
[错误] 限制子代理灵活性
示例:
规划者: "读取文件config.yaml, 返回端口配置"
→ 仅传递文件路径和查询
3. 文件系统记忆 (File System Memory)
用于: 需要共享状态的复杂任务
过程:
- 代理读写持久化存储
- 文件系统作为协调机制
- 避免共享状态传递的上下文膨胀
权衡:
[OK] 无上下文传递的共享状态
[错误] 引入延迟和一致性挑战
示例:
多个代理写入/shared/task_progress.json
其他代理读取获取状态
选择指南:
选择完整上下文委托:
- 子任务复杂, 需要全局理解
- 上下文大小不是问题
选择指令传递:
- 子任务简单、明确
- 需要严格隔离
选择文件系统记忆:
- 需要共享状态
- 异步操作可接受
- 上下文传递太昂贵
共识和协调
投票问题:
简单多数投票的问题:
- 将弱模型的幻觉视为与强模型推理相等
- 多智能体讨论因内在偏向一致
- 退化为对错误前提的共识
示例:
代理A (弱): 2+2=5
代理B (强): 2+2=4
代理C (弱): 2+2=5
多数投票: 5 (错误!)
解决方案:
1. 加权投票 (Weighted Voting)
def weighted_vote(agent_responses, weights):
"""
按置信度或专业知识加权代理投票
weights = {
"expert_agent": 0.5, # 高权重
"general_agent": 0.3, # 中权重
"novice_agent": 0.2 # 低权重
}
"""
result = aggregate(responses, weights)
return result
2. 辩论协议 (Debate Protocols)
def debate_protocol(topic, rounds=3):
"""
要求代理在多轮中相互批评输出
对抗性批评 > 协作共识 (复杂推理)
"""
for round in range(rounds):
# 代理提出论点
arguments = [agent.propose(topic) for agent in agents]
# 代理批评他人论点
critiques = []
for agent in agents:
critique = agent.criticize(arguments)
critiques.append(critique)
# 代理根据批评修订
for agent in agents:
agent.revise(topic, critiques)
return final_conclusion()
3. 基于触发的干预 (Trigger-Based Intervention)
triggers = {
"stall": StallTrigger(), # 讨论无进展
"sycophancy": SycophancyTrigger() # 代理互相模仿
}
def monitor_interaction(agents):
"""监控多智能体交互的行为标记"""
# 停滞触发器
if no_progress_detected(agents):
activate_intervention("redirect")
# 唯唯诺诺触发器
if answers_too_similar(agents):
activate_intervention("diversify")
失败模式和缓解
| 失败模式 | 描述 | 缓解策略 |
|---|---|---|
| 监督者瓶颈 | 监督者累积所有worker上下文, 容易饱和和退化 | 输出模式约束 (worker返回仅摘要)、检查点持久化状态 |
| 协调开销 | 代理通信消耗token和延迟, 复杂协调抵消并行化好处 | 清晰交接协议、批处理结果、异步通信模式 |
| 分歧 | 代理追求不同目标无中央协调, 偏离意图目标 | 明确目标边界、收敛检查、TTL限制 |
| 错误传播 | 一个代理的输出错误传播到消费该输出的下游代理 | 输出前验证、重试逻辑+熔断器、幂等操作 |
实现示例:
# 监督者瓶颈缓解
class Supervisor:
def aggregate_results(self, worker_outputs):
# 要求worker返回摘要而非完整输出
schema = {
"summary": str,
"key_findings": List[str],
"confidence": float
}
return validate_outputs(worker_outputs, schema)
# 协调开销缓解
def handoff(agent_a, agent_b, state):
"""清晰交接协议, 最小化通信"""
# 仅传递必要状态
minimal_state = {
"task": state["task"],
"progress": state["progress"]
}
return agent_b.receive(minimal_state)
# 分歧缓解
def convergence_check(agents, shared_goal):
"""验证朝共享目标的进展"""
positions = [agent.get_position() for agent in agents]
divergence = calculate_divergence(positions)
if divergence > threshold:
realign_agents(agents, shared_goal)
# 错误传播缓解
def validate_output(agent_output):
"""输出前验证"""
if not is_valid(agent_output):
raise ValidationError(agent_output)
return agent_output
def retry_with_circuit_breaker(agent, task, max_retries=3):
"""重试逻辑+熔断器"""
for attempt in range(max_retries):
try:
return agent.execute(task)
except TemporaryError:
continue
except PermanentError:
break # 熔断
raise CircuitBreakerError()
模块2: 记忆系统设计
核心概念
记忆谱系:
即时上下文 ← → 永久存储
工作内存 (上下文窗口)
├─ 零延迟访问
└─ 会话结束时消失
短期记忆 (会话持久)
├─ 可搜索
└─ 会话结束消失
长期记忆 (跨会话持久)
├─ 结构化
└─ 半永久
永久记忆 (归档)
├─ 可查询
└─ 永久
有效架构使用谱系上的多层。
为什么简单向量存储不足
向量RAG的问题:
向量RAG:
- 在共享嵌入空间嵌入查询和文档
- 相似性搜索检索最语义相似的文档
- 对文档检索工作良好
- 但缺乏代理记忆的结构
示例失败:
代理学习: "客户X在日期Z购买产品Y"
向量存储可以:
[OK] 检索这个事实 (如果直接询问)
但无法回答:
[错误] "购买产品Y的客户还买了什么产品?"
原因: 关系结构未保留
→ 图查询不可能, 仅相似性搜索
时间有效性问题:
事实随时间变化:
- 用户地址从A变到B
- 产品价格从$100变到$120
- 公司名称从"X"变为"Y"
向量存储:
[错误] 无机制区分"当前事实"vs"过时事实"
[错误] 除了显式元数据和过滤
结果:
→ 检索返回过时信息
→ 上下文冲突 (矛盾信息)
迁移到基于图的记忆
知识图谱优势:
向量存储:
[文档] → 嵌入 → 相似性搜索
知识图谱:
实体A --关系R--> 实体B
示例:
(客户X) --[购买]--> (产品Y)
(产品Y) --[类别]--> (电子产品)
(产品Y) --[相关]--> (产品Z)
查询: "购买产品Y的客户还买了什么?"
遍历: (客户X) → [购买] → (产品Y) ← [购买] ← (客户W) → [购买] → (产品Z)
→ 支持遍历关系而非仅相似性的查询
时间知识图谱:
为事实添加有效性期间
事实有:
- valid_from (从何时有效)
- valid_until (到何时有效, 可选)
示例:
(客户X) --[居住在, 2020-01-01至2022-06-15]--> (地址A)
(客户X) --[居住在, 2022-06-16至今]--> (地址B)
查询: "客户X在2021-05-20的地址是什么?"
→ 仅检索在2021-05-20有效的地址
→ 返回地址A
启用:
[OK] 时间旅行查询
[OK] 重建特定时间点的知识
[OK] 防止上下文冲突 (过时vs当前信息)
[OK] 时间推理 (实体如何变化)
基准性能比较
DMR基准数据 (Deep Memory Retrieval):
| 记忆系统 | DMR准确率 | 检索延迟 | 备注 |
|---|---|---|---|
| Zep (时间KG) | 94.8% | 2.58s | 最佳准确率, 快速检索 |
| MemGPT | 93.4% | 可变 | 良好通用性能 |
| GraphRAG | ~75-85% | 可变 | 比基线RAG高20-35% |
| Vector RAG | ~60-70% | 快 | 失去关系结构 |
| 递归摘要 | 35.3% | 低 | 严重信息丢失 |
关键发现:
Zep vs 全上下文基线:
- 检索延迟减少90% (2.58s vs 28.9s for GPT-5.2)
- 效率来源: 仅检索相关子图而非整个上下文历史
GraphRAG vs 基线RAG:
- 复杂推理任务准确率高20-35%
- 通过基于社区的摘要减少幻觉30%
递归摘要:
- 仅35.3%准确率
- 严重信息损失
- 不推荐用于复杂任务
五层记忆架构
第1层: 工作记忆 (Working Memory)
上下文窗口本身
特点:
- 零延迟访问
- 有限容量
- 会话结束消失
使用模式:
1. 草稿本计算
- 代理跟踪中间结果
2. 对话历史
- 为当前任务保留对话
3. 当前任务状态
- 跟踪活跃目标的进展
4. 活跃检索文档
- 当前使用的信息
优化:
- 仅保留活跃信息
- 在离开注意力前摘要已完成工作
- 关键信息放在注意力优势位置
第2层: 短期记忆 (Short-Term Memory)
跨当前会话持久, 不跨会话
特点:
- 可搜索
- 会话结束消失
- 中等延迟
实现:
1. 会话范围数据库
- persist until session end
2. 文件系统存储
- 指定会话目录
3. 内存缓存
- 会话ID键
用例:
- 跨轮跟踪对话状态
- 存储工具调用中间结果
- 维护任务检查清单
- 会话内缓存检索信息
第3层: 长期记忆 (Long-Term Memory)
跨会话无限期持久
特点:
- 结构化
- 半永久
- 检索延迟
实现范围:
- 简单键值存储
- 图数据库
- 向量存储
- 混合系统
选择基于:
- 建模关系的复杂性
- 需要的查询模式
- 可接受的基础设施复杂性
用例:
- 跨会话学习用户偏好
- 建立领域知识库
- 维护实体登记和关系历史
- 存储可重用的成功模式
第4层: 实体记忆 (Entity Memory)
专门跟踪实体 (人、地点、概念、对象)
维护:
1. 实体身份
示例: "John Doe"在一个对话中提及
是同一人在另一个对话中
2. 实体属性
示例: John Doe属性:
- 职业: 工程师
- 公司: Acme Corp
- 位置: 纽约
3. 实体关系
示例: John Doe --[工作于]--> Acme Corp
Acme Corp --[位于]--> 纽约
创建:
基础知识图谱
第5层: 时间知识图谱 (Temporal Knowledge Graphs)
扩展实体记忆, 显式有效性期间
事实不仅是真/假
而是在特定时间范围内为真
启用:
[OK] 查询: "用户在日期X的地址是什么?"
通过检索该日期范围内有效的事实
[OK] 防止上下文冲突
过时信息与新数据矛盾
[OK] 时间推理
实体如何随时间变化
示例:
(用户X) --[居住在, 2020-01至2022-06]--> (地址A)
(用户X) --[居住在, 2022-06至今]--> (地址B)
query_2021 = "用户X的地址 (2021-05)"
→ 返回地址A
query_2023 = "用户X的地址 (2023-01)"
→ 返回地址B
记忆实现模式
模式1: 文件系统即记忆 (File-System-as-Memory)
# 简单、无需额外基础设施、渐进式加载
实现:
- 文件系统层次结构组织
- 有意义的命名约定
- 结构化格式 (JSON, YAML)
- 时间戳用于时间跟踪
优势:
[OK] 简单
[OK] 透明
[OK] 可移植
劣势:
[错误] 无语义搜索
[错误] 无关系跟踪
[错误] 需手动组织
示例结构:
memory/
├── entities/
│ ├── user_123.json
│ └── company_456.json
├── conversations/
│ └── conv_2025-01-15.json
└── facts/
└── fact_789.json
模式2: 带元数据的向量RAG
# 语义搜索 + 过滤能力
嵌入事实/文档, 存储元数据:
{
"embedding": [0.1, 0.2, ...],
"metadata": {
"entity_tags": ["user", "customer"],
"valid_from": "2025-01-01",
"source": "conversation_123",
"confidence": 0.95
}
}
查询:
元数据过滤器 + 语义搜索
示例:
query = "用户偏好"
filters = {
"entity": "user_123",
"valid_from": ">= 2025-01-01"
}
results = vector_store.search(query, filters)
模式3: 知识图谱
# 显式建模实体和关系
定义:
- 实体类型 (用户、产品、公司)
- 关系类型 (购买、工作于、位于)
- 图数据库或属性图存储
- 常见查询模式索引
示例Cypher查询 (Neo4j):
MATCH (user:User {id: "123"})-[:PURCHASED]->(product:Product)
MATCH (product)-[:RELATED_TO]->(related:Product)
RETURN related.name
"用户123购买的产品相关的产品"
模式4: 时间知识图谱
# 为事实添加有效性期间
实现:
- 每个关系有valid_from和valid_until
- 时间范围索引
- 时间点查询
示例查询 (Cypher):
MATCH (user:User {id: "123"})-[r:LIVES_AT]->(address:Address)
WHERE user.id = $user_id
AND r.valid_from <= $query_time
AND (r.valid_until IS NULL OR r.valid_until > $query_time)
RETURN address
"用户在特定时间的地址是什么?"
记忆检索模式
语义检索:
# 通过嵌入相似性检索
def retrieve_semantic(query, top_k=5):
query_embedding = embed(query)
results = vector_store.similarity_search(query_embedding, k=top_k)
return results
实体检索:
# 通过遍历图关系
def retrieve_entity(entity_id, depth=2):
# 检索所有与实体相关的记忆
query = f"""
MATCH (entity {{id: '{entity_id}'}})-[r*1..{depth}]->(related)
RETURN related
"""
return graph_db.query(query)
时间检索:
# 通过有效性期间过滤
def retrieve_temporal(entity_id, query_time):
query = f"""
MATCH (entity {{id: '{entity_id}'}})-[r]->(related)
WHERE r.valid_from <= '{query_time}'
AND (r.valid_until IS NULL OR r.valid_until > '{query_time}')
RETURN related
"""
return graph_db.query(query)
记忆整合
为什么需要整合:
记忆随时间累积
→ 需要整合防止无界增长
→ 移除过时信息
→ 提高检索性能
整合触发器:
triggers = [
"显著记忆累积后",
"检索返回过多过时结果",
"定期计划 (每周/每月)",
"显式请求整合时"
]
整合过程:
def consolidate_memory():
# 1. 识别过时事实
outdated = identify_outdated_facts()
# 2. 合并相关事实
merged = merge_related_facts()
# 3. 更新有效性期间
update_validity_periods()
# 4. 归档或删除过时事实
archive_or_delete(outdated)
# 5. 重建索引
rebuild_indexes()
模块3: 工具设计原则
核心概念
工具作为契约:
工具 = 确定性系统与非确定性代理间的契约
人类调用API:
- 理解契约
- 阅读文档
- 发出适当请求
- 知道如何处理错误
代理调用工具:
- 从描述推断契约
- 从自然语言生成调用
- 必须理解参数和格式
- 需要恢复指导
→ 需要重新思考API设计!
工具描述即提示词:
工具描述加载到代理上下文中
→ 共同引导行为
不仅是文档
→ 是塑造代理如何推理工具使用的提示工程
示例:
差: "搜索数据库"
好: "通过ID或电子邮件检索客户信息。
使用时机: 用户询问特定客户详细信息...
返回: 客户对象, 包含...
错误: NOT_FOUND, INVALID_FORMAT..."
整合原则
核心原则:
如果人类工程师不能确定在给定情况下
应该使用哪个工具,
就不能期望代理做得更好。
→ 偏好单个综合工具而非多个狭窄工具
示例对比:
[错误] 多个狭窄工具:
list_users() # 列出用户
list_events() # 列出事件
create_event() # 创建事件
代理必须:
1. 知道调用list_users查找参与者
2. 知道调用list_events检查冲突
3. 知道调用create_event创建
4. 正确排序调用
5. 处理失败
→ 复杂、易错
[OK] 单个综合工具:
schedule_event(
title: str,
attendees: List[str],
duration: int
# 内部处理:
# - 查找参与者可用性
# - 检查现有事件冲突
# - 创建事件
)
代理仅:
1. 提供事件详情
2. 工具处理工作流
→ 简单、可靠
为什么整合有效:
1. 代理有有限上下文和注意力
→ 每个工具在工具选择阶段竞争注意力
2. 每个工具添加描述tokens
→ 消耗上下文预算
3. 重叠功能造成歧义
→ 哪个工具用于给定情况?
整合:
- 消除冗余描述 (减少token)
- 消除歧义 (一个工具覆盖工作流)
- 减少工具选择复杂度
何时整合:
[OK] 应该整合:
- 工具链式使用以完成工作流
- 工具重叠功能
- 工具用于一致的模式
[错误] 不应整合:
- 根本不同行为的工具
- 不同上下文中使用的工具
- 可能独立调用的工具
架构简化
文件系统代理模式:
不为数据探索、模式查找、查询验证构建自定义工具
→ 通过单个命令执行工具提供直接文件系统访问
代理使用标准Unix工具:
grep, cat, find, ls, jq, etc.
示例对比:
[错误] 复杂工具架构:
# 专门工具
explore_database_schema()
query_table()
validate_query()
analyze_results()
每个需要描述、参数、错误处理...
→ 大量维护开销
[OK] 简化架构:
# 单个执行工具
execute_command(command: str)
代理使用:
execute_command("psql -d mydb -c '\d table_name'")
execute_command("psql -d mydb -c 'SELECT * FROM users LIMIT 10'")
execute_command("cat schema.sql | grep 'CREATE TABLE'")
→ 灵活、强大、零维护
为什么有效:
1. 文件系统是模型深刻理解的经过验证的抽象
2. 标准工具有可预测、文档完善的行为
3. 代理灵活链接原语, 不受预定义工作流约束
4. 文件中的良好文档替代摘要工具需求
关键:
文档质量 > 工具复杂性
何时简化胜过复杂:
[OK] 简化有效:
- 数据层文档良好、结构一致
- 模型有足够推理能力导航复杂性
- 专门工具约束而非启用模型
- 花费更多时间维护脚手架而非改进结果
[错误] 简化失败:
- 底层数据混乱、不一致、文档不良
- 领域需要模型缺乏的专门知识
- 安全约束需要限制代理能力
- 操作真正复杂, 受益于结构化工作流
停止约束推理:
常见反模式: 构建工具"保护"模型免受复杂性
例子:
- 预过滤上下文
- 约束选项
- 包装交互验证逻辑
- 抽象复杂系统
问题:
这些护栏随模型改进常成为负债
关键问题:
工具是启用新能力, 还是约束模型本可自行处理的推理?
为未来模型构建:
模型改进快于工具跟进度
为今天模型优化的架构可能对明天模型过度约束
→ 构建最小架构, 可受益模型改进
而非锁定当前限制的复杂架构
策略:
1. 优先考虑原语
2. 投资文档质量
3. 避免过度抽象
4. 让模型推理
工具描述工程
描述结构 (回答四个问题):
1. 工具做什么?
# 差
"搜索数据库"
# 太模糊
# 好
"通过ID或电子邮件检索客户信息"
# 清晰、具体
2. 何时使用?
"""
使用时机:
- 用户询问特定客户详细信息
- 需要客户上下文进行决策
- 验证客户身份
"""
3. 接受什么输入?
"""
参数:
customer_id: 客户唯一标识符
格式: "CUST-######" (例如 "CUST-000001")
email: 客户电子邮件地址
格式: 标准email格式
默认: 如果提供email则忽略customer_id
"""
4. 返回什么?
"""
返回:
Customer对象包含:
- id: 客户ID
- name: 全名
- email: 电子邮件地址
- status: 账户状态 (ACTIVE, INACTIVE, SUSPENDED)
- created_at: 账户创建日期
错误:
NOT_FOUND: 未找到客户
INVALID_FORMAT: ID/email格式无效
MULTIPLE_MATCHES: 多个客户匹配email
"""
完整示例:
def get_customer(
customer_id: str = None,
email: str = None,
format: str = "concise"
) -> Customer:
"""
通过ID或电子邮件检索客户信息。
使用时机:
- 用户询问特定客户详细信息、历史或状态
- 用户提供客户标识符并需要相关信息
- 验证客户身份或账户状态
参数:
customer_id: 客户ID (格式"CUST-######")
email: 客户电子邮件地址
format: "concise"关键字段, "detailed"完整记录
返回:
concise格式: id, name, email, status
detailed格式: 完整对象, 包括历史、订单、支持票据
错误:
NOT_FOUND: 未找到客户
INVALID_FORMAT: ID必须匹配CUST-######模式
"""
响应格式优化
为什么需要格式选项:
工具响应大小显著影响上下文使用
场景A: 确认客户存在
→ 需要基本字段即可
场景B: 分析客户行为
→ 需要完整历史和订单数据
→ 代理应该控制详细程度
实现:
def get_customer(
customer_id: str,
format: str = "concise" # 默认concise
) -> dict:
"""
format参数:
- "concise": 仅关键字段
适用: 确认、基本信息
- "detailed": 完整对象
适用: 决策的完整上下文
"""
if format == "concise":
return {
"id": customer.id,
"name": customer.name,
"email": customer.email,
"status": customer.status
}
else: # detailed
return {
"id": customer.id,
"name": customer.name,
"email": customer.email,
"status": customer.status,
"order_history": customer.orders,
"support_tickets": customer.tickets,
"preferences": customer.preferences,
"created_at": customer.created_at
}
指导代理选择:
"""
格式选择指导:
- 使用"concise": 快速确认、状态检查
- 使用"detailed": 分析、决策、报告生成
"""
错误消息设计
两个受众:
开发者: 调试问题
代理: 从失败中恢复
→ 代理错误消息必须可操作!
设计原则:
[OK] 告诉代理什么出错
[OK] 如何纠正
[OK] 提供示例
[OK] 下一步建议
[错误] "错误: 无效输入" (无帮助)
[错误] "失败" (无信息)
示例对比:
[错误] 糟糕:
{
"error": "Invalid input"
}
# 代理无法知道什么无效或如何修正
[OK] 良好:
{
"error": "INVALID_FORMAT",
"message": "customer_id必须匹配格式'CUST-######'",
"provided": "12345",
"expected_format": "CUST-000001",
"suggestion": "请提供格式为CUST-######的ID, 例如CUST-000123"
}
# 代理知道:
# - 什么错误
# - 提供了什么
# - 期望什么
# - 如何修正
可恢复错误:
# 重试错误
{
"error": "TEMPORARY_UNAVAILABLE",
"message": "数据库暂时不可达",
"retry_after": 5, # 秒
"suggestion": "5秒后重试"
}
# 输入错误
{
"error": "MISSING_PARAMETER",
"message": "缺少必需参数'customer_id'",
"required_params": ["customer_id", "email"],
"provided_params": ["email"],
"suggestion": "提供customer_id参数"
}
# 权限错误
{
"error": "PERMISSION_DENIED",
"message": "无权限访问此资源",
"required_permission": "customers:read",
"suggestion": "联系管理员授予customers:read权限"
}
MCP工具命名要求
问题:
使用MCP (模型上下文协议) 时,
多个服务器可能提供同名工具
Example:
server_a.get_user()
server_b.get_user()
代理调用"get_user()" → "tool not found"错误
解决方案:
# [OK] 正确: 完全限定名称
"使用BigQuery:bigquery_schema工具检索表模式"
"使用GitHub:create_issue工具创建问题"
# [错误] 错误: 非限定名称
"使用bigquery_schema工具..."
# 可能因多个服务器而失败
格式: ServerName:tool_name
实施:
# 在所有工具引用中包括服务器上下文
def describe_tools():
return """
可用工具:
- BigQuery:bigquery_schema: 检索BigQuery表模式
- BigQuery:execute_query: 执行SQL查询
- GitHub:create_issue: 创建GitHub问题
- GitHub:get_file: 获取文件内容
"""
工具集合设计
研究显示:
工具描述重叠导致模型混乱
更多工具不总是带来更好结果
合理指南:
- 大多数应用: 10-20个工具
- 如需更多: 使用命名空间创建逻辑分组
帮助代理选择正确工具:
1. 工具分组
# 命名空间组织
database_tools = [
"db:query",
"db:schema",
"db:tables"
]
file_tools = [
"file:read",
"file:write",
"file:list"
]
# 代理路由到适当组
2. 基于示例的选择
def get_customer(customer_id: str):
"""
通过ID检索客户信息
示例:
get_customer("CUST-000001") → 返回客户1的信息
get_customer("CUST-999999") → 错误: 未找到
对比:
NOT: get_orders() # 获取订单历史
NOT: search_customers() # 搜索客户列表
"""
3. 层级: 伞形工具
# 伞形工具路由到专门的子工具
def data_operation(operation: str, **params):
"""
执行数据操作
operation参数确定子工具:
- "query": 执行SQL查询
- "schema": 获取表模式
- "tables": 列出所有表
示例:
data_operation("query", sql="SELECT * FROM users")
data_operation("schema", table="users")
data_operation("tables")
"""
使用代理优化工具
Claude可以优化自己的工具:
给定工具和观察到的失败模式
→ 诊断问题
→ 建议改进
生产测试:
- 任务完成时间减少40%
- 帮助未来代理避免错误
工具测试代理模式:
def optimize_tool_description(tool_spec, failure_examples):
"""
使用代理分析工具失败并改进描述
过程:
1. 代理尝试在多样任务中使用工具
2. 收集失败模式和摩擦点
3. 代理分析失败并提出改进
4. 对相同任务测试改进的描述
"""
prompt = f"""
分析此工具规范和观察到的失败。
工具: {tool_spec}
观察到的失败:
{failure_examples}
识别:
1. 代理为什么失败
2. 描述中缺少什么信息
3. 什么歧义导致错误使用
提出解决这些问题的改进工具描述。
"""
return get_agent_response(prompt)
创建反馈循环:
代理使用工具
↓
生成失败数据
↓
代理分析失败
↓
改进工具描述
↓
减少未来失败
工具设计示例
良好设计示例
def get_customer(
customer_id: str,
format: str = "concise"
) -> dict:
"""
通过ID检索客户信息。
使用时机:
- 用户询问特定客户详细信息
- 决策需要客户上下文
- 验证客户身份
参数:
customer_id: 格式"CUST-######" (如"CUST-000001")
format: "concise"关键字段, "detailed"完整记录
返回:
concise格式: id, name, email, status
detailed格式: 完整记录, 包括历史、订单、支持
错误:
NOT_FOUND: 客户ID未找到
INVALID_FORMAT: ID必须匹配CUST-######模式
示例:
get_customer("CUST-000001") → 客户1的信息
get_customer("CUST-999999", "detailed") → 错误: 未找到
"""
为什么好:
[OK] 清晰名称: get_customer (动词_名词)
[OK] 使用时机: 明确场景
[OK] 参数描述: 格式、约束、默认值
[OK] 返回描述: 格式选项、字段
[OK] 错误处理: 错误类型、含义
[OK] 示例: 成功和失败情况
糟糕设计示例
def search(query):
"""搜索数据库。"""
pass
问题分析:
| 问题 | 描述 | 后果 |
|---|---|---|
| 模糊名称 | “search”搜索什么, 为什么目的? | 代理不知道何时使用 |
| 缺少参数 | 什么数据库? 查询什么格式? | 代理无法正确调用 |
| 无返回描述 | 返回什么? 列表? 字符串? | 代理无法解释结果 |
| 无使用上下文 | vs其他工具? | 代理选择错误工具 |
| 无错误处理 | 数据库不可用时? | 代理无法恢复 |
失败模式:
1. 代理应在使用更具体工具时调用此工具
2. 代理无法确定正确查询格式
3. 代理无法解释结果
4. 代理无法从失败中恢复
核心原则总结
多智能体架构
-
子代理存在主要是为了隔离上下文
- 不是拟人化角色分工
- 每个子代理在干净上下文中操作
-
选择架构模式基于协调需求
- 监督者: 明确分解、人工监督
- 点对点: 灵活探索、emergent需求
- 层级化: 大型项目、企业管理
-
实现明确交接协议
- 状态传递
- 避免电话游戏问题 (forward_message工具)
- 直接响应机制
-
监控失败模式
- 监督者瓶颈 (输出约束、检查点)
- 协调开销 (批处理、异步)
- 分歧 (收敛检查、TTL)
- 错误传播 (验证、重试、熔断)
-
Token经济学现实
- 多智能体系统消耗~15x基线tokens
- 但模型选择常比token预算更重要
- 并行化优势 = 时间节省
记忆系统
-
匹配记忆架构到查询需求
- 简单持久化: 文件系统记忆
- 语义搜索: 向量RAG + 元数据
- 关系推理: 知识图谱
- 时间有效性: 时间知识图谱
-
实现渐进式披露
- 按需记忆加载
- 战略性注入注意力优势位置
-
使用时间有效性
- 防止过时信息冲突
- 时间旅行查询
- 时间推理
-
定期整合
- 防止无界增长
- 移除过时信息
- 合并相关事实
-
五层架构
- 工作记忆 (上下文)
- 短期记忆 (会话)
- 长期记忆 (跨会话)
- 实体记忆 (实体跟踪)
- 时间KG (时间有效性)
工具设计
-
整合减少歧义
- 单个综合工具vs多个狭窄工具
- 人类无法确定 → 代理无法确定
-
描述回答什么、何时、返回什么
- 清晰、具体
- 使用上下文
- 示例和默认值
-
实现响应格式选项
- concise vs detailed
- token效率
-
错误消息使代理能够恢复
- 可操作
- 纠正指导
- 明确下一步
-
质疑工具启用还是约束模型
- 为未来模型构建
- 最小架构 > 复杂架构
- 文档质量 > 工具复杂性
-
使用代理优化工具
- 反馈循环
- 失败分析
- 迭代改进
(完)