基于agency-agents构建多智能体协作系统:从核心概念到实战应用 最近在尝试构建一个多智能体协作系统时发现市面上虽然有不少框架但要么过于复杂要么功能不够灵活。直到我深入研究了msitarzewski/agency-agents这个开源项目它提供了一种清晰、模块化的方式来构建和管理智能体Agent让我眼前一亮。本文将带你从零开始全面解析agency-agents的核心概念、架构设计并通过一个完整的实战项目手把手教你如何用它来构建一个具备自主协作能力的智能体系统。无论你是想入门智能体开发还是希望为现有项目引入更灵活的自动化能力这篇文章都能为你提供一套可直接复用的解决方案。1. 背景与核心概念什么是智能体Agent与agency-agents在深入代码之前我们有必要厘清几个核心概念。在人工智能领域智能体Agent通常被定义为一个能够感知环境、进行决策并执行动作以实现特定目标的实体。它不仅仅是调用一个 AI 模型如 GPT而是一个包含记忆Memory、规划Planning、工具使用Tool Use等能力的完整系统。那么agency-agents是什么它是一个用 Python 编写的开源库旨在简化智能体的构建过程。它的核心思想是“将智能体视为可组合的模块”。与一些“大而全”的框架不同agency-agents提供了高度解耦的组件让你可以像搭积木一样自由组合不同的能力来创建智能体。它解决了什么问题模块化缺失许多框架将记忆、工具、规划逻辑紧耦合难以替换或升级单一组件。通信复杂在多智能体场景中智能体间的消息传递、协作逻辑编写起来很繁琐。状态管理困难智能体的对话历史、知识库等状态如何持久化和隔离是常见的痛点。agency-agents通过清晰的抽象如Agent、Tool、Memory、Channel和松耦合的设计让开发者能专注于智能体的业务逻辑而非底层通信机制。常见应用场景自动化工作流例如一个智能体读取邮件分析内容后调用另一个智能体在日历中创建会议。多专家协作系统构建具有不同专业领域如代码生成、文案写作、数据分析的智能体让它们共同完成复杂任务。游戏 NPC为游戏中的非玩家角色赋予更复杂的决策和行为树。研究与实验平台快速原型化新的智能体架构或交互模式。2. 环境准备与版本说明在开始实战之前请确保你的开发环境已就绪。本文将使用 Python 作为主要语言。操作系统: Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04) 均可。Python: 推荐使用 Python 3.9 或更高版本。你可以通过python --version检查。包管理工具: 使用pip进行安装。IDE: 推荐使用 VSCode 或 PyCharm它们对 Python 有很好的支持。首先创建一个干净的虚拟环境来隔离项目依赖这是一个非常重要的最佳实践。# 创建项目目录并进入 mkdir agency-agents-demo cd agency-agents-demo # 创建 Python 虚拟环境 (以 venv 为例) python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate激活后你的命令行提示符前应该会出现(venv)字样。接下来安装agency-agents库。由于它是一个较新的项目我们直接从其 Git 仓库安装。同时为了给智能体提供“大脑”我们需要一个 LLM大语言模型后端。这里我们使用 OpenAI 的 API你也可以替换为其他兼容 OpenAI 接口的模型如本地部署的 Ollama。# 安装 agency-agents pip install githttps://github.com/msitarzewski/agency-agents.git # 安装 OpenAI Python SDK这是 agency-agents 与 GPT 模型通信所必需的 pip install openai # 可选安装 python-dotenv 来管理环境变量推荐 pip install python-dotenv版本说明agency-agents: 本文基于撰写时的最新主分支代码。开源项目迭代较快核心概念稳定但具体 API 可能有细微调整请以官方文档为准。openai: 版本 1.0.0。注意 OpenAI SDK 在 1.x 版本有重大更新。其他依赖将由agency-agents自动处理。项目结构预览 在开始编码前我们先规划一下项目结构这有助于保持代码清晰。agency-agents-demo/ ├── .env # 存储敏感信息如 API Key ├── .gitignore # Git 忽略文件 ├── requirements.txt # 项目依赖列表 ├── main.py # 主程序入口 ├── agents/ # 智能体模块目录 │ ├── __init__.py │ ├── writer_agent.py # 写作智能体 │ └── coder_agent.py # 编程智能体 ├── tools/ # 工具模块目录 │ ├── __init__.py │ └── calculator_tool.py # 自定义工具示例 └── memory/ # 记忆模块目录可选 └── __init__.py3. 核心架构与组件拆解agency-agents的威力源于其简洁而强大的抽象。让我们逐一拆解其核心组件理解“为什么这样设计”。3.1 智能体 (Agent)Agent类是核心。一个智能体至少需要一个名字 (name)用于标识。一个系统提示词 (system_prompt)定义它的角色、能力和行为准则。一个模型 (model)即 LLM 的配置告诉它使用哪个 AI 模型进行思考。工具列表 (tools)智能体可以调用的函数集合。关键设计Agent本身不处理与 LLM 的通信细节它只定义“谁”和“能做什么”。实际的 LLM 调用由Model组件负责这实现了控制反转IoC使得更换模型比如从 GPT-4 换到 Claude变得非常容易。3.2 工具 (Tool)Tool是智能体与外部世界交互的桥梁。任何 Python 函数只要加上tool装饰器就可以被智能体发现和调用。框架会自动处理函数描述的生成、参数的 JSON Schema 转换以及调用。为什么需要工具LLM 本身是“纯思考”的它需要工具来执行具体操作如计算、搜索、读写文件、调用 API 等。3.3 记忆 (Memory)Memory组件负责存储和检索智能体的对话历史、知识等。agency-agents内置了简单的对话历史记忆。你也可以实现自定义的Memory类例如连接到向量数据库如 Chroma, Pinecone来实现长期记忆和语义检索。记忆的重要性没有记忆的智能体就像金鱼每次对话都是新的。记忆使其能够进行连贯的多轮对话并基于历史信息做出决策。3.4 通道 (Channel) 与空间 (Space)这是实现多智能体协作的关键抽象。Channel: 可以理解为一条通信线路如一个 Slack 频道、一个微信群。智能体加入同一个Channel后就可以相互发送和接收消息。Space: 是一个运行环境管理着智能体和通道的生命周期。你可以把Space想象成一个“房间”里面有不同的“讨论组”Channel智能体们在这些组里交流。这种设计使得智能体间的协作模式非常灵活可以是一对一私聊也可以是多对多的群组讨论。3.5 模型 (Model)Model封装了与具体 LLM 提供商如 OpenAI, Anthropic的交互细节。它接收智能体的提示词调用 API并返回解析后的响应。通过配置不同的Model你可以轻松切换底层的大模型。4. 完整实战案例构建一个写作与编程智能体协作系统现在我们将理论付诸实践。我们的目标是创建两个智能体一个写作助手Writer和一个代码专家Coder。Writer 负责构思内容大纲Coder 负责将大纲实现为具体的代码比如一个简单的网页。它们需要通过协作来完成“创建一个介绍 Python 的网页”这个任务。4.1 项目初始化与配置首先创建.env文件来安全地存储你的 OpenAI API Key。# 在项目根目录下创建 .env 文件 echo OPENAI_API_KEY你的实际API密钥 .env重要请将你的实际API密钥替换为你从 OpenAI 平台获取的有效密钥。确保.env文件已被添加到.gitignore中避免密钥泄露。然后创建requirements.txt文件记录依赖。openai1.0.0 python-dotenv1.0.0 # agency-agents 通过 git 安装通常不直接写在 requirements.txt 里但可以备注 # githttps://github.com/msitarzewski/agency-agents.git4.2 创建自定义工具让我们先为 Coder 智能体创建一个简单的工具用于“创建文件”。在tools/calculator_tool.py旁边我们创建file_tool.py。# file: tools/file_tool.py import os from agency_agents import tool tool def create_file(filepath: str, content: str) - str: 在指定路径创建或覆盖一个文件并写入内容。 Args: filepath (str): 要创建的文件的路径例如 ./output/index.html。 content (str): 要写入文件的内容。 Returns: str: 操作结果信息例如 文件创建成功 或错误信息。 try: # 确保目录存在 os.makedirs(os.path.dirname(filepath), exist_okTrue) with open(filepath, w, encodingutf-8) as f: f.write(content) return f文件 {filepath} 创建成功。 except Exception as e: return f创建文件时出错: {str(e)} # 再创建一个简单的计算器工具供 Writer 或 Coder 在需要时使用 tool def calculator(a: float, b: float, operation: str) - float: 执行简单的数学运算。 Args: a (float): 第一个数字。 b (float): 第二个数字。 operation (str): 运算类型支持 add, subtract, multiply, divide。 Returns: float: 运算结果。 if operation add: return a b elif operation subtract: return a - b elif operation multiply: return a * b elif operation divide: if b 0: raise ValueError(除数不能为零) return a / b else: raise ValueError(f不支持的运算: {operation})4.3 定义智能体接下来我们分别定义 Writer 和 Coder 智能体。# file: agents/writer_agent.py from agency_agents import Agent from openai import OpenAI import os from dotenv import load_dotenv load_dotenv() # 加载 .env 中的环境变量 # 首先创建一个 Model 实例指向 OpenAI 的 GPT-4 # 注意这里使用了 OpenAI SDK 1.x 的写法 client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) # 定义一个简单的 Model 包装类agency-agents 未来可能会提供更官方的集成 from agency_agents import Model class OpenAIModel(Model): def __init__(self, model_namegpt-4-turbo-preview): self.model_name model_name self.client client def generate(self, messages): # 将 agency-agents 的消息格式转换为 OpenAI 格式 openai_messages [] for msg in messages: # 这里简化处理实际应根据 agency_agents 的 Message 对象结构调整 # 假设 msg 有 ‘role‘ 和 ’content‘ 属性 openai_messages.append({role: msg.role, content: msg.content}) response self.client.chat.completions.create( modelself.model_name, messagesopenai_messages, temperature0.7, ) # 返回 Assistant 的消息内容 return response.choices[0].message.content # 创建 Writer Agent writer_model OpenAIModel(gpt-4-turbo-preview) writer Agent( nameWriter, system_prompt你是一个专业的写作助手擅长将复杂的想法拆解为清晰、有条理的大纲和描述。你的输出应该结构清晰要点明确为后续的代码实现提供直接指导。, modelwriter_model, # Writer 暂时不需要特定工具如果需要可以添加 calculator tools[], # 可以从 tools 模块导入 calculator )# file: agents/coder_agent.py from agency_agents import Agent from .writer_agent import OpenAIModel # 复用同一个 Model 类 from tools.file_tool import create_file, calculator import os # 创建 Coder Agent coder_model OpenAIModel(gpt-4-turbo-preview) # 可以使用不同模型这里用同一个 coder Agent( nameCoder, system_prompt你是一个全栈开发专家精通 HTML, CSS, JavaScript 和 Python。你能根据详细的内容大纲快速生成简洁、规范、可运行的代码。你会使用 create_file 工具来保存你的代码成果。, modelcoder_model, tools[create_file, calculator], # Coder 拥有创建文件和计算工具 )4.4 创建协作空间并运行任务现在让我们创建一个主程序将两个智能体放入同一个空间并启动它们的协作。# file: main.py import asyncio from agency_agents import Space, Channel from agents.writer_agent import writer from agents.coder_agent import coder import os from dotenv import load_dotenv load_dotenv() async def main(): # 1. 创建一个协作空间 space Space() # 2. 在空间中创建一个频道可以把它想象成一个“项目会议室” project_channel Channel(namewebpage-project) space.add_channel(project_channel) # 3. 将 Writer 和 Coder 智能体加入到这个频道 # 这样它们就能听到频道里的所有消息并对彼此做出反应 await space.add_agent_to_channel(writer, project_channel) await space.add_agent_to_channel(coder, project_channel) # 4. 定义初始任务并指定由 Writer 开始处理 initial_task 任务创建一个介绍 Python 编程语言的单页网站。 要求 1. 页面需要包含 Python 的简介、主要特点、一个简单的代码示例。 2. 设计简洁美观适合初学者阅读。 3. 最终产出为一个 index.html 文件。 请 Writer 先制定一个详细的内容大纲和设计要点。 print( 任务开始 ) print(f任务描述:\n{initial_task}\n) print(- * 50) # 5. 将任务作为一条消息发送到频道并指定发送者为“用户”User # 也可以不指定 sender框架会有默认处理 initial_message project_channel.create_message(roleuser, contentinitial_task) # 6. 触发智能体的协作流程 # 这里我们采用一种简单方式让 Writer 先回复然后 Coder 基于 Writer 的回复继续工作。 # 更复杂的协作如自动接力需要定义更精细的 Agent 行为逻辑或使用 Workflow 组件。 # 首先获取 Writer 对任务的理解和计划 print(【Writer】正在思考...) writer_response await writer.react_to_message(initial_message, project_channel) print(f【Writer】说\n{writer_response.content}\n) print(- * 50) # 将 Writer 的回复作为新消息放入频道 writer_message project_channel.create_message(roleassistant, contentwriter_response.content, senderwriter.name) # 然后让 Coder 基于 Writer 的大纲来生成代码 print(【Coder】正在基于大纲编写代码...) coder_response await coder.react_to_message(writer_message, project_channel) print(f【Coder】说\n{coder_response.content}\n) print(- * 50) # 注意在实际的 agency-agents 高级用法中可以通过设置 Agent 的 loop 或 policy # 来自动化这个“监听-反应”的过程。这里为了演示清晰我们手动控制了两轮对话。 print( 任务阶段完成 ) print(请检查 ./output 目录下是否生成了 index.html 文件。) if __name__ __main__: asyncio.run(main())4.5 运行与结果在终端中运行主程序python main.py你将看到类似下面的输出展示了两个智能体的“对话”和思考过程 任务开始 任务描述: 任务创建一个介绍 Python 编程语言的单页网站。 要求 1. 页面需要包含 Python 的简介、主要特点、一个简单的代码示例。 2. 设计简洁美观适合初学者阅读。 3. 最终产出为一个 index.html 文件。 请 Writer 先制定一个详细的内容大纲和设计要点。 -------------------------------------------------- 【Writer】正在思考... 【Writer】说 好的我将为“介绍Python编程语言的单页网站”制定一个详细的内容大纲和设计要点。 **一、内容大纲** 1. **页首 (Header)** * 网站主标题Python - 简洁强大的编程语言 * 副标题适合初学者入门也是专家级开发者的利器 * 简洁的导航菜单锚点链接首页 | 简介 | 特点 | 示例 | 资源 2. **简介部分 (Introduction)** * Python 是什么通用、高级、解释型语言。 * 创建者Guido van Rossum1991年首次发布。 * 设计哲学优雅、明确、简单“Python之禅”。 * 主要应用领域Web开发、数据分析、人工智能、自动化、科学计算等。 3. **主要特点部分 (Key Features)** * **易于学习阅读**语法接近英语缩进定义代码块。 * **解释型语言**无需编译快速迭代。 * **跨平台**可在 Windows, macOS, Linux 上运行。 * **丰富的标准库**“内置电池”哲学。 * **庞大的生态系统**PyPI 上有数十万个第三方库。 * **社区支持**庞大活跃的社区资源丰富。 4. **代码示例部分 (Code Example)** * 示例1经典的 print(Hello, World!)。 * 示例2定义一个函数计算斐波那契数列展示 Python 的简洁性。 * 示例3使用 requests 库获取网页内容需说明是第三方库。 * 每个示例配以简短说明和输出预览。 5. **页尾 (Footer)** * 鼓励语开始你的 Python 之旅吧 * 有用的链接Python 官网、官方文档、PyPI、学习平台如 Codecademy, Coursera。 * 版权信息。 **二、设计要点** 1. **配色方案** * 主色调Python 标志性的蓝色 (#3776AB) 和黄色 (#FFD43B)。 * 背景浅灰色 (#f8f9fa) 或白色。 * 文字深灰色 (#333333)。 2. **字体** * 标题使用无衬线字体如 Segoe UI, Roboto, -apple-system显得现代。 * 正文同上或使用衬线字体如 Georgia 提升可读性用于长段落。 3. **布局** * 单列流式布局居中显示在移动端和桌面端都有良好体验。 * 各部分之间有足够的留白。 * 代码示例区域使用等宽字体如 Consolas, Monaco, Courier New背景色为深色如 #282c34高亮显示语法。 4. **交互** * 导航菜单平滑滚动到对应章节。 * 代码示例可以有一个“复制”按钮通过少量JS实现。 * 响应式设计适配手机和平板。 这个大纲为 Coder 提供了清晰的结构和视觉指导可以直接用于编写 HTML/CSS/JS 代码。 -------------------------------------------------- 【Coder】正在基于大纲编写代码... 【Coder】说 我将根据 Writer 提供的大纲和设计要点开始创建网站。首先我需要创建 HTML 结构然后添加 CSS 样式最后实现简单的交互。 我将使用 create_file 工具来生成 index.html 文件。这个文件将包含内联的 CSS 和 JavaScript 以实现一个完整的单页应用。 思考我需要生成一个完整的 HTML 文件。内容要包含大纲中的所有部分并应用设计要点中的配色和布局。我会先构建 HTML 骨架然后填充内容最后添加样式和脚本。 让我开始创建文件。 调用工具create_file 工具调用: create_file(filepath./output/index.html, content!DOCTYPE html\nhtml langen\nhead\n meta charsetUTF-8\n meta nameviewport contentwidthdevice-width, initial-scale1.0\n titlePython - 简洁强大的编程语言/title\n link relstylesheet hrefhttps://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\n style\n /* CSS 内容将在这里 */\n /style\n/head\nbody\n !-- HTML 内容将在这里 --\n script\n // JavaScript 内容将在这里\n /script\n/body\n/html) 工具返回: 文件 ./output/index.html 创建成功。 文件已创建成功。现在我需要填充具体的 CSS 和 HTML 内容。由于内容较长我将分步骤进行。首先我将用更完整的样式和结构替换文件内容。 调用工具create_file ... (后续会看到 Coder 多次调用 create_file 工具最终生成完整的 HTML 文件)运行完成后检查项目根目录下的./output文件夹你应该能看到一个index.html文件。用浏览器打开它一个根据 Writer 智能体的大纲、由 Coder 智能体自动生成的 Python 介绍网页就呈现在眼前了。5. 常见问题与排查思路在实践过程中你可能会遇到一些问题。以下是常见问题的排查指南。问题现象可能原因排查步骤与解决方案导入错误ModuleNotFoundError: No module named agency_agents1.agency-agents未正确安装。2. 虚拟环境未激活或 IDE 未使用正确解释器。3. 包名引用错误。1. 确认虚拟环境已激活 ((venv)前缀)。2. 重新运行pip install githttps://github.com/msitarzewski/agency-agents.git。3. 在 Python 交互环境中尝试import agency_agents测试。OpenAI API 错误AuthenticationError或InvalidRequestError1.OPENAI_API_KEY环境变量未设置或错误。2. API Key 已过期或额度不足。3. 请求的模型不存在或无权访问。1. 检查.env文件是否存在且格式正确无多余空格。2. 在代码中print(os.getenv(“OPENAI_API_KEY”))确认密钥已加载。3. 登录 OpenAI 平台检查密钥状态和余额。4. 确认model_name字符串正确如”gpt-4-turbo-preview”。智能体不响应或无输出1. 智能体未正确加入到Channel。2.model.generate方法实现有误未返回正确格式。3. 异步 (async/await) 调用错误。1. 检查space.add_agent_to_channel是否成功执行。2. 在OpenAIModel.generate方法中添加print语句调试输入和输出。3. 确保主入口使用asyncio.run(main())。工具调用失败1. 工具函数未用tool装饰器装饰。2. 工具函数参数类型提示不明确导致 Schema 生成错误。3. LLM 生成的调用参数格式错误。1. 确认函数上方有tool。2. 为函数参数和返回值添加明确的类型提示如str,int,List[str]。3. 打印出 LLM 决定调用工具时的中间 JSON 信息检查格式。多智能体协作混乱1. 所有智能体都在同一个频道里“同时”说话导致消息循环。2. 缺乏协调逻辑谁在什么时候发言。1. 使用更精细的Channel规划如一对一私聊频道广播频道。2. 为智能体实现policy函数定义其触发响应的条件例如仅当消息提到自己名字时才回复。3. 使用Space的run_task或手动控制对话流程如本文示例。6. 最佳实践与工程建议将agency-agents用于实际项目时遵循以下建议可以提升系统的稳定性、可维护性和性能。1. 智能体设计原则单一职责每个智能体应专注于一个明确的领域如写作、编程、审核。避免创建“全能”但逻辑复杂的智能体。清晰的系统提示词提示词是指引智能体行为的“宪法”。务必详细定义其角色、目标、约束和输出格式。好的提示词能大幅减少无效交互。工具粒度适中工具函数应完成一个具体的、原子性的操作。过于复杂的工具会让 LLM 难以正确调用。例如create_file比create_web_project更原子。2. 配置与安全管理永远不要硬编码密钥坚持使用.env文件和环境变量管理所有敏感信息API Keys、数据库连接串。模型配置隔离将Model的配置如base_url,api_key,model_name集中管理方便切换不同环境开发、测试、生产或不同供应商OpenAI, Azure, Anthropic。工具权限控制对于有潜在危险的工具如文件删除、数据库写入、网络请求应在工具函数内部实现严格的参数校验和权限检查。可以考虑为智能体分配不同的工具集。3. 状态与记忆管理对话历史持久化默认的内存可能只在会话中有效。对于需要长期记忆的应用实现自定义的Memory类将历史存储到数据库如 SQLite, PostgreSQL或向量数据库。记忆窗口限制LLM 有上下文长度限制。实现一个滑动窗口或摘要机制只保留最近 N 条消息或自动总结早期对话以避免 token 超限。智能体状态分离确保不同用户或会话的智能体状态是隔离的避免信息泄露。可以通过为每个会话创建独立的Agent和Memory实例来实现。4. 协作与流程编排定义明确的协作协议在多智能体系统中事先约定好通信协议。例如可以使用特定的消息格式如 JSON来封装任务描述、结果和元数据。引入协调者Orchestrator对于复杂工作流可以创建一个专用的“协调者”智能体。它的职责不是完成具体任务而是分解总任务、分配给专家智能体、收集结果并整合。错误处理与重试智能体调用工具或 LLM 可能失败。在Space或工作流引擎层面实现错误捕获、重试逻辑和降级方案例如让另一个智能体接手失败的任务。5. 性能与成本优化缓存 LLM 响应对于重复性或模板化的查询可以考虑缓存 LLM 的响应结果以降低 API 调用成本和延迟。使用更便宜的模型并非所有任务都需要 GPT-4。可以用 GPT-3.5-turbo 处理简单的分类、格式化任务将复杂的推理留给更强的模型。异步并发agency-agents基于异步 IO。当多个智能体可以并行执行独立任务时使用asyncio.gather来并发执行显著提升整体吞吐量。6. 测试与监控单元测试工具函数像测试普通 Python 函数一样为所有tool装饰的函数编写单元测试确保其功能正确。集成测试智能体交互模拟用户输入验证多智能体协作的端到端流程是否产生预期输出。添加日志与可观测性在关键节点如收到消息、调用工具、调用 LLM、发送回复添加详细的日志。这有助于调试复杂的交互和监控系统运行状态。通过遵循这些最佳实践你可以构建出不仅功能强大而且健壮、可扩展、易维护的智能体应用系统。agency-agents提供的模块化架构为这种工程化实践奠定了良好的基础。