
几个月前我第一次把 AgentChat 这套基于大语言模型的多智能体对话框架用到一个实际的数据分析项目里当时最大的感受是以前我写 Prompt 让一个模型大包大揽现在换成三四个各司其职的智能体反而更可控了。AgentChat 并不是又一个聊天机器人封装而是一套把多个 AI 智能体组织成一个对话团队、让它们通过消息协作完成任务的多智能体对话框架。它可以用来做复杂的代码生成、数据管线治理、文档审校也可以当作企业内部自动化工作流的中枢。无论你是刚接触多智能体开发的初学者还是已经跑过不少 LangChain 项目的开发者这篇文章都值得往下看我会从设计逻辑、最小 Demo、核心概念到完整实战和本地化部署一步步拆开这套框架顺便把踩过的坑一起说清楚。1. 多智能体对话框架为什么值得用先从单模型困境说起1.1 单一大模型的“角色过载”问题很多团队一开始做 AI 应用习惯把所有需求塞进一个大模型里既要让它理解用户意图又要规划步骤还要写代码、执行代码、检查结果最后写一份漂亮的总结。你会发现 prompt 越写越长最后的输出却越来越不稳定。原因很简单一个大模型在同一轮推理里要同时扮演“目标拆解者”“代码执行者”“质量检查员”三种角色任何一个环节出问题整条链路就崩。我自己有一种切身体感单模型的 system prompt 就像是让一个全科医生同时做问诊、开方、拿药和手术不是能力不够而是注意力被摊薄了。角色一旦复杂模型就会在长上下文里“迷失”前面说要做什么、后面就忘了甚至编造出根本没执行过的工具调用来。这个问题的本质是把多个推理任务塞进同一个上下文窗口既要规划又要执行既占 Token 又互相干扰。1.2 AgentChat 的设计哲学消息驱动的多智能体调度AgentChat 解决这个问题的思路是把“一个全能模型”拆成“多个专业智能体”每个智能体有自己的名字、系统提示词、工具列表和记忆它们之间靠标准化的消息对象进行沟通。这套思路并不神秘你可以把它理解成一个“项目小组”项目组里每个人各干一个岗位组员之间的沟通用统一的会议纪要格式消息对象会议的主持逻辑调度器决定下一步谁发言。AgentChat 里的RoundRobinGroupChat是轮流发言SelectorGroupChat是让一个“主持人”智能体动态决定下一步交给谁底层全部基于消息驱动和异步运行时。消息驱动的核心价值是解耦。每个智能体只负责处理自己收到的消息然后产出一条新消息至于这条消息下一个被谁看到由运行时和调度策略决定。这种设计让你可以随意替换模型、增删智能体而不用重写整个调用链。我更愿意把它看作是一个“多智能体操作系统”而不是一个聊天库智能体是进程消息是进程间通信Team 是调度器Termination Condition 是 PLC 里的急停按钮。2. 环境准备与一个最小可运行的 AgentChat 对话 Demo2.1 安装依赖与模型接入方式选择先跑起来比什么都重要。当前 AgentChat 的代码主要分布在autogen-agentchat、autogen-core和autogen-ext这几个包里社区延续版本 AG2 也保留了完全兼容的导入路径。我的建议是统一安装避免后面导包时缺东缺西。pip install autogen-agentchat autogen-ext如果是 AG2 系也可以pip install ag2装完之后确认 Python 版本最好用 3.10 以上。AgentChat 的 API 全面拥抱异步asyncio是标配版本太低会遇到一堆协程兼容问题。模型接入有两种主流方式。一是走 OpenAI 兼容接口把OpenAIChatCompletionClient的base_url指向云端 API 或任何本地推理服务二是本地部署 Ollama 之类的推理引擎同样暴露一个/v1兼容端点。这里我先用本地模型演示因为不涉及密钥配置最适合当第一个 Demo。2.2 最小化多智能体对话一跑就通的完整代码下面这段代码是我测试环境里跑通过的最小版本一个用户代理加一个助手代理轮流发言最多 6 条消息后自动终止。import asyncio from autogen_agentchat.agents import AssistantAgent, UserProxyAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import MaxMessageTermination from autogen_ext.models.openai import OpenAIChatCompletionClient # 1. 模型客户端这里指向本地 Ollama 的 OpenAI 兼容端点 model_client OpenAIChatCompletionClient( modelqwen2.5:14b, base_urlhttp://localhost:11434/v1, api_keyollama, ) # 2. 助手智能体负责具体回答 assistant AssistantAgent( nameassistant, model_clientmodel_client, system_message你是一个高效的助手尽量给出简洁可执行的回答。, ) # 3. 用户代理模拟用户输入不需要人工介入 user_proxy UserProxyAgent( nameuser_proxy, model_clientmodel_client, human_input_modeNEVER, ) # 4. 团队轮流发言 最多6条消息终止 team RoundRobinGroupChat( [user_proxy, assistant], termination_conditionMaxMessageTermination(max_messages6), ) # 5. 运行一次任务 async def main(): result await team.run(task帮我写一个Python函数计算斐波那契数列第n项。) for msg in result.messages: print(f[{msg.source}] type{msg.type}) print(msg.content) print(- * 40) asyncio.run(main())这段代码跑通后你就拥有了一个最小的多智能体对话系统原型。整个框架的复杂度都被封装在team.run()这一行里消息如何流转、谁先发言、何时停止全部交给运行时处理。2.3 代码逐行拆解搞清楚每个对象在干什么OpenAIChatCompletionClient是模型接入层所有智能体共用同一个客户端。这里有个容易踩的坑如果多个智能体要使用不同的模型就为每个智能体创建各自的model_client而不是共用。AssistantAgent是核心执行者它接收消息、调用模型、生成回复或工具调用请求。system_message决定智能体的“人设”在多智能体场景里这个字段要写清楚该智能体的职责边界而不是写泛泛的“你是助手”否则三个智能体都会抢着做同一件事。UserProxyAgent在human_input_modeNEVER模式下会变成一个“触发源”只要轮到它发言就把 user 消息发送到团队里。如果不设置成 NEVER它会等待键盘输入适合调试但不适合自动化流水线。RoundRobinGroupChat是团队调度的最简单实现按成员列表顺序轮流发言。对应生产环境SelectorGroupChat更适合复杂任务它由 GPT-4 级别的模型来动态决定下一位发言者。MaxMessageTermination是最直接的终止条件这里的6意味着整个团队最多产生 6 条消息。在我实际调试里这个数字不能太保守否则任务还没做完就被喊停但也不能过大否则死循环时它会无限跑下去。3. 会话消息、终止条件与上下文记忆AgentChat 的三个核心概念3.1 消息类型多智能体之间的“通讯协议”消息是 AgentChat 里所有智能体之间传递的基本单位每条消息都带有source消息来源。我总结了一张表覆盖 90% 的开发场景消息类型触发者关键字段用途说明TextMessageAgent/UserProxysource, content最常见的文本消息智能体之间聊天的基本格式MultiModalMessageAgent/UserProxysource, content, images携带图片和多段内容适合视觉分析、截图理解ToolCallMessageAgentsource, tool_calls智能体请求调用某个工具工具名和参数都在这条消息里ToolCallResultMessage工具执行器source, content, tool_call_id把工具执行结果回传给智能体必须带tool_call_id配对StopMessageAgent/Teamsource, content终止信号Team 看到这类消息就停止本轮运行刚开始写多智能体应用时一个常见误区是只关注TextMessage忽略工具调用消息。一旦你的智能体要执行代码、查询数据库ToolCallMessage和ToolCallResultMessage就会成为主干。我在调一个数据清洗项目时遇到过智能体明明调用了统计分析工具但后续智能体拿不到结果一查发现是tool_call_id对不上模型无法把工具结果关联到前面的调用请求。理解消息类型本质上就是理解智能体之间的通讯协议。3.2 终止条件为什么对话一定要有“刹车”多智能体系统里最让人头疼的问题就是死循环两个智能体互相“嗯”“好的”来回客套几十轮停不下来。终止条件就是解决这个问题的。AgentChat 内置了几种常用条件我用过比较顺的是下面这几个MaxMessageTermination(max_messagesN)团队总消息数达到 N 就停最简单粗暴适合限定预算的场景。TextMentionTermination(APPROVE)只要某条消息里出现指定关键词就停适合“最终审核”环节。比如让审校智能体输出“已通过”团队立刻收工。TokenUsageTermination(max_token_usage...)总 Token 消耗达到阈值就停适合对成本敏感的线上环境。CombinedTermination组合多个条件满足任意一个就停。这些条件不仅能保护你不在调试时烧掉太多 Token也是一种“显式的任务完成信号”。如果你设计得当每个智能体完成职责后都会输出一个特定关键词终止条件会变得非常优雅且自然。3.3 会话与上下文避免 Token 爆炸的实践经验AgentChat 的team.run(task...)会把整轮会话放进一个ConversationThread会话线程里默认每次 run 之间不共享历史。这意味着如果你把任务切成多个run每个 run 都是“失忆”的需要用 memory 或重新注入上下文来保持连续性。这里有一条经验对于长任务不要把几十个步骤全部塞进一个run否则上下文窗口会很快被塞满模型后面的表现会肉眼可见地变差。我通常的做法是把大任务拆成几段每段用一次run关键结论通过TextMessage塞进下一轮的task参数里。还有一个容易被忽略的点每次team.run()返回的result.messages会包含所有消息如果你把这个列表原封不动地作为下一轮上下文就会发生上下文内容的指数级膨胀。每次只提取“最后一条有效总结”传下去而不是把整个聊天记录传下去这是 AgentChat 应用中控制 Token 的核心技巧。4. 实战用三个智能体协作完成一个数据分析任务4.1 场景拆解规划、执行、检查三个角色怎么分工多智能体协作能不能发挥作用关键在于任务拆解。我拿一个数据分析任务举例给定一组数据让系统计算平均值、方差并绘制直方图。传统单模型做法是让它直接写代码并“假装”运行结果经常出错。多智能体做法则是拆成三个角色规划者planner负责拆任务、制定步骤它不写不跑代码。执行者coder负责把规划变成具体代码并通过代码执行器真实运行。审核者critic负责检查前两步的输出发现错误就反馈给规划者重新处理。这三个角色构成一个小型协作闭环各自职责清晰不容易出现“一个大模型既写代码又核对却没人把关”的情况。这里的核心思想是把“质量反馈”做成显式的智能体而不是依赖模型单轮推理里隐含的自我纠错。4.2 工具注册把外部能力挂到智能体上除了让智能体之间互相协作还需要让智能体具备外部能力比如执行代码、查数据库、调用内部 API。AgentChat 里注册工具非常简单写一个普通的 Python 函数加上类型注解和 docstring然后放进tools列表。from typing import Annotated def sum_values(numbers: Annotated[list, 整数列表]) - int: 计算整数列表的总和。 return sum(numbers) assistant AssistantAgent( nameassistant, model_clientmodel_client, tools[sum_values], )docstring 很重要。模型就是靠 docstring 来理解什么时候调用这个工具、传什么参数的。参数类型用Annotated标注清楚模型就能自动生成正确的工具调用。如果你注册的函数 docstring 写得太模糊模型会经常“猜错参数”甚至拒绝调用。4.3 完整代码与运行效果解读三智能体完整代码我贴在下面你可以直接复制跑。这里用CodeExecutorAgent接本地命令行执行器真实运行智能体生成的 Python 代码。import asyncio from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import MaxMessageTermination from autogen_agentchat.code_executors import LocalCommandLineCodeExecutor from autogen_ext.models.openai import OpenAIChatCompletionClient model_client OpenAIChatCompletionClient( modelgpt-4o-mini, api_keyYOUR_API_KEY, ) code_executor LocalCommandLineCodeExecutor(work_dirtmp_agent_work) planner AssistantAgent( nameplanner, model_clientmodel_client, system_message你负责拆解数据分析任务规划步骤但不直接执行代码。, ) coder CodeExecutorAgent( namecoder, code_executorcode_executor, ) critic AssistantAgent( namecritic, model_clientmodel_client, system_message你负责检查前序结果指出错误并给出修复建议。, ) team RoundRobinGroupChat( [planner, coder, critic], termination_conditionMaxMessageTermination(max_messages12), ) async def run_analysis(): task 对数组[3,1,4,1,5,9,2,6]求平均值和方差并绘制直方图保存为hist.png result await team.run(tasktask) return result result asyncio.run(run_analysis()) for msg in result.messages: print(f[{msg.source}] {msg.type}: {msg.content})实际运行时会看到这样的流程planner 先给出分析步骤coder 编写并执行 Python 代码critic 检查输出和图表是否合理如果没有问题任务在 12 条消息内完成。遇到错误时critic 会指出代码中的问题planner 会修正方案coder 再重跑这个“试错-修正”循环正是多智能体系统比单模型更稳的地方。我个人的体会是critic 这个角色是最容易被省略、但价值最大的一环。很多数据分析场景下代码“能跑”不等于“跑得对”。加了独立的审核智能体后很多统计口径错误在早期就被拦下来了。5. 模型接入与本地化部署选型从 API 到 Ollama5.1 OpenAI 兼容接口一个 base_url 打通一切AgentChat 的模型接入层做了很好的抽象几乎所有推理服务都可以通过 OpenAIChatCompletionClient 接入只是base_url不同。我用过云端 API、本地 Ollama、还有公司内部部署的推理网关代码改动量只有一行。# 云端 API model_client OpenAIChatCompletionClient( modelgpt-4o, api_keysk-xxx, ) # 本地 Ollama model_client OpenAIChatCompletionClient( modelqwen2.5:14b, base_urlhttp://localhost:11434/v1, api_keyollama, )这个设计让你可以先用云端模型完成原型验证再平滑切换到本地模型而无须改业务代码。我在开发阶段就用本地模型跑通多智能体调度最后上线时切到云端模型整体迁移成本几乎为零。5.2 本地部署的取舍与模型选择建议本地部署大语言模型在 2026 年已经非常成熟Ollama 是最容易上手的选择之一一条命令就能拉起服务。它的优点是数据不出内网、调用延迟可控、没有按 Token 计费的压力劣势是模型能力受限尤其复杂推理和代码生成方面本地小模型的短板比较明显。以我实测的经验Ollama 上跑qwen2.5:14b和llama3.1:8b都能完成基础的多智能体对话调度但在“需要审校者检查代码逻辑”这种场景里小模型经常漏判问题。建议策略是本地模型用于跑通流程和日常低复杂度任务关键任务切云端强模型用CombinedTermination控制成本。5.3 关键参数的调优经验OpenAIChatCompletionClient 的常见参数包括temperature、max_tokens、timeout。在多智能体场景里我一直不建议把 temperature 调太高一旦超过 1.0多个智能体之间的行为会不可预测容易出现计划之外的“自由发挥”。我常设置为 0.2 到 0.5 之间保证输出稳定又不至于完全机械。max_tokens也很有讲究。AssistantAgent 回复太短可能导致后续智能体拿不到足够上下文但设置过大会增加单轮延迟。最稳妥的做法是先设置 1024根据实际输出截断情况逐步调整。调试期间建议把timeout设大一些本地模型推理本来就慢默认超时太短会导致误报超时错误。一个容易被忽略的外部因素是并发。AgentChat 是异步框架多个 Team 可以并行运行但如果底层模型服务不支持并发请求需要加锁或队列。Ollama 默认并发能力有限我曾在并行跑三个任务时把本地服务打崩后来限制为串行或复用同一个 model_client 才稳定下来。6. 常见问题与排查技巧实录6.1 五个高频故障及解决思路多智能体框架调试起来比单模型链路复杂得多因为问题可能出在模型、调度、工具、终止条件任意一环。我把高频问题整理成一张速查表现象可能原因排查与解决对话一直不结束终止条件不匹配检查 TextMentionTermination 的关键词是否被模型实际输出临时把 MaxMessageTermination 调小上下文超长报错消息轮次过多、历史重复传递拆分任务为多次 run只传摘要配置 TokenUsageTermination工具调用不产生效果参数类型不匹配、docstring 模糊检查 ToolCallResultMessage 的 tool_call_id 是否配对用 Annotated 明确参数类型UserProxyAgent 卡住human_input_mode 设置为 ALWAYS自动化场景改为 NEVER或使用触发式消息多团队运行互相干扰多个 Team 共用可变状态确保每个 Team 使用独立实例必要时为每个任务创建新 Team6.2 针对多智能体死循环的三种实用刹停方案死循环是多智能体对话里最常见的“事故现场”我至少有三次是在吃火锅时手机收到账单预警才发现跑了几百条消息。后来我总结出三层刹停机制第一层是硬限制。MaxMessageTermination(max_messages20)是保底防线无论如何都不会烧穿预算。第二层是语义刹车。给每个智能体约定一个“完成词”比如审核者输出“APPROVED”时触发TextMentionTermination这是最符合业务直觉的终止方式。第三层是 Token 刹车。TokenUsageTermination适合在无限次修复循环中使用比如目标 Token 上限设为 20000超过立刻停止。这三层同时启用时即使某个智能体行为失控系统也能在小时级别内自动收住而不是无限跑下去。实际生产环境里我还建议把team.run()包一层超时控制比如asyncio.wait_for(team.run(...), timeout300)双保险。再提一个深度经验死循环的根源很多时候不是调度问题而是 system prompt 的边界不够清晰。两个智能体如果都被赋予了“总结”职责它们就会互相总结。每个智能体的系统提示词里明确写“不许做什么”和“完成标志”比堆砌一堆“你要积极主动”更有用。这套框架目前在我这边的多个场景里稳定跑了几个月包括数据报告自动生成、代码审查辅助、内部知识库问答等。根据我自己的经验第一次上手 AgentChat 最值得投入时间的不是研究 API 细节而是想清楚任务里到底要有哪几个角色、每个角色的输出是什么、谁来判断任务是否完成——这三件事想明白了代码写起来会非常快。最后分享一个小技巧每次调完一轮多智能体对话把result.messages序列化保存下来它就是一份天然的“AI 协作日志”做问题回溯的时候比什么 debug 工具都好用。