
从去年下半年开始我连续被好几个团队问到同一个问题Agent到底要不要引入工作流编排有的团队在LangGraph里写了一堆状态节点最后发现改一个分支要动半套图有的团队则相反搭了一个可视化平台结果业务方提了一句“加个条件分支”产品和技术在工单里来回拉扯了两周。大家不是在选型而是在为上一个没想清楚的决定买单。这篇是Agent系列的第9.1篇专门聊“工作流编排的光谱与选型”。我会把编排方案从硬编码到可视化平台的完整光谱摊开讲清楚每个位置适合什么场景再结合我自己实操过的客服工单Agent案例给出一份可落地的选型决策参考。适合正在做Agent落地的开发者、技术负责人也适合被业务方追着问“这个流程能不能拖出来改”的架构师。不管你是第一天接触Agent还是已经写了不少自定义调度代码这篇都会帮你重新校准一下自己的位置。1. 工作流编排的光谱从一行代码到一个拖拽画布1.1 先厘清为什么说编排是一个光谱很多人把“工作流编排”当成一个二元选项要么用代码写死所有步骤要么上一个大而全的编排平台。但我在实际项目里感受最深的是它更像一个连续的“光谱”左端是纯代码函数调用右端是拖拽式BPM平台中间还有DSL脚本、状态机、轻量级工作流引擎、消息队列驱动的事件流等一堆过渡形态。为什么是这个光谱形态因为工作流编排的本质是回答三个问题步骤怎么定义、步骤之间怎么连接、出错以后怎么处理。这三个问题的答案不同就会把你推到光谱的不同位置。比如你的流程是“调用A函数再调用B函数”硬编码就够了但如果你的流程有十几个步骤、有人工审批、有可能半夜执行失败要重试那硬编码就非常痛苦。光谱不是为了制造概念而是帮助你识别自己真实的复杂程度。还有个原因团队能力、维护成本和运行环境也在光谱上分布。一个全是资深后端工程师的团队和一个需要业务运营自己配流程的团队面对同一个需求会做出完全不同的判断。所以别问“哪个工具最好”先问“我站在哪里”。1.2 光谱左端代码内编排与手动状态机光谱左端最常见的形态是把Agent的每一步直接写进Python或者Go代码里比如def run_agent(input_text): result1 step_extract(input_text) result2 step_classify(result1) result3 step_retrieve(result2) return step_generate(result3)这种方式的优势是直接、灵活、好调试。因为全流程都在你的控制流里你可以清晰看到每一步的输入输出IDE断点直接打进去单元测试也容易写。对于步骤少于五六个、分支不多、不需要长时间等待的流程我强烈建议就用这个别折腾什么编排引擎。但左端的痛也明显状态是散落在内存里的一旦进程崩溃整个流程就丢了重试逻辑得自己写每多加一个步骤函数的签名可能就要改一次分支越来越多之后代码开始变得像意大利面条。有些人会在这个阶段自己写一个“状态机”用字典或者枚举记录当前状态看起来比一堆if-else有结构感但本质上还是在左端。1.3 光谱右端可视化工作流平台光谱右端是各种可视化编排平台比如n8n、Dify、Microsoft Power Automate以及企业内部的老牌BPM系统。这类平台的卖点是把流程节点拖拽出来连线配置参数业务人员也能看懂。在Agent场景里右端方案最大的价值是“快速搭原型”和“交付给运营”。我见过一个团队用n8n把“客服答疑Agent”从想法到Demo只用了一个下午节点分别是接收消息、调用LLM、查知识库、返回答案全程没有写一行后端代码。这在光谱左端几乎不可能做到。但右端的坑一点都不少。首先是复杂逻辑受限一旦流程里要处理循环、并发分支、复杂的超时补偿可视化节点往往不够表达其次是版本管理和代码评审很尴尬很多平台导出的是JSON或私有格式没法像代码一样做Git diff和Code Review最后是供应商锁定今天用这个平台的画布明天想迁到代码方案等于重写一遍流程。所以右端适合轻交互、短流程、业务人员深度参与的场景不适合作为核心业务系统的主干。1.4 光谱中间DSL脚本与轻量级工作流引擎绝大多数Agent项目最优解其实都在光谱中间。这里的方案是用一种结构化描述YAML、JSON或DSL定义流程结构然后交给一个执行引擎去跑。比如Temporal、Prefect、Airflow以及近几年很受关注的LangGraph本质上都处于这个区间。中间地带的优势在于流程定义和业务代码分离了。流程长什么样是文件里写清楚的可以在CI里做静态检查可以评审、回滚、版本化但每个节点内部的实现还是普通代码不丢掉灵活性。我越来越认为这才是Agent工程化里“既要又要”的正解。举个例子你可以在Python里用Temporal的Workflow定义几个步骤每个步骤是一个Activity然后让Temporal负责调度、重试、超时、以及故障后的恢复。代码还是你的代码但流程的可靠性不用自己造轮子了。这就是光谱中间最大的价值你不用面对一个不透明的大平台也不用把所有脏活累活扛在自己代码里。2. 选型前先回答六个关键问题2.1 你的节拍是“一次跑完”还是“长时挂起”Agent流程的运行节拍决定了编排在底层要支持什么能力。有些Agent是一次性的拿到输入调几次LLM返回结果整个过程几秒钟。这种状况下硬编码和轻量状态机就够了不需要引入能存活几天的工作流引擎。但另一个极端是Agent流程里有人工审批审批人要第二天才点确认那你的流程必须能“挂起”几小时甚至几天。我见过一个团队用普通函数写Agent跑到一半遇到一个需要人工介入的环节直接把流程状态存在内存里进程一重启全部清零。这就是没想清楚节拍的下场。任何需要跨小时、跨天运行的流程一定要选择支持持久化执行的编排引擎至少也得把每一步的状态落库。在选型表里加上“是否支持长时间运行”这一项能过滤掉一半不合适的产品。2.2 谁在修改流程研发还是业务第二个问题听起来简单但往往决定方案走向。如果流程的修改总是由研发团队内部完成那代码优先的方案LangGraph、Temporal完全没问题因为有工程师的上下文能理解代码。如果业务方会频繁提出“流程能不能改”而且他们自己也想动手拖拽那你就需要考虑可视化平台。但这里有个很容易忽略的隐藏成本业务修改流程的频率和粒度是什么只是改一改阈值比如“当置信度大于0.8时才走自动回复”那不需要可视化平台把它做成配置中心的一个参数就够了。如果是“在分类之后新增一个风险校验节点”结构变了那才是编排层面的改动。后者才需要把流程定义的权限开放出去。所以不是“业务能改就行”而是“业务到底改结构还是改参数”。大部分时候业务想改的是参数。2.3 流程结构变动的频率有多高准确的词是“拓扑稳定性”。如果你画一下流程图发现这个图三个月才变一次那任何方案其实都够用如果每两周就要调整一次节点顺序、增加分支、删除合并逻辑那左端硬编码会让你疲于奔命。对于高频变化的流程你要找的是一个“流程定义与业务代码解耦”的方案DSL加执行引擎是最现实的取舍。我在实际项目里发现很多流程的“变动频率”是被低估的。一开始说只是固定几步等接入了真实业务产品经理每个月都有新想法。这种情况下如果你用的是纯代码左端方案每一次叠加分支都是在给未来埋雷。反过来说如果你上的编排引擎非常重每个节点都需要单独部署服务那即使流程结构经常变你也不敢轻易变因为发布成本太高。选型时要再问一句流程变了我改哪里改多久怎么上线2.4 失败恢复你要做到什么程度做Agent的人都应该问自己一个问题如果第4步挂了我该怎么办是重试第4步还是回退重跑整个流程还是把当前状态保存下来等条件满足后再继续这三个要求对应完全不同的编排能力。普通的代码左端方案重试做得简单粗暴把第4步包在一个try-except里失败了就sleep一下再调用最后还是失败就告警。这在很多场景里是够用的尤其是LLM调用本身存在不确定性重试是常态。但如果你需要的是“回滚”问题就复杂了。比如第3步已经往客户系统里写了一张工单第4步挂了你不仅要重试第4步还得处理第3步造成的副作用。这时你就需要编排引擎提供“补偿”能力或者至少在设计流程时把每个节点的幂等性做掉。还有一个很容易被忽视的点人工补偿。真正关键的业务流程可能最终还是要靠人工去判断该重试还是终止。编排引擎能不能在失败时暂停、等一个外部信号、然后恢复这个能力在Agent场景里是杀手级的。2.5 可观测性、追踪与审计是不是刚需Agent流程比普通接口调用链条长得多一个工单从提交到回复可能经过了意图识别、知识检索、风险校验、LLM生成、人工审批五个步骤其中每一步都可能是一个独立的服务调用。如果没有一个全局视角去观察“当前工单卡在哪一步”出了问题调查成本会非常可怕。我甚至见过线上工单莫名丢失排查了两天最后发现是流程在某个分支上没有打日志。所以选型的时候我建议把“可观测性”放到和功能同等的优先级。轻量级引擎能不能暴露当前状态有没有链路追踪的埋点失败有没有统一的日志格式可视化平台虽然自己带了执行记录但往往只是“当前跑没跑完”缺少贯穿跨系统的trace。对于To B的Agent场景审计需求通常也不能让步谁在什么时候做了人工干预系统基于什么理由做出了这个回复这些都需要编排层记录下来。2.6 团队能扛住多少运维复杂度最后一个问题最现实也最扫兴你的团队有几个人愿意去维护编排引擎本身Temporal功能很强大但它需要独立的服务集群要运维要学习曲线Airflow同样需要长期维护调度器和执行器。如果团队只有两三个后端每个人都背着业务需求那我不会建议为了Agent上一个需要单独值班的系统。这不是说它们不好而是团队运维带宽也要算进选型公式。如果你的团队驾驭不了重引擎那退回到“轻量级状态机 外部消息队列 数据库持久化”也可以解决问题。反过来说如果公司已经有了成熟的消息中台和数据平台那复用它们比引入一个全新的编排系统更划算。选型不只是选工具也是选择你要长期承担的平台债务。3. 主流编排方案横向对比与实战体会3.1 代码优先LangGraph 与自研状态机先聊现在Agent圈里最热的LangGraph。用官方的话说它是一个用于构建有状态、多角色Agent应用的图框架。我的直接体验是LangGraph最适合的是“状态驱动、分支复杂、需要人类介入”的Agent流程。它把流程抽象成图节点是业务逻辑边是条件转移整个图的状态可以持久化暂停和恢复。举个例子你可以这样定义一个简单的工作流from langgraph.graph import StateGraph, END class AgentState(dict): messages: list documents: list def classify(state): # 调用LLM分类 return {category: result} def route(state): if state[category] complaint: return risk_review return retrieve def risk_review(state): # 敏感场景人工确认 return {approved: True} def retrieve(state): # 查询知识库 return {documents: docs} def generate(state): # 生成回复 return {messages: [...]} graph StateGraph(AgentState) graph.add_node(classify, classify) graph.add_node(risk_review, risk_review) graph.add_node(retrieve, retrieve) graph.add_node(generate, generate) graph.add_conditional_edges(classify, route, {retrieve: retrieve, risk_review: risk_review}) graph.add_edge(risk_review, retrieve) graph.add_edge(retrieve, generate) graph.set_entry_point(classify) graph.set_finish_point(generate)LangGraph能给你很多现成能力状态管理、手动中断、断点续跑、甚至与用户交互的工具调用。但它的学习曲线并不低你需要理解图、边、状态约减、检查点等概念。而且LangGraph并不擅长“长时业务事务”和“跨服务编排”它更像是Agent内部的控制流而不是整个系统的拍板引擎。如果你只有一个Agent服务用它很顺手如果你有多个微服务和一大堆外部依赖它可能会憋屈。至于自研状态机我的态度是除非你的流程极其稳定且节点很少否则不要造这个轮子。自研状态机最尴尬的地方在于一开始你觉得很简单等加了重试、超时、并发和持久化之后你实际上在重写一个简化版工作流引擎。有这时间不如去看看成熟方案。3.2 工作流引擎Temporal、Prefect、Airflow 的取舍这三位经常被摆在一起但它们的“人设”其实不一样。Temporal是一个通用型的分布式工作流引擎核心模型是一个工作流函数可以“睡眠”很久等活动完成后继续执行。它把持久化状态、重试、超时、补偿都做得非常成熟特别适合“人工审批等待两天”这种场景。在Agent工程中Temporal可以作为一个连接外部系统和Agent逻辑的“业务事务编排层”。Prefect的强项则是数据工作流与动态依赖。它对“从数据库取数、调用模型、写回结果”这种数据管道很友好Pythonic API好上手。Airflow则更偏“定时调度ETL”它有成熟的调度生态和强大的生态扩展但调试体验和状态管理相对重。如果你已经在用Airflow管理离线任务那让Agent的数据处理后端也走Airflow没毛病但如果你需要一个即时、交互式的Agent服务Airflow不是最佳选择。三者之间如果你只是“想给Agent流程加一个可靠的重试和持久化”我建议优先看Temporal。但注意Temporal引入了必须常驻的服务端所以运维预算也要算进去。我自己的经验是如果团队小于五个人先别急着上Temporal用LangGraph加一个持久化保存状态或者直接借用公司已有的消息队列来扛可靠性通常更现实。选引擎的本质是选你能长期养的团队能力。3.3 可视化低代码平台n8n、Dify 与 Coze 的边界可视化平台的代表有n8n、Dify、Coze等。n8n是自托管的自动化工作流工具适合连接外部API、做消息路由Dify偏向LLM应用开发内置了知识库、RAG流程也有可视化编排界面Coze则是面向C端/B端快速搭建机器人的平台拖拽程度最高。我的建议很简单如果目标是“快速Demo内部小工具”直接用可视化平台效率无敌。我试过在n8n里把企业微信消息、向量库检索、LLM回复串成一条自动化前后不到半天也不需要写代码。但如果你要做的是一个面向生产的高并发Agent系统可视化平台通常不够。它们对分支、循环、异常回滚的支持不够细版本管理和灰度发布也比较弱更不用说做代码评审和单测。另一个常见误区是混淆“Agent应用框架”和“流程编排平台”。Dify里虽然能编排但它更多是帮你搭LLM应用如果你的流程核心不在LLM生成上而是围绕工单状态流转、多系统写入那这种“Agent框架型平台”会使不上劲。这时候还是需要回到通用编排引擎或者写代码。3.4 消息队列在编排里的位置Kafka、RabbitMQ、RocketMQ 的实战差异热词里出现了Kafka、RabbitMQ、RocketMQ的选型对比这里也值得讲清楚。很多人会问既然有工作流引擎为什么还要消息队列我的回答是消息队列解决的是“事件解耦”与“流量削峰”工作流引擎解决的是“业务步骤管理”两者不是替代关系而是上下层关系。在Agent场景里我经常把消息队列放在最前端外部请求写进队列工作流节点从队列消费任务失败的消息可以重新投递。选型上Kafka的高吞吐能力最强适合日志、事件流、百万级消息的场景RabbitMQ功能丰实、路由灵活适合后端服务之间的异步消息交互RocketMQ则在可靠性和事务消息上做了很多改进特别适合电商订单事务一类的场景。对于Agent工单处理如果请求量不大、但每条都要可靠处理RabbitMQ或RocketMQ比Kafka更顺手如果你需要把Agent产生的每个动作都作为事件流给下游做分析那Kafka更合适。这里有一个人人都容易忽略的“避坑点”重试的重复消费。Agent在调用LLM时如果超时消息被重新投递同一个用户请求可能被处理两次造成重复扣费。所以使用消息队列时每个消费者的幂等性必须一开始就设计好。比如为每个消息生成唯一的业务ID在入口判断是否已经被处理过。这比任何编排引擎都重要因为队列保证的是“至少一次投递”不保证不会重复。3.5 记忆与知识库是编排的“隐藏依赖”最后说一个热词里反复出现的部分Agent记忆框架与向量数据库选型。表面看记忆和编排是两个话题但实际使用中它们高度耦合。工作流节点之间的状态流动往往不只是传字符串还要携带从向量库检索到的文档、从记忆模块读出的历史对话这时候编排框架得能处理这些“非结构化但可序列化”的数据。我在做选型的时候就踩过一个坑用向量库Milvus存了一大堆文档又在LangGraph里跑了完整的RAG流程结果发现中间某个节点把不可序列化的对象塞进了状态里导致程序重启后检查点恢复失败。这提醒我编排选型要看它怎么对待“数据面”。比如状态里的对象能不能被JSON序列化能不能持久化检索结果放在状态里会不会让每个节点变得很臃肿都是要先确认的。不同的向量库也有不同的适配思路Milvus擅长海量向量检索和分布式部署Chroma轻量、适合本地原型Qdrant性能很强而且Rust实现得很稳。但无论选哪个要把它们当作“外置记忆服务”不要直接跟Agent内存里的状态强绑定。更好的做法是工作流节点通过独立的检索服务去访问向量库把结果转换成轻量的DTO放进工作流状态里。这样编排层和数据层互相不太影响。4. 从0到1选型实操一个客服工单Agent的完整决策过程4.1 业务场景与原始需求为了把这套思路讲透我直接用最近帮一个团队落地的客服工单Agent举例。他们的原始需求是用户在App里提交一条售后工单系统要自动识别工单类型、提取关键信息订单号、问题描述、查询知识库与历史工单、生成一封初步回复并转给人工客服审核。如果识别出来的问题命中“退款”“投诉”等敏感词必须先走到风险审核节点不能直接自动回复。这个场景非常典型因为它既有自动化的LLM步骤也有需要人工介入的节点还涉及外部系统的写入工单系统、知识库而且每天有大几百条工单进来峰值时可能上千。我们把选型过程拆成几步每一步都对照前面提到的六个判断维度。4.2 流程拆解与候选方案先画出控制流它的节点大概是接收工单、意图分类、信息抽取、风险判断、知识检索、回复生成、人工审核、工单回传。其中意图分类后有一个条件分支如果是“退款投诉”类走风险审核否则走标准回复。人工审核节点需要支持“挂起等待”因为客服可能十几分钟甚至几个小时后才处理。对照之后我们从光谱上筛出四个候选方案候选方案核心思路优势主要顾虑A. 纯LangGraph用LangGraph管理整个Agent内部流程状态和分支清晰支持断点人工介入功能和运维边界不够长时挂起需额外持久化B. LangGraph TemporalLangGraph负责Agent内部Temporal管理外部步骤与人工等待长时运行和有损恢复能力强引入两个系统学习与运维成本高C. n8n可视化流程拖拽节点连起来快速、业务可改复杂状态和并发控制太薄弱D. RocketMQ事件驱动把每步作为消息异步处理削峰解耦可靠投递流程逻辑变散状态分散难追踪4.3 最终选型LangGraph 做主控制器RocketMQ 做外围缓冲这个项目最终选择的是A加D而不是B。原因是团队只有四个后端没有专门的SRE能长期维护Temporal集群。我们用LangGraph管理Agent主流程比如意图分类、信息抽取、知识检索、回复生成这些步骤但在接收和回传外部系统的边界上接了一条RocketMQ负责请求的异步进入和工单状态的可靠更新。为什么这么选首先LangGraph已经能覆盖大部分内部状态流转并且支持通过断点实现“暂存等待人工审批”不需要一下子把所有复杂度都交给Temporal。其次峰值流量下直接把请求同步打进AgentLLM调用会把后端资源和成本打爆用RocketMQ在入口做个缓冲消费者再以可控的速度调用Agent是最便宜也最有效的保护。第三人工审核环节我们没有让LangGraph“干等”而是把状态存进数据库客服在后台审核完成后通过接口回调触发Agent继续执行。这个设计让LangGraph避免了一个长连接被挂好几个小时。这套方案的代价也很明确状态不像Temporal那样由引擎自动持久化而是要自己在关键节点落库失败恢复也得自己写一部分。但以团队规模和生产要求来说这个代价是值得的因为可维护性更高。4.4 实施过程中的三个坑与解决方式第一坑LLM调用被重试导致的重复扣费。我把“生成回复”节点放进LangGraph后直接给整条边配置了全局重试。结果某次知识库超时整个节点重试了三次每一次都调用了LLM费用翻了三倍。后来我把LLM调用改成“先探测再调用”并且限制重试只在网络异常时触发而不是在不同状态下盲目重试。更关键的是每个请求都带了唯一的request_id在LLM调用层做了幂等缓存。第二坑状态里放了不可序列化的大对象。一开始我把知识库检索的完整结果直接塞进LangGraph的AgentState结果检查点恢复时直接报错因为里面有几个临时连接对象。最后改成只存文档ID和摘要真正要用的详细内容通过一个检索服务按需加载。这个教训特别值得讲编排系统的状态存储是用来存状态机的上下文的不是用来存业务数据的。第三坑人工审批导致整条流程卡死。最初我们让LangGraph停在审批节点等待外部回调。结果某天审批平台回调接口出了故障所有工单都卡在同一个状态消费者线程全部被占满。后来我改成超时兜底如果两小时没有收到回调就把工单状态标记为“审批超时”转给第二队列处理。这样就算回调失败也不至于整个流程不可恢复。这些细节才是真正决定一个Agent工程能不能长期跑稳的关键。5. 常见问题与避坑速查表5.1 高发问题速查表我在看各种Agent工程时收集了很多高频踩坑点这里整理成一个速查表按“问题-原因-建议”三列给出来方便你对照自己项目排查。问题根本原因建议流程偶尔“丢失”状态只存在内存进程重启即消失关键节点状态落库或用支持持久化的编排引擎重试导致重复调用LLM/API节点级重试过于宽泛没有幂等保护给每个请求一个唯一ID在调用层做去重缓存卡在人工审批节点无法恢复审批回调没有超时兜底设置超时时间超时后转降级流程或重新排队状态里塞入不可序列化对象把数据库连接、临时句柄放进状态上下文只保留轻量DTO详细数据通过外部服务加载流程上线后改不动流程定义和业务代码完全耦合将流程定义剥成DSL/JSON至少从配置中心读取参数观测不到当前跑到哪一步没有给每个节点统一埋点和trace引入链路追踪或至少在状态变更时写审计日志分支过多导致代码如乱麻用了太多if-else代替条件边改用状态图/工作流引擎管理条件分支选了重引擎但没精力运维只看了功能却忽略团队运维带宽只在有明确长期收益时选重引擎否则先轻量起步5.2 什么时候应该坚决不上编排引擎不是所有Agent都需要工作流编排。如果你的流程是线性的、每次只处理一条请求、没有人工等待那最合理的方案是普通代码加几个函数。我见过太多技术团队为了“架构整洁”把简单事情复杂化本来一个service方法能搞定硬是套上Temporal结果每次改需求都要发版升级工作流开发效率反而直线下降。还有一种情况也不该上重引擎你的“流程变动”其实只是参数变动。比如某个系统的提示词在变某个阈值在变某个模型版本在变。这些应该通过配置中心、特征开关或Prompt管理平台解决而不是去改编排图。我自己的经验是先画一遍控制流如果分支不超过三个、节点不超过六个那就别动用任何引擎最多用一个轻量状态常量加一个条件路由函数。做得越复杂你离实际业务其实越远。5.3 我的选型心法先画两张图再做减法最后分享一个我的固定动作也算是这套Agent系列的个人经验沉淀。每次遇到工作流编排选型我会先画两张图第一张是“控制流图”画清楚有哪些节点、节点之间哪些条件边、哪些节点可能失败第二张是“数据流图”画清楚每一步的输入输出从哪里来、会往哪里写尤其是外部系统的副作用。画完这两张图很多问题的答案自己就出来了。如果控制流几乎是一条线那么左端代码方案就够如果控制流里有“等待事件暂停”的节点那必须把长时持久化能力考虑进去如果数据流里有很多外部写操作那幂等和补偿就要重点设计。然后再做减法先看团队有多少人可以维护编排系统再看公司有没有现成的服务可以复用最后才轮到比较工具本身的功能。用这个方法至少能帮你在五花八门的Agent项目里避开一半错误选项。工具一直在迭代今天热门的框架明天可能有替代品但“先看清自己的流程拓扑再决定编排粒度”这件事在Agent工程里是长期通用的。最后再补一个小技巧你把第5.1节的速查表转成一份“选型前检查清单”在项目启动会时让参与的人一起过一遍。哪怕只是花十五分钟逐条回答也会提前暴露很多问题。当初我们客服工单Agent如果在开工前就严格走一遍这个清单后面至少能少加两次班。