
第一次在 GitHub 上刷到 bytedance/deer-flow 这个仓库的时候我第一反应是字节跳动终于把内部跑得很顺的那套 AI 工作流编排能力开源出来了。老实讲2025 年喊“LLM 编排”的项目并不少但真正点开仓库、看完示例、自己动手部署一遍之后我被它的设计打动到了。它不是一个聊天机器人套壳也不是低代码拖拽平台而是把大模型、工具调用、人工审批、定时任务全部塞进一张有向无环图里让你用搭流程的方式把 AI 接入业务系统。这篇文章我就结合自己的实际使用经验从项目定位、核心概念、部署落地到流程搭建完整拆一遍 deer-flow希望能给正在做 AI 应用交付的团队和个人开发者一些参考。我先说结论如果你已经在用代码硬写多步 Agent 逻辑或者被各种“智能体平台”的封闭生态卡住deer-flow 值得花一个下午认真试一下。它解决的核心问题很简单——把 LLM 和工具之间的调用关系可视化、可复用、可运维。适合三类人一是需要交付复杂 RAG 或多步 Agent 应用的开发者二是想把 AI 流程交给业务方自助调整的团队三是像我一样喜欢在开源项目里挖思想和方法论的人。1. 项目整体认知与定位1.1 一个被低估的工作流编排引擎先把这个项目放在它正确的位置上。deer-flow 不是 Agent 框架也不算是完整的低代码应用平台它更像是一个深度面向 AI 流程的工作流编排引擎。你可以把它理解成“AI 时代的节点红”Node-RED各种能力单元被抽象成节点节点之间用连线定义先后顺序和数据传递方向最终整张图就是一个可运行的流程。在这个定位下它和大模型的关系是“编排者”而不是“宿主”。你可以把不同的模型供应商接到同一条流程里也可以让一个流程里既有 LLM 节点又有自定义 Python 脚本节点、HTTP 请求节点、条件判断节点。这种设计意味着你不必被某一家模型厂商绑定也不必把业务逻辑全部塞进 Prompt 里。我自己做过几个 AI 项目最深的体会是当业务方说要“加一个判断”“多一步人工审核”“换个模型试试”如果这些改动要重新部署代码那整个迭代节奏就被拖死了。deer-flow 的定位正好打在这个痛点上把流程的骨架从代码里抽出来变成画布上的图和结构化配置。代码仍然负责能力接入而流程逻辑回到配置层这两者分开之后后续的改动和维护都清爽很多。1.2 它真正解决的四个问题第一解决多步调用中的状态管理。单次 LLM 调用就是一个 request 的事但真实业务里经常是“先查知识库再让模型做摘要然后走人工审批通过后调用发送接口”。每一步的输入都依赖上一步的输出中间还有分支、循环、异常重试用代码写很快就会变成一团乱麻。deer-flow 把这种状态流转交给引擎管理你不用自己维护一堆中间变量。第二解决流程可视化。不是说画个图好看而是排查问题的时候太有用了。流程跑到哪一步、哪一步超时、哪一步返回了不符合预期的数据全部可以在界面上直观看到。对比以前看日志里一坨嵌套调用体验完全是两个级别。第三解决复用问题。同一个子流程可以拆出来反复使用比如“意图识别”“敏感词过滤”“格式化输出”做成通用子流程之后新的业务只要引用就行。这个能力在代码时代是要靠抽象封装而在这里变成了画布上的复制粘贴。第四解决人机协同问题。现在不少流程设计成“全自动”看起来很美但真正落到业务上总有一些决策需要人来拍板比如退款金额高、内容审核拿不准、风险评分超阈值。deer-flow 支持把人工确认做成流程中的一个节点整个流程可以停在那边等人处理后继续跑。这个点在不少项目里被当成边缘需求实际落地时价值非常大。1.3 什么样的团队适合直接上手如果你所在团队已经积累了很多零散的脚本每个脚本处理一段逻辑由外部调度系统拼起来跑deer-flow 能把这些脚本整合成一张有业务意义的图。因为流程里支持调用自定义节点老代码不用推翻重写包一层 API 或者做成节点就能接进去。如果你的项目刚刚起步还在纠结怎么组织多步推理逻辑deer-flow 也很合适。它不会强制你用某种编程语言部署完以后按画布拖一拖就能跑通一个最小闭环比直接读源码上手快得多。反过来如果你的需求只是“给我一个能聊天的页面”那确实用不上它。deer-flow 的价值在流程复杂度上来之后才真正体现出来这也是我在最开始说它“被低估”的原因——大多数人只把它当成又一个聊天机器人模板根本没有耐心把图搭完。2. 核心概念与设计思路拆解2.1 节点能力封装的基本单位在 deer-flow 里节点是最核心的抽象。你可以把一个节点理解成一个“积木块”每个积木块只干一件事然后通过连线组合出复杂的业务逻辑。我在实际使用中接触比较多的节点类型包括输入/输出节点、LLM 节点、知识库检索节点、条件分支节点、HTTP 请求节点、定时触发节点以及用户自定义的代码节点。节点与节点之间不是独立存在的它们通过“边”相连上游节点的输出会作为下游节点的输入。每个节点的输出通常是一个结构化的 JSON 对象下游引用某个字段时直接指定路径就行了。第一次用的时候可能会觉得这个概念有点抽象但你只要记住一点把每个节点当做一个函数输入是 JSON输出也是 JSON中间发生了什么节点自己负责。这样理解之后整个流程的思维模型就立起来了。我在做一个工单自动分类流程的时候就明显感受到这种设计的好处。先是一个输入节点接收工单文本然后 LLM 节点负责分类分类结果进入条件分支判断再分发到不同的后续节点。哪一步出了问题直接看对应节点的输入输出就能定位不用像调试传统代码那样在脑子里模拟整个调用链。2.2 边与数据流图里跑的都是 JSONdeer-flow 里流程本质上是一张有向图节点之间通过边定义执行顺序。值得注意的是边的设计不只是“跑完 A 再跑 B”它还要负责数据的传递。上游节点产出的结果会被放在一个统一的上下文里下游节点通过字段引用的方式拿到自己需要的那部分数据。画流程的时候我总结了一个经验不要把“数据传递”这件事交给节点内部去硬处理否则每个节点都去上下文里翻一遍耦合度会迅速上升。更好的做法是让每个节点只声明自己需要哪些输入字段输出固定成一个结构清晰的 JSON。这样即使在需求迭代频繁的阶段替换掉其中某个节点对其他节点的影响也能控制到最小。另外这里的“边”并不一定只是顺序执行有些场景下还可以配置条件表达式相当于给边加上开关。比如只有当上游分类结果等于“高优先级”时才走某条分支这实际上把简单的编程逻辑搬到了配置层业务方看起来就是几条带条件的连线理解成本非常低。2.3 “有状态编排”思考方式我在上手之前一直纠结一个问题这种流程图能不能表达循环比如“最多重试三次”“如果结果不合格就重新生成”。用链式调用去表达这些逻辑是很痛苦的因为链式天然是直线遇到回环只能靠代码绕。deer-flow 的思路是把流程当做一个有状态的执行引擎节点之间不仅有线性的顺序还能通过条件分支和循环结构组成更复杂的拓扑。我真实项目里遇到过一个场景模型生成的最终答案需要经过一个“质量标准检查节点”不合格就回到生成节点重跑连续两次不合格就转人工。这个逻辑如果用代码写我得维护一个重试计数器和 branching state但用 deer-flow 来做就是拉一条回环的线在分支条件里写上判断规则。图上跑起来之后整个流程的执行过程肉眼可见业务方看了直呼“原来这么直观”。当然有状态编排也意味着需要更严格的失败处理和超时控制。deer-flow 在节点级别都有异常捕获和重试配置每个节点跑挂了不会让整张图瞬间失控而是可以进入预设的异常分支或者触发告警。这部分在部署和设计流程时需要格外重视后面我会详细说。3. 部署落地本地跑通的完整过程3.1 环境准备与依赖项说明动手部署前先把依赖说清楚。deer-flow 的前端是标准 React 技术栈后端是 Java 生态Spring Boot数据库用的是 PostgreSQL。这里要注意的是它不像很多 Python 写的 LLM 项目那样靠 pip install 就完事要跑源码版需要准备好 JDK 17、Node.js 18、Maven以及一个可用的 PostgreSQL 实例。还需要准备一个可用的 LLM API Key。deer-flow 对模型接入做了抽象OpenAI 兼容的接口都能接所以你手里的国产模型、自建模型服务只要暴露成兼容接口一般都能配置进去。我自己测试时用的是 OpenAI 兼容协议配置一个 base_url 和 api_key 就能跑起来。第一次部署时就别想着完全搞懂每一个参数了先把最小环境跑通比什么都重要。我见过不少同事卡在“为什么我的配置和文档不一样”上最后发现是版本号对不上。这里建议查看官方仓库当前分支的 README示例配置以仓库代码为准不要凭记忆照抄网上的老教程。3.2 Docker Compose 快速启动如果本地已经有 Docker Compose 环境最快的方式是直接用编排文件拉起后端、前端和数据库。这里给一个思路性的示例具体内容以你拉到的仓库 docker 目录为准version: 3.8 services: postgres: image: postgres:14 environment: POSTGRES_USER: deer POSTGRES_PASSWORD: deer POSTGRES_DB: deer_flow volumes: - pgdata:/var/lib/postgresql/data ports: - 5432:5432 backend: build: ./deer-flow-backend environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/deer_flow LLM_PROVIDER: openai LLM_MODEL: gpt-4o-mini LLM_API_KEY: sk-xxx LLM_BASE_URL: https://api.openai.com/v1 ports: - 8080:8080 depends_on: - postgres web: build: ./deer-flow-web ports: - 3000:80 depends_on: - backend volumes: pgdata:跑docker compose up -d之后等后端日志出现启动成功的信息再访问前端页面。用 Docker 部署的好处是环境隔离得好不污染本机升级版本也方便重新拉镜像或者重新 build 就行非常适合第一次尝试。不过我遇到过一些问题比如本地 5432 端口已经被其他 PostgreSQL 占用的冲突。解决方案很简单右边映射端口换一个宿主端口比如5433:5432同时后端连接串里的端口也要跟着调整这个不细说等真遇到时改一下环境变量即可。3.3 源码启动方式与开发环境配置如果你打算在源码基础上做二次开发或者想跟踪最新代码调试那源码启动是绕不开的。后端先启动进入deer-flow-backend目录确认application.yml里的数据库配置正确后执行mvn spring-boot:run。第一次跑会下载大量依赖需要有耐心网络不太好可能要等一阵子。前端开发环境在deer-flow-web目录先npm install再npm run dev启动后默认是 Vite 端口一般是 5173。开发调试时前端页面的请求要通过 Vite 代理转发到后端 8080这个代理配置在前端vite.config.ts里。如果代理没配好最常见的问题就是页面能打开但创建流程后不保存、运行后结果不回来。用源码跑调试的好处是每个节点背后的代码逻辑都能跟进去。我记得排查一个“自定义节点加载失败”的问题时就是直接在后端日志里看到类加载异常才知道自己 Java 版本编译不兼容。如果你不是要做二次开发真的不必折腾源码版Docker 一把梭够了。3.4 首次启动后的界面功能认知项目启动起来之后别急着上手拖节点先把界面上的几个关键区域认清楚。deer-flow 的界面设计风格属于工程风功能模块划分很明确流程列表、节点库、画布区、属性配置区、运行历史。第一次进去可以先创建一个空流程然后从节点库里拖几个节点出来试试连线感受一下交互逻辑。我之前犯过一个错误一上来就把某个示例流程导入然后试图直接跑通结果因为模型 Key 没配好、节点参数没改白白浪费了半天。后来换了思路先自己拖一个最简单的流程输入节点 → LLM 节点 → 输出节点跑通之后再逐步加条件判断和工具调用。这个“先最小闭环再逐步加码”的思路在一切业务流程编排工具里都适用deer-flow 也不例外。4. 实操从零搭建一个可用的工作流4.1 选一个能体现复杂度的业务场景为了讲清实操我挑一个在真实业务里很有代表性的场景客户工单自动分类与处理。输入是一条客户提交的工单文本流程要做的事情是先让 LLM 判断工单属于哪个类型比如“退款”“账号问题”“产品咨询”再根据类型决定处理方式“退款”和“账号问题”需要转人工审核“产品咨询”则直接生成自动回复最终调用一个企业微信机器人接口把处理结果推送出去。这个场景能很好地展示 deer-flow 的核心能力因为它同时包含了 LLM 调用、条件分支、变量引用、外部系统集成、人工介入这几个关键环节。而且这个流程搭好之后稍微改一改就能复用到其他需要文本分类和分发的场景。选择场景这件事本身就是一种设计能力。很多初学者容易一上来就模拟特别复杂的业务画了二十多个节点结果跑不通也不知道从哪里查。我建议第一次练手先控制在五到七个节点以内把几个核心概念走通比追求流程规模重要得多。4.2 画布上的节点配置流程第一步加一个输入节点。输入节点的作用是声明这个流程被触发时需要接收哪些参数。在工单场景里就是ticket_id和ticket_content两个字段。这一步相当于定义函数的入参也可以用 HTTP 触发节点来替代区别在于输入节点更多用于流程内部测试。第二步加一个 LLM 节点把工单类型判断放进去。配置这个节点时需要指定模型供应商、模型名称、Prompt 模板以及希望模型返回的字段。Prompt 我一般会写成这样“你是一个工单分类助手根据输入的工单内容返回 JSON 格式的类型和置信度类型只可以从以下列表里选择退款、账号问题、产品咨询。”然后用输出字段解析功能把它转成结构化字段。第三步加条件分支节点判断上一步的category字段。这个节点类似于代码里的 switch case每个分支配一个表达式比如“等于退款”“等于账号问题”。条件分支配置完成后画布上会明显看到几条不同颜色的连线业务逻辑一目了然。第四步加处理节点。退款和账号问题走“创建人工审核任务”节点这个节点可以用自定义代码实现也可以调用内部系统 API产品咨询走“LLM 生成回复”节点。最后再接一个“发送企业微信消息”节点把结果推送出去。到这里一条能请求的工单流程就成型了。4.3 字段映射与数据引用技巧整个流程里最考验细心的就是字段映射。每次在两个节点之间连线后一定要去下游节点的输入配置里确认它拿到的字段名和上游输出一致。不同版本的 deer-flow 在字段引用语法上可能有差异但基本思路是一样的通过路径引用上游节点输出的某个字段比如{{node_id.output.category}}。我在部署时就被这个坑过上游 LLM 节点明明输出了category字段下游条件分支却一直匹配不上。排查了半天发现是模型返回的 JSON 字段名带了空格或者大小写不一致。从那以后我在 LLM 节点的输出配置里固定加了一步“结构化解析”要求模型严格返回 JSON并且用系统提示词强制字段名规范。在使用 LLM 节点时强烈建议开启 JSON 输出模式。虽然这会占用一定的输出 token但换来的是下游解析的稳定性。很多时候流程“莫名其妙”不工作不是编排逻辑错了而是模型返回了一些额外说明文字把结构化数据撑坏了。4.4 测试运行和日志调试配置完成后先别急着接真实业务用流程编辑页的“测试运行”按钮跑一遍。deer-flow 会提供一次性的输入参数入口你可以模拟一条工单文本传进去然后观察每一步的执行情况。运行结束后在运行历史里能看到每个节点的耗时、输入、输出这个观察窗口比什么调试器都直观。我第一次测试工单流程时问题出现在“产品咨询”分支的回复生成节点。模型返回了一段很长的标准答案结果发送消息节点直接超时了。后来我才意识到不是节点的问题是消息接口只接受 500 字以内的文本。我在生成节点前加了截断逻辑问题就解决了。这类问题如果不看运行历史里的具体输出几乎不可能定位得这么快。调试过程中还有一个效率技巧给每个节点起一个业务上能看懂的名字而不是默认的 node1、node2。你在运行历史里排查时能一眼看出是“分类判断”出了问题还是“消息推送”出了问题。这个习惯虽然简单但能省下大量时间。5. 常见问题与排查技巧实录我把这段时间使用中遇到的高频问题和排查思路整理成了一个速查表希望帮你少走弯路现象可能原因排查顺序流程一直卡在某个节点外部 API 超时、节点重试配置不当先看运行历史里节点的耗时再看日志中是否有超时异常LLM 节点返回 401/403API Key 错误、额度不足、base_url 配置不对确认模型供应商配置项是否生效直接在节点里用简单 prompt 测试下游拿不到上游字段字段名不一致、输出是数组不是对象打开上游节点输出详情对比路径引用是否匹配条件分支永远走同一个方向表达式语法写错、字段类型不是预期在断言前加一个输出节点把待判断的字段值打印出来前端页面能打开但接口全报错前端代理配置没生效、后端端口不对打开浏览器开发者工具看请求失败的 URL 和响应体数据库连不上环境变量里连接串写错、容器没就绪docker compose logs postgres先确认 DB 是否健康模型输出内容总被截断输出 token 上限设太小调整模型节点的 max_tokens 参数或改用更长上下文的模型除了表格里的这些还有一些属于经验层面的东西。比如流程里涉及多次 LLM 调用时尽量选用响应速度稳定的模型不要在全自动链路里用那种排队特别严重的大模型接口。因为流程一旦编排完单个节点慢几十秒整个链路的体验就会非常难受。还有一个很值得说的坑不要把敏感数据直接放在节点配置里。deer-flow 的节点配置会持久化到数据库如果流程包含内部系统密码、Token 这类信息建议通过环境变量注入或者外部密钥服务引用否则一旦数据库泄露等于把所有配置全暴露了。关于重试策略我给一个推荐方案普通外部调用节点重试次数设 2 到 3 次重试间隔用指数退避LLM 节点尽量不要开太多重试因为模型调用本身就贵不如在上游做输入校验提高第一次调用的成功率。这个策略在线上稳定运行后被验证挺靠谱的。调试环节最大的心得是永远保留一个输出节点。不管你的流程多复杂在各关键节点后面挂一个日志/输出节点跑一次就能看到整个过程的数据流转定位问题的速度能提升一个数量级。等流程真的稳定以后再把这些临时输出节点删掉也不迟。6. 个人使用体会与后续扩展思路用 deer-flow 做过两个完整流程之后我对“AI 编排引擎”这个赛道的理解比之前清晰了很多。像这种引擎真正有价值的地方不在“能跑”而在“可维护”。同样一个多步 Agent 逻辑用代码写一周后会忘让别人接手更是灾难但在画布上节点的连接关系、判断条件、数据引用看得清清楚楚哪怕隔一个月再回来也能快速进入状态。我特别想把一个经验分享给正在考虑引入类似工具的团队不要一开始就追求流程平台的“大而全”。先选一个真实业务场景把最小闭环跑起来让业务方看到效果再逐步把更多场景收到平台里。deer-flow 这类工具是“越用越有价值”的前提是你有耐心把第一个流程打磨好。后续我打算做的扩展有几个方向一是把流程通过 API 暴露给上游系统让内部系统可以直接触发它二是尝试写几个自定义节点把团队里已有的 Python 服务包进去三是研究一下子流程拆分的玩法把公共逻辑抽出来复用。这些如果折腾出了成果我再来分享具体细节。最后说一个很实用的冷门技巧如果关键流程要上线生产建议把流程配置导出成文件留底并且写清楚每个节点的核心参数。这既方便在测试环境和生产环境之间迁移也是团队协作和交接的重要保障。很多人把精力花在写代码上却忽略了“流程即资产”这件事deer-flow 让我重新审视了这种工程习惯。