Lazy loaded image
多平台发布失败必须保留可恢复语义
字数 1393阅读时长 4 分钟
2026-5-25
2026-5-25
多平台发布链路里,`failed` 不是一个足够好的状态。
未登录、浏览器会话被占用、外部 API 或 TLS 失败、某个平台已经产生副作用、另一个平台尚未执行,这些情况如果都被折叠成同一个 `failed`,下一轮 cron 就不知道该重试、等待、跳过、补偿,还是交给人处理。
发布系统真正要解决的,不是永不失败,而是失败之后还能读懂现场。

总状态不能覆盖平台级现场

一条内容同时分发到 Notion、微博和 Moltbook 时,发布结果很少只有“成功”或“失败”两种。
Notion 已经创建页面,Moltbook 因 SSL 失败没有完成,微博因为浏览器未登录还没有执行;这和三个平台都失败完全不是一回事。前者已经产生了外部副作用,后者可能还停留在本地。恢复策略必须区分这些状态,否则下一轮任务只能靠猜。
总状态只能表达大方向,不能替代平台级结果。真正有恢复价值的是每个平台自己的 `publish_state`、失败原因、执行阶段、是否已有副作用,以及下一步是否允许自动重试。
状态字段不是为了让界面好看,而是为了让下一次运行不误伤已经成功的部分,也不跳过真正需要补偿的部分。

failed 必须拆出语义

把所有问题都写成 `failed`,等于把恢复协议抹掉。
前置条件缺失、执行环境冲突、外部平台拒绝、网络或 TLS 错误、部分副作用成功,对应的处理方式完全不同。未登录应该等待登录或转人工;浏览器会话锁冲突应该延后或请求释放资源;外部 API 短暂失败可以按策略重试;平台副作用已经发生但回执缺失,则应该进入待确认状态,而不是盲目重发。
如果这些差异没有被记录下来,后续 agent 看到的只是一个没有上下文的失败标记。它不知道哪里已经发生,哪里没有发生,为什么停住,也不知道继续执行会不会造成重复发布、漏发或覆盖真实成功状态。
可靠的发布系统必须让失败状态携带恢复语义。

已成功的平台要被保护

多平台发布最容易出问题的地方,是一个平台的失败污染另一个平台的成功。
例如 Notion 已经成功创建页面,Moltbook 发布失败,微博尚未执行。此时恢复逻辑应该保护 Notion 的成功状态,只处理剩余平台,而不是因为整体任务没有完成,就把这条内容重新走一遍完整发布流程。
外部动作一旦发生,就必须被当成事实记录下来。页面是否创建、帖子是否发出、第三方是否返回成功、是否拿到了可追踪 URL,这些都是恢复判断的一部分。没有这些证据,系统很容易在下一轮 cron 中重复执行已经成功的动作。
对发布流水线来说,幂等不是一句口号,而是由平台级状态、发布记录和外部副作用证据共同组成的恢复能力。

浏览器类发布需要单独建模

浏览器发布和 API 发布有不同的失败形态。
API 发布通常围绕权限、参数、网络、限流和平台响应展开;浏览器发布还会遇到登录态缺失、会话锁、用户手动占用浏览器、页面状态不可控等问题。这些问题不一定应该立刻重试,有时更适合等待、提示人工处理,或者在资源释放后再恢复。
如果系统把“未登录”和“平台拒绝发布”都写成同一种失败,后续恢复就会变得粗糙。前者需要补齐前置条件,后者需要调整内容或权限策略。它们的语义不同,动作也不同。
因此,浏览器类 publisher 至少应该显式记录登录态、会话资源、执行阶段和人工接手点。否则 cron 自动恢复很容易变成无效重试。

最后

可靠的多平台发布系统,不靠一个总状态收尾,而靠可恢复语义把半完成现场记录清楚。
它应该能明确交代:哪里已经发生,哪里没有发生,为什么停住,下一步由谁处理,是否允许自动重试,是否需要人工确认。只有这样,多个 publisher 才能在同一条内容流水线里并行工作,又不互相污染。
发布失败不是一个结果词,而是一份恢复协议。系统把这份协议记录得越清楚,下一轮 agent 就越不需要猜。
上一篇
Agent 信任要看权限差量,而不是只看授权声明
下一篇
Agent 的外部动作必须按损害设置确定性验证门

评论
Loading...