构建多 Agent 系统:何时使用以及如何使用
虽然单 Agent 系统已经能有效处理多数企业工作流,多 Agent 架构在合适场景下仍能释放额外价值。本文说明何时以及如何使用它。
多 Agent 系统指多个 LLM 实例各自拥有独立对话上下文,并由代码协调运行的架构。本文聚焦编排器-子 Agent 模式:由主 Agent 创建并管理专门处理子任务的 Agent。
今天,多 Agent 系统经常被用在其实单 Agent 更合适的场景中。随着模型提升,这个判断会变化,但当前仍要谨慎。
基于生产实践,多个 Agent 稳定优于单 Agent 的场景主要有三类:上下文污染影响表现、任务可以并行、专业化能改善工具选择或任务聚焦。除此之外,协调成本通常会超过收益。
为什么应先从单 Agent 开始
设计良好、工具合适的单 Agent,能完成的事情往往比很多开发者预期更多。
多 Agent 系统会引入额外开销。每增加一个 Agent,就多一个可能失败的点、多一组要维护的 prompt,也多一种意外行为来源。
我们看到一些团队把规划、执行、审查和迭代拆给不同 Agent,结果每次交接都会丢上下文,协调消耗的 tokens 甚至超过真正执行任务的 tokens。
多 Agent 系统的决策框架
只有当多 Agent 架构解决了单 Agent 无法克服的明确限制时,它才真正有价值。也就是说,只有收益足以抵消额外成本时才应采用。
下面这些模式,是我们持续观察到能带来正向回报的场景。
上下文保护
大模型的上下文窗口有限,随着上下文增长,回答质量可能下降。当某个子任务产生的信息对后续任务无关时,就会形成上下文污染。子 Agent 可以隔离上下文,让每个 Agent 专注自己的任务。
例如客服 Agent 既要查询订单历史,又要诊断技术问题。如果每次订单查询都把大量历史信息塞进上下文,Agent 对技术问题的推理能力就会下降。
单 Agent 做法:
# Single agent accumulates everything in context conversation_history = [ { "role" : "user" , "content" : "My order #12345 isn't working" }, { "role" : "assistant" , "content" : "Let me check your order..." }, # Tool result adds 2000 + tokens of order history { "role" : "user" , "content" : "... (order details, past purchases, shipping info) ..." }, { "role" : "assistant" , "content" : "Now let me diagnose the technical issue..." }, # Context is now polluted with order details the agent doesn 't need ]
在单 Agent 做法中,Agent 必须带着大量无关订单历史来分析技术问题,注意力被稀释,回答质量会下降。
多 Agent 做法:
from anthropic import Anthropic client = Anthropic() class OrderLookupAgent : def lookup_order ( self , order_id : str ) -> dict : # Separate agent with its own context messages = [ { "role" : "user" , "content" : f "Get essential details for order {order_id}" } ] response = client.messages.create( model= "claude-sonnet-4-5" , max_tokens= 1024 , messages=messages, tools=[get_order_details_tool] ) # Returns only essential information return extract_summary(response) class SupportAgent : def handle_issue ( self , user_message : str ): if needs_order_info ( user_message ): order_id = extract_order_id(user_message) # Get only what 's needed, not full history order_summary = OrderLookupAgent().lookup_order(order_id) # Inject compact summary, not full context context = f"Order {order_id}: {order_summary[' status ']}, purchased {order_summary[' date ']}" # Main agent context stays clean messages = [ {"role": "user", "content": f"{context}\n\nUser issue: {user_message}"} ] response = client.messages.create( model="claude-sonnet-4-5", max_tokens=2048, messages=messages ) return response
在多 Agent 做法中,订单查询 Agent 处理完整订单历史并提取摘要,主 Agent 只接收真正需要的 50 到 100 tokens,保持上下文聚焦。
当子任务会产生大量上下文,但其中大部分对主任务无关时,上下文隔离最有效。它也适合定义清楚的检索、过滤和摘要类任务。
并行化
并行运行多个 Agent 可以探索比单 Agent 更大的搜索空间,尤其适合搜索和研究任务。
Research 功能就使用了这种方式:主 Agent 分析问题,派生多个子 Agent 并行研究不同侧面,再汇总精炼结论。
核心实现是把问题拆成相互独立的方面,并发运行子 Agent,然后综合结果。
import asyncio from anthropic import AsyncAnthropic client = AsyncAnthropic() async def research_topic(query: str) -> dict: # Lead agent breaks query into research facets facets = await lead_agent.decompose_query(query) # Spawn subagents to research each facet in parallel tasks = [ research_subagent(facet) for facet in facets ] results = await asyncio.gather(*tasks) # Lead agent synthesizes findings return await lead_agent.synthesize(results) async def research_subagent(facet: str) -> dict: "" "Each subagent has its own context window" "" messages = [ { "role" : "user" , "content" : f "Research: {facet}" } ] response = await client.messages.create( model= "claude-sonnet-4-5" , max_tokens= 4096 , messages=messages, tools=[web_search, read_document] ) return extract_findings(response)
覆盖面提升是有成本的。多 Agent 系统通常会比等价单 Agent 消耗 3 到 10 倍 tokens,因为每个 Agent 都需要自己的上下文、协调消息和交接摘要。
并行化的主要收益是更全面,而不一定是更快。当你需要搜索很大的信息空间或从多个角度研究复杂问题时,并行 Agent 能覆盖更多内容,代价是 tokens 和总计算量更高。
专业化
有些任务需要不同工具集、系统提示词或领域知识。与其让一个 Agent 拥有几十个工具,不如让专门 Agent 配置更聚焦的工具集,可靠性通常更好。
工具集专业化
当 Agent 可用工具太多时,表现会下降。以下三个信号说明可能需要工具专业化:
• 数量:工具太多时,Agent 很难选择正确工具,常见阈值大约是 20 个以上。
• 领域混淆:工具跨多个无关领域时,Agent 容易混淆当前任务属于哪个领域。
• 性能退化:新增工具后,原有任务表现变差,说明 Agent 可能已接近工具管理能力上限。
系统提示词专业化
不同任务有时需要互相冲突的人设、约束或指令。客服要耐心共情,代码审查要精确挑剔,合规检查要严格遵守规则,头脑风暴要有创造性。拆成专门 Agent 后,行为会更稳定。
领域知识专业化
有些任务需要大量领域上下文,直接塞给通用 Agent 会过载。法律、医学等领域可以用专门 Agent 携带更聚焦的专业知识。
例如多平台集成系统要同时处理 CRM、营销自动化和消息平台。每个平台都有多个 API 端点,单 Agent 带 40 多个工具时容易选错;拆成专门 Agent 后能减少选择错误。
from anthropic import Anthropic client = Anthropic() # Specialized agents with focused toolsets and tailored prompts class CRMAgent : """ Handles customer relationship management operations """ system_prompt = "" "You are a CRM specialist. You manage contacts, opportunities, and account records. Always verify record ownership before updates and maintain data integrity across related records." "" tools = [ crm_get_contacts, crm_create_opportunity, # 8 - 10 CRM-specific tools ] class MarketingAgent : """ Handles marketing automation operations """ system_prompt = "" "You are a marketing automation specialist. You manage campaigns, lead scoring, and email sequences. Prioritize data hygiene and respect contact preferences." "" tools = [ marketing_get_campaigns, marketing_create_lead, # 8 - 10 marketing-specific tools ] class OrchestratorAgent : """ Routes requests to specialized agents """ def execute ( self , user_request : str ): response = client.messages.create( model= "claude-sonnet-4-5" , max_tokens= 1024 , system= "" "You coordinate platform integrations. Route requests to the appropriate specialist: - CRM: Contact records, opportunities, accounts, sales pipeline - Marketing: Campaigns, lead nurturing, email sequences, scoring - Messaging: Notifications, alerts, team communication" "" , messages=[ { "role" : "user" , "content" : user_request} ], tools=[delegate_to_crm, delegate_to_marketing, delegate_to_messaging] ) return response
这种模式类似现实中的专业协作:匹配角色的专家比试图掌握所有领域的通才更可靠。但专业化会引入路由复杂度,编排器必须正确分类请求并委派给合适 Agent。
什么时候单 Agent 架构不够用了
除了通用框架,还有一些具体信号说明单 Agent 模式可能已经不够用:
接近上下文限制:如果 Agent 经常使用大量上下文且表现下降,瓶颈可能是上下文压力。需要注意,压缩等上下文管理技术正在缓解这个问题。
管理大量工具:当 Agent 有 15 到 20 个以上工具时,模型会花很多上下文和注意力理解可选项。采用多 Agent 前,也可以考虑 Tool Search Tool,让 Claude 按需发现工具。
可并行的子任务:当任务天然能拆成独立部分时,例如多来源研究或多个组件测试,并行子 Agent 可以带来明显加速。
这些阈值会随着模型能力提升而变化。当前限制是实用指导,不是根本性约束。
以上下文为中心拆分任务
采用多 Agent 架构时,最重要的设计决策是如何在 Agent 之间分工。很多团队会在这里做错,导致协调成本抵消多 Agent 收益。
关键洞察是:拆任务时要采用“以上下文为中心”的视角,而不是“以问题类型为中心”的视角。
按问题类型拆分通常适得其反。例如一个 Agent 写功能、一个写测试、一个做审查,会产生持续协调开销,每次交接都丢上下文。
按上下文边界拆分通常更有效。处理某个功能的 Agent 也应该处理对应测试,因为它已经拥有必要上下文。只有上下文能真正隔离时才应该拆分。
这个原则来自多 Agent 失败模式:按角色拆分时,Agent 会像传话游戏一样反复交接,信息质量逐步下降。
有效的拆分边界包括:
• 上下文管理的关键,是让模型只读取当前任务真正需要的信息,避免无关内容稀释注意力。
• 把目标、输入、步骤、边界和成功标准说清楚,Claude 才能稳定完成复杂任务。
• 上下文管理的关键,是让模型只读取当前任务真正需要的信息,避免无关内容稀释注意力。
有问题的拆分边界包括:
• 上下文管理的关键,是让模型只读取当前任务真正需要的信息,避免无关内容稀释注意力。
• Agent 系统设计应围绕任务上下文、工具边界和可验证结果展开,不要盲目增加复杂度。
• Agent 系统设计应围绕任务上下文、工具边界和可验证结果展开,不要盲目增加复杂度。
验证子 Agent 模式
验证子 Agent 是跨领域都很稳定的一种模式。它只负责测试或验证主 Agent 的工作。
更强的编排模型越来越能直接评估子 Agent 的工作,但当编排器能力较弱、验证需要专门工具,或你想强制设置验证关卡时,验证子 Agent 仍然有价值。
这个原则来自多 Agent 失败模式:按角色拆分时,Agent 会像传话游戏一样反复交接,信息质量逐步下降。
实现方式
主 Agent 完成一个工作单元后,在继续前创建验证子 Agent,并把待验证产物、成功标准和验证工具交给它。
验证器不需要理解产物为什么这样构建,只需要判断它是否满足指定标准。
from anthropic import Anthropic client = Anthropic() class CodingAgent : def implement_feature ( self , requirements : str ) -> dict : """ Main agent implements the feature """ messages = [ { "role" : "user" , "content" : f "Implement: {requirements}" } ] response = client.messages.create( model= "claude-sonnet-4-5" , max_tokens= 4096 , messages=messages, tools=[read_file, write_file, list_directory] ) return { "code" : response.content, "files_changed" : extract_files(response) } class VerificationAgent : def verify_implementation ( self , requirements : str , files_changed : list ) -> dict : """ Separate agent verifies the work """ messages = [ { "role" : "user" , "content" : f "" " Requirements: {requirements} Files changed: {files_changed} Run the test suite and verify: 1. All existing tests pass 2. New functionality works as specified 3. No obvious errors or security issues You MUST run the complete test suite before marking as passed. Do not mark as passing after only running a few tests. Run: pytest --verbose Only mark as PASSED if ALL tests pass with no failures. " "" } ] response = client.messages.create( model= "claude-sonnet-4-5" , max_tokens= 4096 , messages=messages, tools=[run_tests, execute_code, read_file] ) return { "passed" : extract_pass_fail(response), "issues" : extract_issues(response) } def implement_with_verification(requirements: str, max_attempts : int = 3 ): for attempt in range(max_attempts): result = CodingAgent().implement_feature(requirements) verification = VerificationAgent().verify_implementation( requirements, result[ 'files_changed' ] ) if verification[ 'passed' ]: return result requirements += f "\n\nPrevious attempt failed: {verification['issues']}" raise Exception(f "Failed verification after {max_attempts} attempts" )
适用场景
验证子 Agent 适用于:
• 质量保证:运行测试套件、lint 代码、按 schema 校验输出。
• 合规检查:确认文档满足政策要求,输出符合规则。
• 输出验证:交付前确认生成内容满足规格。
• 事实核验:让单独 Agent 检查生成内容中的声明或引用。
过早宣布成功的问题
验证子 Agent 最大的失败模式,是没有充分测试就宣布通过。它可能只跑一两个测试,看到通过就结束。
缓解策略包括:
• 具体标准:写“运行完整测试套件并报告所有失败”,不要只写“确认能用”。
• 全面检查:要求验证器覆盖多个场景和边界情况。
• 反向测试:要求验证器尝试应当失败的输入,并确认确实失败。
• 明确指令:“必须运行完整测试套件后才能标记通过”非常关键。没有明确要求时,验证 Agent 容易走捷径。
下一步
多 Agent 系统很强,但并不总是合适。增加多个协调 Agent 之前,需要确认:
• 确实存在多 Agent 能解决的约束,例如上下文限制、并行机会或专业化需求。
• 拆分应跟随上下文,而不是跟随工作类型。按任务需要的上下文分组。
• 存在清晰验证点,让子 Agent 能在不需要完整上下文的情况下验证工作。
建议从能工作的最简单方案开始,只有证据支持时再增加复杂度。
这是多 Agent 系列的第一篇。想了解单 Agent 模式、上下文管理策略和多 Agent 研究系统,可以继续阅读原文中链接的相关文章。
致谢
作者:Cara Phillips,Paul Chen、Andy Schumeister、Brad Abrams 和 Theo Chu 亦有贡献。