1. 自动化跑完最后一公里人反而更忙了你有没有遇到过这种场景凌晨两点你盯着屏幕上那个跑了三个小时的自动化工作流进度条卡在87%不动了。日志里最后一行写着“等待元素超时”然后就是一片死寂。你心里清楚明天早上九点之前如果这个流程跑不完下游的报表、通知、数据同步全部要延迟。于是你只能手动打开那个界面一步一步把剩下的13%点完。这不是段子这是很多做AI自动化和Agent工作流的人每天都在经历的事。我们花了大量时间搭建流程、调试节点、优化提示词结果真正让人崩溃的往往不是流程本身跑不通而是跑了一半失败之后工作该怎么继续。“麦睿菱AI实践”这个项目标题里提到的“自动化失败后工作怎样继续”恰恰戳中了当前AI Agent和工作流落地中最真实的痛点。大家聊AI自动化的时候喜欢聊“一键完成”“全自动闭环”“无人值守”但真正在一线干活的人都知道自动化系统的健壮性不取决于它顺利时跑得多漂亮而取决于它失败时能不能优雅地交棒给人。这篇文章想聊的就是这件事当你的AI工作流、Agent任务、自动化脚本在中途挂掉之后怎么设计一套“失败续跑”的机制让工作不至于从头再来也不至于让人陷入比手动做还累的窘境。不管你是用Coze搭工作流、用Playwright做自动化测试、还是自己写Agent调度逻辑这套思路都能直接拿去用。2. 为什么自动化失败后的“续跑”比“重跑”难十倍2.1 重跑的成本被严重低估了很多人对自动化失败的第一反应是重新跑一遍不就行了这个想法在流程很短、状态很轻的场景下没问题。比如你写个脚本批量重命名文件失败了重来一遍几秒钟的事。但放到AI工作流和Agent场景里重跑的代价完全不是一个量级。我拿一个典型的简历筛选工作流举例。假设你的流程是这样的从邮箱拉取简历附件调用OCR提取文本用大模型做信息抽取和评分最后把结果写入表格并发送通知。这个流程跑到“大模型评分”这一步失败了如果你选择重跑意味着前面拉取邮件、OCR识别、文本清洗全部要再来一遍。如果简历有几百份光是OCR那一步就可能花掉十几分钟。更关键的是有些操作是有副作用的——比如你已经给候选人发了确认邮件重跑会导致重复发送比如你已经写入了部分数据重跑会产生脏数据。这就是重跑和续跑的本质区别重跑假设系统是无状态的续跑要求系统能记住自己走到哪了。而绝大多数AI工作流工具默认并不帮你做这个状态记录。2.2 Agent场景下的失败更隐蔽传统自动化脚本的失败通常很明确元素找不到、接口返回错误、文件不存在。但AI Agent的失败往往更隐蔽。比如你让Agent去完成一个“调研竞品并生成报告”的任务它可能不会报错而是自信地给你一份基于错误信息的报告。这种“静默失败”比直接崩溃更可怕因为你不知道它从哪一步开始跑偏的。还有一种情况是Agent陷入了循环。它反复调用同一个工具每次都得到相似的结果但就是无法推进到下一步。你在日志里看到的是正常的工具调用记录但整个任务实际上已经卡死了。这种失败没有异常抛出没有错误码只有时间在一分一秒地流逝。所以讨论“失败后工作怎样继续”首先要区分失败的几种类型失败类型典型表现是否可续跑处理策略硬失败接口超时、元素找不到、进程崩溃通常可以从检查点恢复软失败结果质量差、逻辑跑偏需要人工判断人工介入修正后继续静默失败无报错但任务未完成需要检测机制增加校验节点循环失败Agent反复执行同一操作需要熔断设置最大重试次数2.3 状态管理的三个层次要让工作流在失败后能继续核心是做好状态管理。我把状态管理分成三个层次你可以对照自己的系统看看在哪一层。第一层无状态。每次执行都是全新的失败了就从头来。这是最简单的模式适合短流程、无副作用的场景。大部分入门级的自动化脚本都在这一层。第二层检查点状态。在流程的关键节点记录执行进度失败后可以从最近的检查点恢复。比如每处理完10条数据就写一次进度文件重启时读取这个文件决定从哪继续。这是大多数生产级工作流应该达到的层次。第三层事务状态。不仅记录进度还记录每个操作的输入输出和副作用支持回滚和补偿。比如某个步骤失败了系统能自动撤销之前步骤产生的副作用然后从干净的状态重新执行。这是金融级系统才需要的层次对大多数AI工作流来说过于重了。对于“麦睿菱AI实践”这类场景我建议至少做到第二层。具体怎么落地下一节展开讲。3. 给工作流装上“存档点”检查点机制的设计与落地3.1 检查点应该记什么设计检查点机制第一个要回答的问题是我需要记住什么才能在失败后继续很多人第一反应是记住“执行到第几步了”。但这个信息远远不够。假设你的流程是处理一个列表执行到第37条失败了。你知道要从第37条继续但第37条之前的处理结果在哪如果结果只存在内存里进程一挂就全没了。所以检查点至少要包含三类信息进度信息当前处理到哪个元素、哪个步骤。这是最基本的。中间结果已经处理完的数据、已经生成的中间产物。这些需要持久化到磁盘或数据库。副作用记录已经执行了哪些不可逆的操作比如发送了哪些通知、写入了哪些外部系统。这是为了避免重复执行。我见过很多团队只做了第一项结果续跑的时候发现中间结果丢了只能把前面的步骤重跑一遍来重建上下文。这就失去了续跑的意义。3.2 检查点的写入时机检查点写得太频繁会影响性能写得太稀疏失败时会丢失大量进度。怎么找平衡点我的经验法则是按“重跑成本”来决定写入频率。如果一个步骤重跑要花30秒那每完成这个步骤就写一次检查点。如果一个步骤只要0.1秒那可以每100个步骤写一次。核心思路是让“最坏情况下需要重跑的工作量”控制在一个可接受的范围内。具体到代码层面一个简单的检查点写入逻辑大概长这样import json import os CHECKPOINT_FILE checkpoint.json def save_checkpoint(step, processed_items, side_effects): checkpoint { step: step, processed_items: processed_items, side_effects: side_effects, timestamp: time.time() } # 先写临时文件再重命名避免写入过程中崩溃导致文件损坏 tmp_file CHECKPOINT_FILE .tmp with open(tmp_file, w) as f: json.dump(checkpoint, f) os.replace(tmp_file, CHECKPOINT_FILE) def load_checkpoint(): if os.path.exists(CHECKPOINT_FILE): with open(CHECKPOINT_FILE) as f: return json.load(f) return None这里有个细节值得注意写检查点要用“临时文件原子重命名”的方式。如果你直接往目标文件写写到一半进程崩了检查点文件就损坏了下次启动读不出来等于白做。这个坑我在早期项目里踩过排查了半天才发现是文件写入的原子性问题。3.3 续跑时的状态恢复逻辑有了检查点续跑的逻辑就清晰了启动时先读检查点如果存在就从检查点记录的位置继续如果不存在就从头开始。但这里有个容易忽略的问题检查点可能过期。比如你的工作流是每天处理当天的数据昨天的检查点今天就不适用了。所以检查点里最好带上一个“批次标识”或“时间戳”启动时校验一下这个检查点是否属于当前批次不属于就忽略。另一个问题是检查点与外部状态的一致性。假设你的检查点记录“已处理到第37条”但外部数据库里第35条的数据被人工修改了。这时候从第37条继续可能会导致数据不一致。对于这种情况我的建议是检查点只记录进度不记录业务数据的快照。业务数据以外部系统为准续跑时重新读取。检查点的作用是告诉你“从哪继续”而不是“当时的数据长什么样”。4. 人工接管的接口设计让“交棒”不添乱4.1 失败通知要带够上下文自动化失败后如果系统决定交给人来处理第一件事是通知人。但很多系统的通知做得极其敷衍比如只发一句“任务失败请检查”。这种通知等于没发因为人还得自己去翻日志、找原因、定位进度。一个好的失败通知应该包含这些信息失败位置在哪个步骤、处理到哪个元素时失败的失败原因错误类型、错误信息、相关日志片段当前进度整体完成了多少还剩多少已产生的副作用已经做了哪些不可逆的操作建议操作是重试、跳过、还是人工处理把这些信息组织成一条消息推送到人能看到的地方。如果是即时通讯工具最好带上一个“一键继续”的链接或按钮让人不用登录服务器就能触发续跑。4.2 人工修正后的“回填”机制人工介入处理完失败点之后工作流需要从人工处理的结果继续往下走。这里的关键是人工处理的结果要能被工作流识别和消费。举个具体例子。假设你的工作流在“调用大模型评分”这一步失败了因为某个简历的文本格式异常导致模型返回了错误。人工介入后你手动给这份简历打了个分。现在工作流要继续处理剩下的简历它需要知道这份简历已经有人工评分了不要再调模型了。实现方式可以是在数据里加一个字段比如manual_override: true和manual_score: 85。工作流在处理每条数据时先检查这个字段有值就直接用没有才走自动流程。这样人工修正的结果就无缝地融入了后续流程。4.3 部分成功怎么算还有一种棘手的情况一个步骤处理了10个元素成功了7个失败了3个。这时候工作流应该算成功还是失败我的处理原则是能继续就继续不能继续的单独标记。也就是说不要因为3个失败就阻断整个流程。把成功的7个正常推进到下一步失败的3个记录下来等整个流程跑完之后再统一处理。这样至少保证了大部分工作能往前走而不是卡在一个点上。当然这要求你的流程设计是“元素级独立”的。如果元素之间有依赖关系比如第5个元素的处理需要第3个元素的结果那就不能这么简单处理了。所以在设计工作流的时候尽量让每个元素的处理是独立的这会大大降低失败处理的复杂度。5. 从工具层面看不同平台的续跑能力对比5.1 Coze、Dify这类工作流平台Coze和Dify这类平台的优势是可视化搭建节点之间的数据流转很直观。但它们在失败续跑方面的能力参差不齐。Coze的工作流目前对失败处理的支持比较基础主要是节点级的重试配置。你可以设置某个节点失败后重试几次、重试间隔多久。但它没有内置的检查点机制如果整个工作流在中途失败重新执行是从头开始的。对于短流程这没问题对于长流程就比较痛苦。Dify在这方面稍好一些它的工作流支持变量和会话状态可以在一定程度上实现断点续传。但需要你自己在节点里写逻辑来存取状态平台本身不自动帮你做这件事。如果你用这类平台搭建长流程我的建议是把长流程拆成多个短流程。比如把“拉取数据”做成一个工作流“处理数据”做成另一个“写入结果”再做成一个。每个短流程独立执行、独立重试。这样即使中间某个环节失败也不需要从头再来。5.2 Playwright、Appium这类自动化测试框架自动化测试框架的失败续跑是另一个典型场景。Playwright和Appium本身不提供检查点机制但它们的测试运行器通常支持“失败重试”和“只跑失败的用例”。以Playwright为例你可以在配置里设置retries: 2这样失败的用例会自动重试两次。但这是用例级的重试不是步骤级的。如果一个用例有20个步骤在第15步失败了重试是从第1步开始的。要做到步骤级续跑需要自己封装。一个常见的做法是把每个步骤的完成状态写到一个上下文对象里用例开始时先检查这个对象已经完成的步骤就跳过。这样虽然不能完全避免重跑但至少能跳过那些耗时的前置步骤。5.3 自建Agent调度系统如果你是自己写Agent调度逻辑那续跑的灵活性最高但工作量也最大。你需要自己实现检查点存储、状态恢复、失败通知、人工接管这一整套机制。我的建议是不要一开始就追求大而全。先从最简单的做起在流程的关键节点写一个进度文件失败后能从这个文件恢复。这个最简单的机制就能解决80%的问题。等真的有更复杂的需求了再逐步加上副作用记录、人工接管接口这些高级功能。6. 几个真实踩过的坑和对应的解法6.1 检查点文件被并发写坏了早期我做的一个数据同步工作流支持多个实例同时跑。结果发现检查点文件经常损坏续跑时读不出来。排查后发现是多个实例同时往同一个文件写检查点互相覆盖导致的。解法很简单每个实例用独立的检查点文件文件名里带上实例ID或进程ID。续跑时根据实例ID找到对应的检查点。如果实例是动态创建的那就用一个中心化的存储比如数据库来管理检查点用行级锁保证并发安全。6.2 续跑后重复发送了通知这个坑更隐蔽。工作流在处理完一条数据后会发送通知邮件检查点是在发送邮件之后写的。结果有一次在写检查点之前进程崩了续跑时从上一个检查点恢复导致最后一条数据的通知被重复发送。解法是把副作用操作和检查点写入放在一个事务里。要么都成功要么都失败。如果做不到事务那就把检查点写在副作用操作之前续跑时先检查副作用是否已经执行过。比如发邮件前先查一下发送记录已经发过的就跳过。6.3 Agent续跑后“失忆”了Agent场景下的续跑有个特殊问题Agent的上下文丢失了。比如一个Agent在前面几步通过工具调用获取了一些信息这些信息存在对话历史里。失败重启后对话历史没了Agent不知道之前发生了什么可能会重复调用工具或者做出错误的决策。解法是把Agent的关键上下文也纳入检查点。不只是记录“执行到第几步”还要记录“Agent当前知道什么”。具体来说就是把对话历史、工具调用结果这些信息序列化存下来续跑时恢复。当然这会让检查点变大需要权衡存储成本和恢复价值。6.4 人工接管后忘了“交还控制权”这个坑是流程设计的问题。人工介入处理完失败点后工作流应该自动继续。但有时候人工处理完就忘了触发续跑工作流一直停在那里。或者更糟的是人工处理的同时工作流也在重试两边同时操作导致数据冲突。解法是明确控制权的转移。工作流失败后进入“等待人工”状态这个状态下工作流不再自动重试。人工处理完后通过一个明确的动作比如点击按钮、调用接口把控制权交还给工作流。在“等待人工”状态下工作流的所有自动重试都要暂停。7. 一套可复用的失败续跑设计清单把上面的经验整理成一份清单你在设计任何AI工作流或Agent任务时都可以对照检查状态记录方面是否在关键节点写了检查点检查点是否包含进度、中间结果、副作用记录检查点写入是否原子化避免损坏检查点是否有批次标识避免跨批次误用失败检测方面是否有超时机制避免无限等待是否有循环检测避免Agent卡死是否有结果校验避免静默失败人工接管方面失败通知是否包含足够的上下文人工处理的结果是否能被工作流消费控制权转移是否有明确的机制续跑执行方面续跑时是否能正确恢复状态副作用操作是否有幂等性保证部分成功的情况下是否能继续推进这份清单不是要求每一条都做到而是帮你识别当前系统的薄弱环节。根据实际场景选择最重要的几条先落地比追求完美更重要。8. 写在最后的一点个人体会做AI自动化和Agent工作流这几年我最大的体会是自动化的价值不在于替代人而在于让人把精力花在真正需要人的地方。一个设计良好的自动化系统不是永远不出错而是出错之后能快速恢复让人只需要处理那20%的异常情况而不是被80%的重复劳动困住。“自动化失败后工作怎样继续”这个问题本质上是在问我们怎么和自动化系统协作是把所有控制权都交给它还是保留人在关键节点的介入能力我的答案是后者。至少在目前的技术水平下人机协作的混合模式比追求全自动无人值守更现实、更可靠。所以下次你的工作流又卡在87%的时候别急着骂它不争气。想想怎么给它加个存档点怎么让它在失败时优雅地喊你帮忙怎么让你帮完忙之后它能自己接着跑。这些看起来不起眼的机制才是自动化系统真正能落地的关键。