智能体项目复盘 · deepagents 篇:1 主 3 子架构、HITL、RAGFlow 接入,以及 16 个真实踩坑 智能体项目复盘 · deepagents 篇1 主 3 子架构、HITL、RAGFlow 接入以及 16 个真实踩坑前面几篇把大模型的基础盘、RAG 调参、低代码平台和私有化部署都过了一遍但那些内容有个共同上限一个 Agent 干所有事。这一篇讲的是另一条路——多智能体。课件是尚硅谷大模型智能体课程的04-多智能体项目_deepagents5 天时间从create_deep_agent()一行代码一路做到主智能体 3 个子智能体 FastAPI WebSocket Vue 前端 MySQL 查询 RAGFlow 知识库的完整深度搜索项目。但真正值得写的不是它能跑起来而是中间那 16 个坑为什么并发必须用 ContextVar 而不是全局变量、为什么流式解析要先过滤中间件节点、为什么教案里把 RAGFlow 说成字节开源、为什么子代理套子代理这条路走不通。这些内容才是一个项目从 Demo 到能上线的距离。1. 先把三层关系对齐LangChain、LangGraph、DeepAgents这是看这类课程最容易迷路的第一步三个东西都叫 agent 框架但它们不在同一层。课件给的分层说法我认为是全篇最清晰的一句层项目角色类比管什么FrameworkLangChain提供做动作的积木Spring模型适配、Prompt 模板、工具、toolRuntimeLangGraph提供跑流程的引擎SpringMVC 容器状态图、节点、边、checkpointer、StoreHarnessDeepAgents负责组织与调度SpringBoot Starter规划、子代理、虚拟文件系统、长期记忆、HITL你的业务代码 -- DeepAgents(Harness) -- LangChain(Framework) LangGraph(Runtime) -- 大模型 API简单理解LangChain 负责会做事LangGraph 负责按流程做事DeepAgents 负责把复杂的事拆给一队人做。课件用的版本锁得很死这套组合是配套演进的跨版本很容易炸依赖版本deepagents0.4.3langchain1.2.10langgraph1.0.9langgraph-checkpoint4.0.0langgraph-prebuilt1.0.8langchain-openai1.1.10fastapi/uvicorn0.129.2 / 0.41.0ragflow-sdk0.24.0前端Vue 3.5.24 TS 5.9 Vite被 override 成rolldown-vite7.2.5Q为什么不直接用 LangGraph 手搓一个因为 DeepAgents 帮你内置了四件你迟早要自己写的事。课件把它总结为四大核心能力① write_todos -- 规划与任务分解配套 read/update/delete_todos ② 文件系统工具集 -- ls / read_file / write_file / edit_file用来把上下文卸载到文件防溢出 ③ task 工具 -- 生成子代理 上下文隔离 ④ LangGraph Store -- 跨 thread 的长期记忆其中 ② 是最容易被低估的一条。长任务真正的瓶颈不是模型不聪明是上下文塞不下——把中间结果写进文件只把路径留在对话里是这套框架最实用的设计。2. 多智能体什么时候该上什么时候不该上课件在这一节写得非常克制这很难得——大部分教程会直接开始教你建 5 个 agent。先给对比维度单体 Agent多智能体上下文全部堆在一个窗口注意力被稀释每个子代理只看自己该看的上下文隔离提示词越长越互相打架每个角色一份短提示词拆解方式靠模型自己排序分而治之成本线性Token 指数级失控可调试性尚可非确定性叠加调试噩梦课件因此给了两条很硬的规则三条入场铁律① 问题极度开放② 存在领域冲突不同角色对同一问题的最优解不同③ 需要多方向并行。一句工程铁律不建全链路追踪绝不上线。第二条我自己踩过深表认同——多智能体的 bug 长得不像 bug它长得像模型今天心情不好。架构模式上业界三条路也顺便理清了层级式 Orchestrator-Workers主代理派活、收结果 -- DeepAgents 走这条 网 络式 Network 任意两两通信 -- AutoGen 走这条 混 合式 角色分工 局部协商 -- CrewAI 走这条Q所以 deepagents 到底是不是多智能体框架更准确的说法是它是一个层级式指挥官模式的多智能体脚手架。子代理在框架里被统一暴露成一个叫task的工具主代理发出的调用长这样{name:task,args:{subagent_type:网络搜索助手,description:...}}也就是说“调用子代理这件事被降维成了调用一个工具”。这是 DeepAgents 最重要的一个设计取舍简单、可组合但也正是这个设计决定了它的一个硬限制——见下一节。3. 核心 API一个create_deep_agent就够了课件里 90% 的示例都从这一个函数出发。把它的参数认清框架就通了。fromdeepagentsimportcreate_deep_agent deep_agentcreate_deep_agent(modelllm,tools[internet_search],subagents[],system_prompt你是一个专家级的研究员...,)实际用到的全部参数来自课件的《DeepAgents 使用总结》参数作用备注model模型实例init_chat_model(model..., model_provideropenai, temperature0.1)system_prompt人设与规则项目里全部外置到prompts.ymltools主代理自己的工具subagents子代理列表见下checkpointer状态存储HITL 必需示例用InMemorySaver()interrupt_on人工介入白名单backend文件/记忆的落点缺省走 LangGraph state虚拟 FSstore跨 thread 长期记忆middleware中间件限流、自定义工具拦截skillsAgent Skills 目录必须先配FilesystemBackend子代理两种写法# 写法 1字典项目里三个子代理都是这个每个只有 8 行weather_agent{name:weather_helper,description:...,system_prompt:...,tools:[],}# 写法 2兼容层——把 LangGraph 图 / LangChain agent 包装进来fromdeepagentsimportCompiledSubAgent sub_agentCompiledSubAgent(namegraph_agent,description处理所有的业务逻辑,runnablecompile_graph)写法 2 有个强制约束图的 State 必须包含messages且带add_messagesreducer否则消息合并直接报错。Q流式输出怎么解析这是课件标注重点的部分也是最容易被劝退的部分。astream()的 chunk 只有四种语义A 模型决定调工具 -- B 工具返回结果 -- C 模型决定调子代理(nametask) -- D 最终回复而节点名只有model和tools两个 key。但要先加一道过滤否则会中途崩掉ifnotstateormessagesnotinstate:continue# 否则会被 {TodoListMiddleware.after_model: None} 之类崩掉框架内置的TodoListMiddleware、PatchToolCallsMiddleware会往流里塞自己的节点不认识的 key 一律跳过是多智能体流式解析的通用保命符。QHITL人工确认怎么接三个硬条件缺一个就静默失败条件说明必须配checkpointer状态要能挂起必须传thread_id且二次调用线程 id 必须完全一致二次invoke只能传Command(resume{decisions: [...]})不能再把 query 传进去decisions支持approve / reject / editedit要带edited_action: {name, args}并且数组顺序必须与被拦截的顺序一一对应。课件注释很坦白InMemorySaver仅用于测试生产建议换 Redis checkpointer。Q子代理能再套子代理吗不能。课件专门写了 CEO→CTO→Coder 的三层委派实验结论是当前版本不支持子代理再生成子代理字典式 subagent 硬写subagents键也没用原注释“没有这个属性硬写的dict 底层不识别”。多层级只能靠提示词强行约束。这一条直接决定了架构上限你能做的是两层1 主 N 子不是树。4. 项目全貌一个深度搜索产品的完整链路前面是零件这里是怎么装起来。项目定位企业知识 业务数据库 联网搜索三源合一的深度研究报告助手。Vue 前端(5173) --HTTP POST /api/task {query, thread_id}-- FastAPI(8000) --立即返回 started-- 前端 │ │ └────────────── WS /ws/{thread_id} 长连接 ◄────────────────────┘ │ asyncio.create_task(run_deep_agent) │ 主智能体项目经理人设只规划/委派/汇总不自己查数据 ├── task -- network_search_agent (Tavily) ├── task -- database_query_agent (MySQL 三工具) └── task -- knowledge_base_agent (RAGFlow) │ monitor 单例 contextvars 取当前 thread_id -- 定向 send_json 回对应 socket接口层一共 5 个设计得很朴素但都是必要的接口方法作用/api/taskPOST提交任务立即返回{status:started, thread_id}内部asyncio.create_task/api/uploadPOSTmultipart 上传到updated/session_{thread_id}//api/download?pathGET下载产物带路径穿越校验/api/files?pathGET递归列文件按 mtime 倒序/ws/{thread_id}WS事件回传收ping回pong前端断线 3 秒自动重连Q为什么提交任务和拿结果要分成两条通道因为一个深度搜索任务要跑几分钟。HTTP 请求只能立刻返回已受理过程事件tool_start/assistant_call/task_result靠 WebSocket 推。这里有个很值得记住的实现细节并发隔离只能靠ContextVar。全局变量会串台A 会话的文件写进 B 会话的目录而threading.local在 asyncio 单线程模型下完全失效——因为从头到尾就一个线程。api/context.py整个文件就是这段论证。同理ConnectionManager.loop要延迟到app.on_event(startup)里才set_loop()同 loop 用create_task跨线程/跨 loop 必须asyncio.run_coroutine_threadsafe否则报协程在错误的循环中运行。数据侧MySQL RAGFlow项选型细节业务库MySQL 8pharma_dbdrugs10 条 /inventory每药 3 批次 /sales_records外键ON DELETE CASCADE访问方式裸mysql.connector不是 ORMlist_sql_tables/get_table_data/execute_sql_query返回格式CSV 文本首行列头 逗号分隔RAGRAGFlowragflow-sdk 0.24.0检索与生成全在服务端完成本项目不做切块、不做向量检索Embeddingtext-embedding-v3Tongyi-Qianwen建库时显式指定向量存储Elasticsearch8.11.3可选 Infinity部署时需手工把 es 镜像标签改成这个版本号否则触发长时间重拉两个反直觉但很实用的决定一是 SQL 结果转 CSV 再喂给模型。模型对 CSV 的字段对齐理解比 JSON 稳尤其在列数多的时候——JSON 里字段名重复占 token模型反而更容易把值和列对错位。二是 RAG 完全外包。整个项目里没有一行 chunk/embedding 代码ragflow_tools.py只有两个toolget_assistant_list()拼出助手名称;功能介绍;关联知识库create_ask_delete(chat_name, question)走create_session → session.ask(streamTrue) → delete_sessions。Agent 只负责选哪个助手 问什么问题。这带来一个直接后果课件在prompts.yml里把它写成了硬规则知识库名和 description 必须写准因为主代理完全靠 description 决定调用哪个助手同时子代理被要求保留检索的全部信息不需要进行概括性总结防止子代理自作主张压缩上下文。5. 16 个坑清单这一节是我认为这份课件最值钱的地方全部来自代码注释和运行报错不是编的。#坑后果 / 解法1流式解析没过滤中间件节点{TodoListMiddleware.after_model: None}直接崩加continue守卫2HITL 二次调用又传了 query必须只传Command(resume...)且thread_id完全一致3字典 subagent 里写subagents键底层不识别静默失效多层委派走不通4LangGraph 图的 State 少了messagesadd_messages合并报错5在错误的 event loop 上跑 WS 协程用run_coroutine_threadsafeloop 延迟到 startup 设置6用全局变量 /threading.local存会话 id串台 / 完全失效只能用ContextVar7模型自己编路径/workspace、/mnt/data、/home/userpath_utils.py一张 12 行场景表兜底清洗Windows 无盘符要当相对路径session_abc/session_abc/要拍平8os.getenv(tavily_api_key)大小写不匹配取到Noneday01 示例真有这个 bugday04/05 才改对9rawflow/rag_config.py的.env路径算错一层分支永不命中全靠load_dotenv()回退掩盖10execute_sql_query无只读约束表名用 f-string 拼模型可执行任意 SQL。生产必须上只读账号 语句白名单11PDF 转换走win32com 本机装了 WordLinux/Mac 直接不可用requirements 里的xhtml2pdf/weasyprint是没接线的备胎12前端http://localhost:8000与http://127.0.0.1:8000混用/outputs/...是死链后端app.mount已注释真实下载走/api/download13提示词自相矛盾一处要求必须把工作目录告诉子代理另一处说不需要把文件地址告诉子智能体模型行为不可预测人设写成空调公司但数据是医药库角色-数据错配直接影响子代理选择14read_file_content的instruction参数收下后完全未用典型为提示词而写的假参数装饰器签名与函数体脱节15SKILL 放太多原注释“不是越多越好7-10多了模型也不会调用摆烂千万不要放重复功能的 SKILL选择困难”且文件夹名必须等于 SKILL.md 的name16限流中间件没配ModelCallLimitMiddleware(thread_limit, run_limit, exit_behaviorerror/end)wrap_tool_call自定义中间件是控制 Token 失控的唯一实用手段第 10 条值得单独强调给 Agent 一个能执行任意 SQL 的工具等价于把数据库读写权限交给了提示词注入。这是所有 text-to-SQL 项目的通病课件原样留着当教学生产环境绝对不能照搬。6. 顺手做个事实核查教案里有几处是错的这一节不在课程大纲里是我核对时发现的。写出来是因为如果你照抄教案会在面试或者文档里翻车。教案说法实际情况“RAGFlow 是字节跳动开源的 RAG 框架”不对。RAGFlow 是InfiniFlow项目的开源产品把Infinity解释成字节开源的高分辨率图像生成模型完全串了。在 RAGFlow 语境里Infinity 是它自带的可选向量/文档引擎与 Elasticsearch 二选一把Valkey说成缓存、消息队列Valkey 是 Redis 协议的分叉 KV 存储在 RAGFlow 里做队列/缓存但不是消息队列产品模型名qwen3-32b、qwen-max、qwen2.5-14b-instruct混用都是走 DashScope 的 OpenAI 兼容模式https://dashscope.aliyuncs.com/compatible-mode/v1model_provideropenai另外课程代码的.env与教案 md 里是明文 API KeyDashScope、Tavily、RAGFlow 三套。本文已全部脱敏成‹REDACTED-API-KEY›。这里顺带说一句课程资料是会被反复下载和转发的明文密钥写进.env示例就等于已经泄露了真实项目里这类文件必须进.gitignore用.env.example占位。最后总结DeepAgents 的定位要认准它不是新的 Agent 框架是 LangChain 之上、LangGraph 之上的Harness 层。它的价值是组织不是能力。一句话理解模型负责思考LangChain 负责做事LangGraph 负责跑流程DeepAgents 负责把活分给一队人。多智能体是成本换来的确定性上下文隔离、职责单一代价是 Token 指数级失控和非确定性调试。三条入场铁律问题足够开放 / 存在领域冲突 / 需要并行不满足就别上。架构上限是两层当前版本子代理不能再生成子代理。想搭树得自己在task工具之上重做。最实用的三个内置能力虚拟文件系统上下文卸载、interrupt_onHITL、CompositeBackend短期 state 长期 Store 本地文件混用。工程真正的难点不在 Agent在周边event loop 归属、ContextVar并发隔离、模型编路径的清洗表、WS 通道设计——这三样占了本项目一半以上的 bug。笔者后端 架构的判断是这套代码可以直接当多智能体入门 Demo看但不能当生产模板抄。具体不抄三条任意 SQL 工具、InMemorySaver、Windows-only 的 Word 转 PDF。真要上生产先补的是全链路追踪和只读数据通道而不是再加两个子代理。下一篇讲一个完整的落地项目——掌柜智库看 RAG 在真实业务系统里怎么切文档、怎么设计那 24 个.prompt文件。参考资料 致谢[1] DeepAgents - GitHub[2] LangChain 官方文档[3] LangGraph 官方文档[4] RAGFlow - GitHubInfiniFlow[5] 阿里云百炼 DashScope 兼容模式 - 官方文档[6] Tavily API - 官网[7] Vue 3 - 官网[8] FastAPI - 官网[9] [尚硅谷大模型智能体线上速成班 V2.0 · Day02《多智能体项目 deepagents》课件与源码]注文中所有 API Key 已脱敏版本号、端口、表结构等配置均来自课程交付代码属 2026 年课程快照实际依赖请以你本地pip freeze为准。