news 2026/9/7 11:30:06

DeepAgents多智能体协作开发实战:从子智能体到异步任务编排

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DeepAgents多智能体协作开发实战:从子智能体到异步任务编排

这次我们不开箱玩具,直接聊一个真正决定 AI 工程上限的方向:多智能体协作。单个智能体解决单点问题很容易,但要让大模型真正承担一条业务流程,必须把多个智能体组织起来,让它们各自负责一段任务,再通过异步编排把结果汇总成最终产出。DeepAgents 就是围绕这个思路展开的多智能体协作开发框架,本文会从子智能体设计、harness 运行机制、异步任务编排三个层面,给出可落地的开发路径。

先给结论:这套方案的重点不是“多调用几次大模型”,而是把智能体之间的通信、调度、失败重试、并行执行和结果汇总做成一套工程化结构。文章里会包含核心概念梳理、通用代码模板、接口调用示例、批量任务设计,以及一套常见问题排查清单。如果你是做大模型应用开发、智能体平台、自动化流程建设的工程师,这篇文章可以直接收藏,按章节对照落实验证。

1. 核心能力速览

能力项说明
项目类型多智能体协作开发框架与应用方案
核心概念子智能体、harness、异步任务编排、工具调用
主要功能多角色智能体构建、任务拆分、并行调度、结果汇总、API 服务
模型要求通常需要接入具备工具调用能力的 LLM,如 DeepSeek、GPT 系列、Qwen 系列等
硬件需求调用云端 API 时无 GPU 硬性要求;本地部署需按模型大小评估显存
启动方式命令行脚本启动 / WebUI / API 服务,取决于具体实现
是否支持 API支持,可通过 HTTP 接口提交任务并获取结果
是否支持批量任务支持,可设计任务队列与并发执行器
适合场景内容生产、数据分析报告、代码审查、多步骤流程自动化、知识库问答管线
使用边界需要合法授权、数据合规、人工复核关键输出

需要注意,DeepAgents 的生态仍在快速变化,不同开源实现的目录结构、配置格式和接口路由可能存在差异。下面所有命令和代码均以“通用实现模板”给出,实际使用时请以你下载到的项目 README 为准,替换对应的路径、端口和模型名。

2. 适用场景与使用边界

2.1 这个方案适合谁

如果你手头有这些需求,多智能体协作就是值得投入的方向:

  • 内容生产流水线:采集素材、提炼要点、写稿、审校可以由不同智能体分工完成。
  • 数据分析报告:数据读取、指标计算、图表描述、报告生成逐级传递。
  • 代码仓库审查:一个智能体扫描变更,另一个智能体检查安全风险,再有一个智能体汇总修改建议。
  • 客服工单处理:意图识别、知识检索、回复生成、人工复核提示分层处理。
  • 知识库问答:检索增强、上下文压缩、答案生成、引用溯源分开管理。

2.2 不适合什么场景

  • 单次请求延迟要求极高的场景不适合把链路拆得太长,多智能体协作必然带来多次模型调用,端到端耗时会明显高于单次问答。
  • 完全离线且硬件受限的环境需要谨慎,本地跑多个模型需要足够的显存和内存。
  • 输出内容直接商用且不经过复核的场景风险很高,智能体生成内容不代表事实正确,必须有人工质检环节。

2.3 合规边界

涉及图像、声音、人物肖像、版权素材时,必须确认授权;涉及用户隐私数据时,要注意脱敏和访问控制;涉及金融、医疗、法律等领域结论时,绝不能把智能体输出当作最终依据。多智能体系统只是执行工具,责任边界在系统设计和业务方。

3. 先厘清四个关键概念

在写代码之前,把几个容易混淆的词说清楚,后面实操才不会卡壳。

3.1 什么是 DeepAgents

DeepAgents 是基于大模型的多智能体协作开发方案,核心思路是让一个“主智能体”负责理解用户任务、拆解子目标、调用不同的“子智能体”完成具体步骤,最后统一汇总输出。它强调的不是单个模型有多强,而是多个模型和工具如何被组织成一条可靠的任务链路。

3.2 什么是子智能体

子智能体是承担单一职责的智能体实例,每个实例可以有自己的系统提示词、工具集、模型参数和上下文窗口管理方式。比如“信息采集子智能体”只负责搜索和抓取,“报告撰写子智能体”只负责根据结构化素材生成文字。子智能体不应该堆砌任务,而是要“小而专”,方便复用和组合。

3.3 什么是 harness

harness 在直译上是“背带、控制装置”,在多智能体系统里通常指智能体的运行外壳和执行环境。你可以把大模型看作“大脑”,harness 就是负责把大脑的输入输出变成可执行动作的“身体”。它处理模型调用循环、工具解析、错误重试、上下文累积、状态管理等底层逻辑。开发多智能体应用时,大部分工程复杂度其实集中在 harness 层,而不是模型本身。

3.4 什么是异步任务编排

异步任务编排是指把多个智能体任务放入队列,通过调度器决定执行顺序、并发数量、依赖关系和结果回收,而不是同步地“等一个完成再开始下一个”。典型结构是:主智能体拆分任务 -> 任务入队 -> 工作进程并发处理 -> 结果按依赖关系合并 -> 最终输出。异步编排解决的是生产效率问题,多智能体系统的吞吐量上限往往由这一层决定。

4. 环境准备与前置条件

4.1 语言与运行时

多智能体开发最常见的语言是 Python,其次是 TypeScript。以下环境清单以 Python 为例:

  • Python 3.10 或更高版本。
  • pip 包管理器。
  • 能够访问大模型 API,并已准备好 API Key。
  • 本机可以访问外网,或者已配置可用的模型代理服务。

4.2 建议安装的核心依赖

pip install openai pydantic httpx python-dotenv

如果项目本身提供 requirements.txt,直接执行:

pip install -r requirements.txt

依赖安装失败时,优先检查 Python 版本和 pip 镜像源配置,不要贸然升级系统级 Python。

4.3 目录结构建议

一套清晰的项目目录可以避免后续批量任务和模型文件管理混乱:

deepagents-demo/ ├── agents/ # 子智能体定义 ├── core/ # harness 与编排核心 ├── tools/ # 自定义工具 ├── tasks/ # 任务队列与批量任务 ├── config/ # 模型配置、提示词配置 ├── outputs/ # 输出结果 └── main.py # 入口脚本

4.4 硬件门槛

如果使用云端模型 API,普通开发机即可运行,没有 GPU 硬性要求。如果要在本地部署模型并作为智能体后端,需要按模型参数量评估显存,建议先跑 7B 级别以下模型验证流程,再决定是否升级硬件。显存占用必须以实际砸测为准,不同量化方式、上下文长度和并发数差别很大。

5. 从单智能体到子智能体:先跑通最小流程

5.1 最小单智能体示例

下面这段代码建立一个最基础的单智能体循环。它做的事情是:接收用户输入、调用大模型、返回结果。

import os from openai import OpenAI client = OpenAI( api_key=os.getenv("LLM_API_KEY"), base_url=os.getenv("LLM_BASE_URL", "https://api.openai.com/v1"), ) def call_llm(messages, model="gpt-4o-mini", temperature=0.3): response = client.chat.completions.create( model=model, messages=messages, temperature=temperature, ) return response.choices[0].message.content.strip() if __name__ == "__main__": messages = [ {"role": "system", "content": "你是一个专业的写作助手。"}, {"role": "user", "content": "用三句话总结什么是异步任务编排。"}, ] result = call_llm(messages) print(result)

这个流程很简单,但它已经具备一个智能体的基本骨架:系统提示词决定角色,用户消息输入目标,模型返回输出。

5.2 把单智能体包装成子智能体

实际开发中,不能每次都手动拼 messages。建议把子智能体抽象成一个类,内部维护系统提示词和上下文策略。

class SubAgent: def __init__(self, name, system_prompt, tools=None, model="gpt-4o-mini"): self.name = name self.system_prompt = system_prompt self.tools = tools or [] self.model = model self.messages = [{"role": "system", "content": system_prompt}] def run(self, user_message): self.messages.append({"role": "user", "content": user_message}) # 这里调用 call_llm,可扩展到工具调用解析 answer = call_llm(self.messages, model=self.model) self.messages.append({"role": "assistant", "content": answer}) return answer

这里的关键是:每个子智能体都有自己的消息上下文。不要把不同角色的历史消息混在一起,否则角色边界会失效。

5.3 注册多个子智能体

假设我们要构建一个“行业调研报告生成器”,可以拆出三个子智能体:

collector = SubAgent( name="信息采集", system_prompt="你负责从给定资料中提取事实、数据和关键观点,输出结构化条目。", ) analyst = SubAgent( name="数据分析", system_prompt="你负责对结构化数据进行趋势判断、风险识别和结论归纳。", ) writer = SubAgent( name="报告撰写", system_prompt="你负责根据分析结果撰写正式报告,语言专业、结构清晰。", )

到这一步,三个子智能体还彼此独立。接下来要做的是通过一个主智能体或 harness 把这几个子智能体串起来。

6. 编写核心 harness:让智能体真正“动起来”

6.1 harness 要解决什么问题

harness 的核心工作是维护执行循环。一个最简单的 harness 需要做到:

  • 接收总任务。
  • 根据任务类型路由到对应子智能体。
  • 把子智能体的输出整理成结构化结果。
  • 保存执行历史,供后续调试和重试。

6.2 路由式 harness 示例

这里给出一个简单的路由式 harness,它根据任务关键词决定调用哪个子智能体。

class Harness: def __init__(self): self.agents = {} def register(self, agent: SubAgent): self.agents[agent.name] = agent def route(self, task_description: str): if "采集" in task_description or "搜索" in task_description: return self.agents["信息采集"] if "分析" in task_description or "趋势" in task_description: return self.agents["数据分析"] if "报告" in task_description or "撰写" in task_description: return self.agents["报告撰写"] raise ValueError("未匹配到合适的子智能体") def execute(self, task_description: str): agent = self.route(task_description) return agent.run(task_description)

这种路由方式适合任务类型固定的场景。更复杂的场景需要让“主智能体”自己决定调用哪个子智能体,也就是“LLM 路由”。LLM 路由需要模型输出结构化指令,例如 JSON 格式:

{ "agent": "数据分析", "input": "分析近三个月的销售趋势,判断是否进入下降周期" }

harness 解析这个 JSON,再调用对应子智能体。这样主智能体就成了“调度大脑”,子智能体成了“执行者”。

6.3 harness 与 agent 的区别

很多人问 harness 和 agent 到底什么关系。简单讲:agent 是具备推理和行动能力的智能体,harness 是承载 agent 运行的基础设施。一个完整的多智能体系统里,你可以有多个 agent,但通常只有一个 harness 负责调度、记录、重试和上下文压缩。开发时不要把这些职责混在同一个类里,拆分越清楚,越容易测试和扩展。

7. 多智能体协作开发:从串行到并发

7.1 串行流水线

最简单的多智能体协作是串行流水线,前一个智能体的输出作为后一个智能体的输入。

raw_material = collector.run("提取以下新闻中的关键数据:……") analysis_result = analyst.run(raw_material) report = writer.run(analysis_result)

串行方式逻辑清晰,适合步骤之间有严格依赖的场景。缺点是整体耗时长,如果某个环节失败,整条链路中断。

7.2 并行执行

有些子任务彼此独立,可以并发执行。比如报告需要同时包含市场分析、竞品分析和用户反馈三部分,三个子智能体可以并行处理。

import asyncio async def run_parallel(): tasks = [ collector.run("收集市场数据"), collector.run("收集竞品信息"), collector.run("收集用户反馈"), ] results = await asyncio.gather(*tasks) return results results = asyncio.run(run_parallel())

并行执行能显著提升吞吐量,但要注意模型 API 的并发限制和本地显存压力。

7.3 主智能体编排模式

更接近生产环境的模式是:主智能体先分析任务,生成执行计划,然后并行调度子智能体,最后收集结果并汇总。

class Orchestrator: def __init__(self, harness: Harness): self.harness = harness self.execution_log = [] def run(self, user_request: str): plan = self._generate_plan(user_request) partial_results = [] for step in plan["steps"]: result = self.harness.execute( f"{step['instruction']}\n上下文:{user_request}" ) partial_results.append(result) self.execution_log.append({ "step": step["agent"], "input": step["instruction"], "output": result, }) final = self._summarize(partial_results) return final

这里_generate_plan_summarize同样可以交给大模型完成,但不要忘记给模型提供清晰的输出格式约束。

8. 异步任务编排:队列、调度与失败重试

8.1 为什么需要异步任务编排

多智能体系统一旦进入生产环境,就不适合“同步等结果”了。用户提交任务后,系统应该立刻返回一个任务 ID,后台异步执行,执行完成后通过回调或查询接口返回结果。这种方式对长时间的批量任务尤其重要。

8.2 基于队列的任务编排模型

一个生产可用的异步编排模型包含这几个组件:

  • 任务提交接口:接收用户请求,生成任务 ID,入队。
  • 任务队列:保存待执行任务,可以是 Redis、RabbitMQ 或简单的内存队列。
  • 执行器:从队列拉取任务,调度子智能体执行。
  • 结果存储:保存执行状态和最终结果。
  • 查询接口:通过任务 ID 查询进度和结果。

8.3 内存队列快速原型

下面是一个基于 asyncio 的内存队列实现,演示多智能体任务如何异步执行。

import asyncio import uuid from dataclasses import dataclass, field @dataclass class AsyncTask: id: str = field(default_factory=lambda: str(uuid.uuid4())) payload: str = "" status: str = "pending" result: str = "" class AsyncOrchestrator: def __init__(self): self.queue = asyncio.Queue() self.tasks = {} async def submit(self, payload: str) -> str: task = AsyncTask(payload=payload) self.tasks[task.id] = task await self.queue.put(task) return task.id async def worker(self): while True: task = await self.queue.get() try: task.status = "running" task.result = await self._run_pipeline(task.payload) task.status = "completed" except Exception as err: task.status = "failed" task.result = str(err) finally: self.queue.task_done() async def _run_pipeline(self, payload: str): raw = await asyncio.to_thread(collector.run, payload) analysis = await asyncio.to_thread(analyst.run, raw) report = await asyncio.to_thread(writer.run, analysis) return report def get_task(self, task_id: str): return self.tasks.get(task_id)

启动异步编排服务的入口可以这么写:

async def main(): orch = AsyncOrchestrator() workers = [asyncio.create_task(orch.worker()) for _ in range(3)] task_id = await orch.submit("生成新能源汽车市场调研报告") while orch.get_task(task_id).status == "pending": await asyncio.sleep(1) print(orch.get_task(task_id)) asyncio.run(main())

需要注意,内存队列只适合开发和单机测试。生产环境建议换成 Redis/RabbitMQ,并加上持久化,避免进程重启导致任务丢失。

8.4 失败重试与超时控制

异步编排必须考虑失败重试。常见策略是:

  • 单个子智能体调用失败时,最多重试 2 到 3 次,重试间隔按指数退避。
  • 超过任务总超时时间后,标记任务失败,不再继续后续环节。
  • 记录每次重试的输入输出,方便排查是模型问题还是工具问题。
async def call_with_retry(func, *args, retries=3, delay=2): for attempt in range(retries): try: return await func(*args) except Exception as err: if attempt == retries - 1: raise await asyncio.sleep(delay * (2 ** attempt))

8.5 批量任务的目录设计

如果要做批量任务,比如一次性处理 100 篇文档,建议目录结构按批次隔离:

outputs/ ├── batch_20260912/ │ ├── task_001/ │ ├── task_002/ │ └── logs/ └── batch_20260913/

每个批量任务单独建目录,输入、中间结果、最终输出、日志分开存,即使某个任务失败也不会污染其他任务的结果。

9. 接口 API 与批量任务集成

9.1 提供 HTTP 接口

异步编排系统必须提供两个核心接口:提交任务和查询状态。下面是用 FastAPI 实现的通用模板。

from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() orch = AsyncOrchestrator() class TaskRequest(BaseModel): payload: str @app.post("/api/tasks") async def create_task(req: TaskRequest): task_id = await orch.submit(req.payload) return {"task_id": task_id, "status": "pending"} @app.get("/api/tasks/{task_id}") async def get_task(task_id: str): task = orch.get_task(task_id) if not task: return {"error": "task not found"} return {"task_id": task.id, "status": task.status, "result": task.result}

启动服务:

uvicorn main:app --host 127.0.0.1 --port 8000

9.2 curl 调用示例

提交任务:

curl -X POST http://127.0.0.1:8000/api/tasks \ -H "Content-Type: application/json" \ -d '{"payload": "生成2026年智能驾驶行业趋势报告"}'

查询任务:

curl http://127.0.0.1:8000/api/tasks/{task_id}

接口能跑通之后,就能很方便地接进自己的内部系统、企业微信机器人或自动化脚本里。

9.3 Python 调用示例

import requests import time base_url = "http://127.0.0.1:8000" def submit_and_wait(payload, timeout=600): resp = requests.post(f"{base_url}/api/tasks", json={"payload": payload}, timeout=30) task_id = resp.json()["task_id"] start = time.time() while time.time() - start < timeout: status = requests.get(f"{base_url}/api/tasks/{task_id}", timeout=30).json() if status["status"] in ("completed", "failed"): return status time.sleep(3) return {"task_id": task_id, "status": "timeout"} result = submit_and_wait("整理过去一年AI Agent领域的融资事件") print(result)

这里要注意,不同项目的接口路径和字段名可能不同,务必根据实际后端代码调整。

10. 资源占用与性能观察

10.1 需要观察哪些指标

多智能体系统的性能瓶颈通常不在“模型推理有多快”,而在以下几个方面:

  • 模型 API 调用延迟:每个子智能体都要调用一次模型,串行链路下总延迟是多次调用的叠加。
  • 上下文长度:多个智能体传递结果时,消息累积会导致上下文变长,吞吐量下降。
  • 并发数量:并发过高会被模型服务限流,并发过低则浪费资源。
  • 队列堆积数量:观察队列待处理数,能判断执行器是否成为瓶颈。

10.2 如何观察显存占用

如果本地部署模型,可以用nvidia-smi观察显存占用。

nvidia-smi --query-gpu=index,memory.used,memory.total,utilization.gpu --format=csv

不过需要再次强调,显存占用取决于模型大小、量化方式、上下文长度和并发数,不能凭经验拍脑袋。建议用小并发和小上下文先压测,再逐步放大。

10.3 如何降低资源占用

  • 优先使用云模型 API,把显存压力转移给服务端。
  • 子智能体之间只传递必要信息,不要整段复制大文本。
  • 对历史消息做截断或摘要,控制上下文膨胀。
  • 限制并发执行器数量,避免队列任务同时爆发。
  • 批量任务分批提交,每批完成后再提交下一批。

10.4 进程残留与端口冲突

开发时反复启动服务,容易遇到端口被占用的现象。Linux 和 macOS 下可以用:

lsof -i :8000

找到占用进程后,按需结束进程或更换端口:

uvicorn main:app --host 127.0.0.1 --port 8001

11. 常见问题与排查方法

问题现象可能原因排查方式解决方案
依赖安装失败Python 版本不符或镜像源问题查看 pip 报错信息切换 Python 版本或配置国内镜像源
模型接口返回 401API Key 无效或无权限检查环境变量重新配置 API Key 或检查服务权限
子智能体输出为空模型提示词不当或上下文超限打印原始返回结果精简提示词,缩短上下文
异步任务一直 pending执行器未启动或队列卡住检查 worker 进程和日志启动 worker,增加超时退出
批量任务中断任务无持久化检查队列是否内存态切换到 Redis/RabbitMQ
端口冲突上一次服务未关闭lsof 检查端口换端口或结束旧进程
结果质量不稳定链路太长,误差累积记录每个子智能体的输出增加中间结果人工抽检
本地显存不足模型过大或并发过高nvidia-smi 观察占用换小模型、量化或降并发

12. 最佳实践与使用建议

  • 第一版不要追求复杂。先跑通主智能体加两个子智能体的小链路,确认模型路由和结果传递没有断层,再扩展更多子智能体。
  • 每个子智能体必须有明确的输入输出格式约定。无论是 Markdown 标题还是 JSON 结构,都要固定下来,否则后续无法可靠解析。
  • 中间结果一定要落盘。每一步的输出保存到本地,既能调试,也能在最终结果出错时回溯是哪一步出的问题。
  • 批量任务必须加日志和失败重试。按批次写日志,记录任务 ID、输入摘要、输出摘要、耗时和错误信息。
  • API 服务对外暴露时要做好访问限制。内网环境也要加简单的 Token 鉴权,避免任意机器都能提交任务。
  • 涉及真实人物、品牌、版权内容时,务必确认授权。多智能体系统只是把流程自动化,不代表内容可以随意使用。
  • 商用之前必须有复核机制。让第二套模型或人工对最终输出做质量检查,不能把智能体结果直接发布。

13. 总结与下一步

DeepAgents 多智能体协作最值得花时间的地方,不是搭几个子智能体那么简单,而是把 harness 调度、异步队列、失败重试、结果汇总做成一套稳定的工程结构。建议你先从“主智能体 + 两三个子智能体 + 串行流水线”开始,跑通之后再引入并发和队列,最后再根据业务需要增加 HTTP 接口和批量任务。

最容易踩的坑是:子智能体职责不清、消息上下文混用、没有失败重试、中间结果不落盘。这四个问题几乎会在所有项目里遇到,尽早用工程手段解决,后面的开发会顺利很多。

下一步可以往两个方向扩展:一是把自定义工具接入 harness,比如让子智能体调用搜索、数据库、代码执行器等外部能力;二是尝试 MCP 协议来统一工具接入方式,让多智能体系统的工具生态更标准。等这两个方向都打通,你会发现多智能体已经从“演示项目”变成了真正能承载业务流程的生产工具。建议收藏备用,动手调试时对照本文的章节定位问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 11:28:59

CMSIS-DSP源码审计指南:从宏定义到工业级调优

写这份评测之前&#xff0c;我刚用新版 CMSIS-DSP 在一颗无浮点内核的 Cortex-M0 上调试完音频预处理&#xff0c;一个 128 点实数 FFT 跑出来的耗时比预期慢了将近 40%&#xff0c;最后发现不是库本身的问题&#xff0c;而是工程里缺少ARM_MATH_CM0定义&#xff0c;整个库走了…

作者头像 李华
网站建设 2026/9/7 11:28:40

AI编程真实水位线:一个人用AI辅助从零开发并上线SaaS报销系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:26:06

通达信抓涨停选股公式:源码拆解与实战调试全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 11:23:58

麻将厅3D建模全流程:从空间布局、灯光材质到渲染避坑指南

简介&#xff1a;一份面向3D建模初学者与室内场景设计师的麻将厅模型设计资源&#xff0c;可用于学习社交娱乐空间建模、比例把控与氛围渲染技巧。资源包为rar压缩格式&#xff0c;共3个文件&#xff0c;主要包含3ds Max模型源文件、模型预览图和HTM格式说明文档&#xff0c;整…

作者头像 李华