大数跨境

SEO2026第264期 | SEO / GEO 工作自动化部署与实践规范(二十八)

SEO2026第264期 | SEO / GEO 工作自动化部署与实践规范(二十八) 索未
2026-09-23
5

SEO2026第263期 | SEO / GEO 工作自动化部署与实践规范(二十八)

索未 · SEO | 规范与标准流程

本文核心议题

第(二十八)篇|从 Capability 到可靠事务:Command Bus、Execution State Machine、Idempotency 与 Saga

操作路径

01 —— AI Agent 获得执行权限后,如何确保 WordPress、GitHub、Cloudflare、Database 等跨系统动作不重复、不失控、可补偿、可恢复

02 —— 一、真正危险的不是 Tool 调用失败,而是你不知道它到底有没有成功

03 —— Step 1:建立 Execution Record

04 —— Step 2:GitHub 固化版本

05 —— Step 3:WordPress Draft

06 —— Step 4:Pre-Publish Validation

01 前面的治理链解决的核心问题:跨系统动作的可靠性

前面的治理链已经解决了一个极其重要的问题:AI Agent 获得执行权限之后,怎样让 WordPress、GitHub、Cloudflare、Database 等跨系统动作不重复、不失控、可补偿、可恢复。

Agent 不能因为“会调用工具”,就拥有直接修改生产环境的权力。

从 Evidence Plane、Risk Engine、Decision Trace,到 Action Gateway、Policy Enforcement Point,再到短生命周期、限定 Scope 的 Capability Token,我们逐步建立的是一条:

Evidence → Decision → Authorization → Enforcement 链路。

但到了这里,系统仍然没有真正完成生产化。因为 Capability Token 能证明:

这一次动作被允许执行。

它却不能证明:

这一次动作最终只执行了一次。

也不能保证:

当 WordPress 已成功、GitHub 超时、Database 已写入、Cloudflare 没有返回结果时,系统知道下一步到底应该继续、重试、暂停还是回滚。

更无法天然解决:

一个持续 20 分钟、2 小时甚至跨越人工审批窗口的自动化任务,在 Worker 重启、网络抖动、API 429、进程崩溃以后,怎样从正确位置继续,而不是从头再来一次。

因此,第(二十八)篇要解决的是 Governance Engine 之后更接近生产系统本质的问题:Execution Reliability(执行可靠性)。

如果说第(二十七)篇解决的是:

Who may cause a side effect?(谁可以引发副作用?)

那么第(二十八)篇解决的是:

Once a side effect is authorized, how do we make the execution reliable?(副作用被授权后,如何确保执行可靠?)

这意味着,我们需要在 Action Gateway 之后继续增加一层,它至少由四个核心机制组成:

Command Bus → Execution State Machine → Idempotency → Saga / Compensating Action

最终把一次“允许调用 Tool”,升级为一笔:可追踪、可去重、可重试、可补偿、可恢复的生产事务。

这也是从“AI Agent 自动化”真正走向“可靠生产系统”的分界线。

02 真正危险的不是 Tool 调用失败,而是结果未知

传统脚本最容易写成这样:

call WordPress API
call GitHub API
update database
purge Cloudflare cache
send notification

理想情况下是 A → B → C → D → E 全部成功。但生产环境真正发生的情况往往是:

A success
B success
C timeout
D ?
E not executed

这时最关键的问题并不是“C 报错了吗?”,而是:“C 到底执行了吗?”

这是分布式系统里非常典型、也极容易被自动化系统低估的问题。

例如 Agent 向 WordPress 发出创建文章请求:

POST /wp-json/wp/v2/posts

WordPress 已经完成文章创建,但响应返回途中连接断开。Agent 看到的是 Timeout。如果系统简单执行:

if timeout:
    retry()

那么第二次请求可能再次创建文章。于是第一次请求创建 Post #583,第二次请求创建 Post #584。从 Agent 看,一次任务终于成功;从 WordPress 看,两篇内容被创建。

这就是一个关键的工程事实:

Timeout 并不等于 Failure,它也可能意味着 Outcome Unknown(结果未知)。

HTTP 本身同样区分方法的幂等语义。RFC 9110 将 PUT、DELETE 和安全方法定义为幂等方法,并明确指出幂等性之所以重要,是因为客户端在连接中断、无法确定响应结果时能够安全重试。但这并不意味着应用层所有副作用天然都具有这种保证。

对于创建 WordPress 内容、创建 GitHub PR、修改 DNS、更新数据库、触发部署、清理 CDN Cache、发送 Email、提交表单等操作,真正危险的不是明确的 FAILED,而是 UNKNOWN。因为 FAILED 可以处理,而 UNKNOWN 如果被误认为 FAILED,会造成重复执行;如果被误认为 SUCCESS,又会造成流程永久缺失一步。

所以生产级执行系统不能只有 success / failed,而必须建立 Execution State Machine(执行状态机)。

上一章的 Capability Token 本质上是授权凭证,它回答 Publisher Agent 是否有权在指定范围内创建 WordPress Draft,但它没有完整描述现在这一笔具体事务是什么。因此 Action Gateway 不应该拿到 Capability 后直接调用 WordPress,中间还需要一个更稳定的执行抽象,例如:

{
  "command_id": "cmd_20260923_0028_01",
  "workflow_id": "wf_article_0028",
  "saga_id": "saga_publish_0028",
  "decision_id": "dec_0028_publish",
  "capability_id": "cap_wp_draft_7821",
  "command_type": "CREATE_WORDPRESS_DRAFT",
  "target": {
    "system": "wordpress",
    "resource": "post"
  },
  "payload_ref": "artifact://article/0028/v1",
  "idempotency_key": "wp:create:article-0028:v1",
  "preconditions": {
    "editorial_status": "approved",
    "content_version": "v1"
  },
  "timeout_policy": "...",
  "retry_policy": "...",
  "compensation_policy": "...",
  "created_at": "...",
  "expires_at": "..."
}

这时系统管理的就不再只是 HTTP Request(传输行为),而变成 Business Command(业务意图)。HTTP Request 本身并不能告诉系统这是第28篇文章第一次创建、自动重试、人工重新触发,还是某个失败事务恢复后的再次执行。而带有 command_id 和 idempotency_key 的 Command 则可以把一次 API 调用放回完整业务上下文。

因此,本项目下一步需要建立 Command Bus。这里的 Command Bus 不应简单理解为 Kafka、RabbitMQ 等具体中间件,它首先是一种架构边界。所有真正会改变外部世界状态的动作(如 WordPress Create/Update/Publish、GitHub Commit/PR、Cloudflare Purge/DNS 等),原则上都不再允许 Agent → Tool 直接执行,而变成:

Agent
  ↓ Decision
  ↓ Capability
  ↓ Action Gateway / PEP
  ↓ Command Bus
  ↓ Execution Orchestrator
  ↓ System Adapter
  ↓ External System

这样做以后,Agent 不再控制怎么重试、重试几次、是否重复、失败是否回滚、执行进度存在哪里。Agent 只表达 Intent(意图),执行基础设施负责 Execution Semantics(执行语义)。

这实际上完成了一次重要的职责分离:Agent 决定“想做什么”,Governance Engine 决定“是否允许做”,Execution Plane 决定“怎样可靠地做完”。

当前项目已经存在内容生命周期(DISCOVERED → QUALIFIED → ... → PUBLISHED → MONITORING),第(二十八)篇需要再增加另一套状态机。它管理的不是内容处于什么阶段,而是某一个已经授权的生产 Command 执行到了什么阶段。

一个更完整的状态模型如下:

RECEIVED
  ↓
VALIDATING
  ↓
AUTHORIZED
  ↓
QUEUED
  ↓
DISPATCHING
  ↓
RUNNING
  ↓
──────────────────────────────
│          │           │
SUCCESS  RETRY_PENDING  OUTCOME_UNKNOWN
│          │           │
│          └──────→ RUNNING │
│                    ↓       │
│              RECONCILING   │
│                    │       │
│          ┌─────────┴────────┐
│          ↓                  ↓
│       SUCCESS             FAILED
│                            │
│                 ┌──────────┴────────┐
│                 ↓                   ↓
│          COMPENSATING          NEEDS_REVIEW
│                 ↓
│           COMPENSATED
↓
COMPLETED

这里尤其值得增加一个过去自动化系统经常忽略的状态:OUTCOME_UNKNOWN。例如 API timeout、connection reset、worker crashed after send、response lost,都不应该立刻解释成 FAILED,而应该进入 OUTCOME_UNKNOWN → RECONCILING,先检查外部系统(Did the side effect already happen?)。确认没有发生再重试,确认已经发生则恢复为 SUCCESS。这一步能够消灭大量“重试导致重复生产”的问题。

这也是第(二十八)篇最关键的概念之一:Idempotency(幂等性)。很多系统把幂等理解为给 API 请求加一个 UUID,这远远不够。真正的幂等目标是:execute(command) 执行多次,最终产生的业务状态仍然等价于 execute(command) 执行一次。

也就是说:同一个业务命令无论因为 Retry、Worker Restart、Message Redelivery、Network Timeout 或 Operator Replay 被执行多少次,都只能产生一次预期业务效果。

在分布式系统里,消息重复、响应丢失和 Worker 重启本来就应该被当成正常故障模型。因此,更现实的生产目标不是简单宣称 Exactly Once Delivery,而是通过 At-least-once execution + Idempotent consumer + Deduplication + Execution journal + Reconciliation 努力实现底层动作可能被尝试多次,但业务结果只出现一次。

假设每次重试都生成 UUID(),那么 try 1 → key_A,try 2 → key_B,这对执行系统来说是三个不同命令,根本无法去重。真正合理的 Idempotency Key 应该来自 Business Operation Identity,例如:

wordpress:create:article-0028:v1
github:create-pr:article-0028:v1
database:publish-record:article-0028:v1
cloudflare:purge:article-0028:v1

于是同一个逻辑动作无论重新进入多少次,都映射到同一执行记录。这就是 Idempotency 真正开始进入生产语义的地方。

因此,仅有日志仍然不够。普通日志回答“发生过什么?”,Command Registry 或 Execution Journal 则应该回答“这个业务动作现在到底是什么状态?”。项目当前已要求 Automation Job 记录 job_id, status, retry_count, error_type 等,下一阶段可进一步扩展,记录 external_resource_id(如 WordPress post_id 583)。这样即使 Worker 崩溃,系统也能通过 command_id → execution record → post_id 583 重新恢复上下文。前者即使进程死亡,事务仍然存在;后者进程一死,系统就失忆。

自动化系统里非常危险的一段代码是 `except Exception: retry()`。因为并不是所有错误都应该重试。需要至少区分五类结果:

类型 示例 默认策略
Success API 2xx + 已验证 Commit
Transient Failure 429、503、临时网络故障 Backoff + Retry
Permanent Failure 权限拒绝、Schema 错误 Stop
Business Failure Quality Gate 未通过、状态冲突 Review / Reject
Outcome Unknown Timeout、连接中断、Worker Crash Reconcile First

因此,Retry 之前应该先执行 Classify Failure,而 OUTCOME_UNKNOWN 之前更不能盲目重试。正确流程应是:UNKNOWN → Check execution record → Check external system → Already applied? (Yes → Success, No → Retry)。

假设一次发布事务包含:1. Database 创建发布记录,2. GitHub 保存内容版本,3. WordPress 创建文章,4. WordPress 正式发布,5. Cloudflare 清理缓存,6. Database 更新 published 状态,7. Monitoring 创建观察任务。如果前 3 步成功,第 4 步失败,且没有重复动作(Idempotency 正常),系统仍然进入局部失败状态。这时候需要解决的是:已经成功的 1、2、3 怎么办?传统单数据库事务可以 ROLLBACK,但跨系统不存在共同的数据库事务。这就是 Saga 进入系统的地方。

Saga 将一个跨服务事务拆分为一系列本地事务;每一步在自己的服务中完成,如果后续步骤失败,则使用补偿事务处理前面已完成步骤造成的影响。Global Transaction 被拆成 T1 → T2 → T3 → T4 → T5,每一步定义 Forward Action + Compensating Action。例如:

T1: Create WP Draft      C1: Trash WP Draft
T2: Create GitHub Branch C2: Delete Temporary Branch
T3: Create Deployment Record C3: Mark Deployment Cancelled

如果 T1 success, T2 success, T3 failure,Saga 可以执行 C2, C1,把系统带回一个 Business-Consistent State(业务一致状态)。注意,这里不是恢复到原始状态。数据库 rollback 可以撤销尚未提交的事务,但现实世界的副作用经常已经被别人看见(如文章已发布、搜索引擎已抓取)。这时只能创建新的动作抵消前面的业务影响。补偿并不一定把系统精确恢复到原始状态,补偿逻辑通常是业务相关的,且补偿本身也需要记录进度并设计为可重复执行。

因此,Command Registry 最好进一步为动作定义四种事务属性:COMPENSABLE(可补偿)、RETRYABLE(可重试)、IRREVERSIBLE(不可逆)、PIVOT(枢纽/不可回退边界)。Pivot 之后,更重要的往往不再是回滚,而是保证后续步骤最终完成。

动作 类型 处理思路
创建 WP Draft Compensable Trash / Abandon
创建临时 Git Branch Compensable Delete Branch
WordPress Publish Pivot / Externally Observable 谨慎补偿
Cloudflare Purge Retryable 重复完成即可
Email Send Irreversible 尽量放最后

工作流设计应主动把容易撤销的动作放在前面,把不可逆动作尽可能放在最后。这是非常重要的生产原则。

对于 Saga 的实现,Choreography(编排)让各参与服务通过事件自行协作,而 Orchestration(协调)由中心协调器掌握事务流程。对于当前 SEO/GEO Automation 项目,这些系统并非围绕同一个 Event Domain 原生构建的微服务,因此更适合采用 Orchestration(Execution Orchestrator),显式掌握 next step, retry, timeout, compensation 等。这也与现有项目架构中已经定义的 Orchestrator Agent 职责一致。

一个生产级 Saga 最不能接受的是“发生事故 → 再研究怎么回滚”。正确方法是在 Command Definition 阶段就明确 forward_action, compensation_action, pivot, retry_policy, verification。并且特别值得注意:补偿动作也必须幂等。因为可能发生 Forward failed → compensation started → compensation timeout → compensation retry,如果补偿本身不是幂等,系统可能因为“修复失败”制造新的故障。

此外,很多工程师第一反应是“任何一步失败 → rollback all”,这实际上是在用单数据库事务思维理解分布式系统。生产环境应该先判断 Can we continue forward safely? 恢复策略应该更像:Transient? → Retry;Outcome Unknown? → Reconcile;Forward path still safe? → Continue;Pre-pivot unrecoverable? → Compensate;Post-pivot? → Prefer forward recovery;High-risk ambiguous? → Human intervention。

并发控制也是关键。假设 publish article v3 和 update article v4 同时开始,由于 v3 overwrites v4,这不是重复执行,而是并发冲突。因此还需要 resource version, expected version, optimistic lock 等机制。执行前检查 current_version == expected_version? 如果不符则 CONFLICT → NEEDS_REVIEW。这也是为什么 Saga 并不能等同于 ACID Transaction。

03 实践步骤解析

Step 1:建立 Execution Record

Database CREATE execution,记录 workflow_id, saga_id, article_id, version, decision_id, capability_id。这是整个事务的根。

Step 2:GitHub 固化版本

Command: ARCHIVE_CONTENT_VERSION,Idempotency: github:article-0028:v1。成功后记录 commit_sha, branch, artifact_hash。如果这一步失败,Retry or Stop。由于还没有外部发布,风险较低。

Step 3:WordPress Draft

Command: CREATE_WORDPRESS_DRAFT,Idempotency: wordpress:draft:article-0028:v1。执行成功后,将 post_id = 583 写回 Execution Journal。如果 Worker 此时崩溃,系统恢复后不会 Create New Post,而是 lookup command → found SUCCESS → reuse post_id 583。

Step 4:Pre-Publish Validation

对 title, metadata, schema, links, source citations, featured image, content hash 执行核验。如果失败,进入 NEEDS_REVIEW,而不是继续 Publish。这符合当前项目对正式发布默认保留人工终审的要求。

Step 5:Human Approval 与权限重校验

审批本身进入 Execution Journal,记录 reviewer, approved_at, approved_version, content_hash。这里尤其应该绑定 approved_version,防止 Agent silently changed to v2 then Publish v2。因此批准的不是抽象的 article,而是 article_version + hash。

这里延伸出一个关键问题:假设 Capability expires_at = 09:30,但 Human approval 在 10:30 完成。不能因为 Workflow already started 就默认权限一直有效。每个真正高风险副作用执行前,都应该重新检查 Capability valid? Decision still valid? Resource version unchanged? 形成 Authorize at workflow start + Revalidate at side-effect boundary。即:长期运行事务中的权限不是一次性事实,而是需要在关键执行边界重新验证的动态前提。

在真正 Publish 之前,重新验证 capability, decision, content hash, current post state,然后执行 PUBLISH_WORDPRESS_POST。如果返回 200 SUCCESS,记录 post_status = publish, published_at, post_url。Saga 进入 POST_PIVOT。从这一刻开始,后续故障默认策略不再是 Rollback everything,而应该优先 Forward Recovery。

例如 WordPress publish success 但 Cloudflare request timeout,错误做法是 Publish failed → rollback WordPress;正确状态应该是 ARTICLE_PUBLISHED, CACHE_STATE_UNKNOWN,然后 Cloudflare command → OUTCOME_UNKNOWN → RECONCILING → Retry。

04 状态对账与事务外箱模式

假设 WordPress = published,Cloudflare = complete,但 Database Publication Record = timeout。如果系统只看内部 Database 发现 status != published,它可能判断文章没发布,下一轮任务再次发布。这就是状态不一致。因此必须引入 Reconciliation Engine,执行 WordPress reality, GitHub reality, Cloudflare reality 与 Internal journal 之间的对账。最终由外部事实恢复内部状态,而不是再发布一次。

即便建立 Command Bus,还存在经典的双写一致性问题。例如 Database commit success 但 Message send failed,导致状态显示 QUEUED 实际没有消息。AWS 的 Transactional Outbox Pattern 正是针对此类问题:业务数据和 Outbox Event 在同一个本地数据库事务中提交,然后由独立进程(Outbox Relay)负责可靠地把 Outbox 内容送入消息系统。即使 Relay 崩溃,Outbox Event 仍然存在,重新启动后继续发送即可。如果消息重复发送,由 idempotent consumer 负责去重。

05 完整架构与生产原则

到这里,我们可以把第(二十六)至第(二十八)篇真正连起来。完整链路从 LLM → Tool → Production 升级成包含 Evidence Plane, Risk Engine, Governance Decision, Command Bus, Execution State Machine, Saga Orchestrator (含 Idempotency Registry, Execution Journal, Outbox/Inbox, Retry Engine, Compensation Registry, Reconciliation Engine, Human Intervention Queue), System Adapters 的 Execution Transaction Plane。

很多团队会觉得发布文章没必要这么复杂。但这种判断只在“每天人工执行一两个动作”时成立。一旦开始自动化,每天产生几十、几百甚至几千个 Side Effect 后,小概率故障一定会不断出现。真正需要防止的不是 API 永远不失败,而是任何 API 失败以后,系统仍然知道自己在哪里。

从本篇开始,每一个具有真实副作用的自动化,应完整定义为包含 COMMAND, DECISION, TARGET, IDEMPOTENCY, EXECUTION, VERIFY, COMPENSATION, TRANSACTION, OBSERVABILITY, RECOVERY 等维度的规范。这不是另起炉灶,而是在当前项目已有自动化原则之上增加执行级语义,将 Retry, Failure Handling, Rollback 从规范字段真正提升为 Execution Architecture。

进入这一阶段以后,系统应该明确禁止以下模式:

  • Agent → Production API(绕过 Command Bus)
  • timeout → blind retry(不区分 Outcome Unknown)
  • random idempotency key on every attempt(让幂等形同虚设)
  • process memory = workflow state(进程死亡后任务失忆)
  • failure → rollback everything(不区分 Pivot 与不可逆动作)
  • compensation = delete(把复杂业务恢复错误理解成机械反向操作)

只要这些模式仍然存在,系统就仍然是“自动执行脚本”,而不是“可靠事务系统”。

06 总结:从决策可靠到执行可靠

AI Agent 领域很容易把 Reliability 理解为模型少犯错、Prompt 更严格等,这些属于 Decision Reliability,而不是 Execution Reliability。一个模型完全可能判断正确、权限正确、工具正确,最后仍然因为 timeout, duplicate delivery, worker crash 制造生产事故。

因此成熟 Agent Architecture 需要至少区分 Reasoning Reliability, Governance Reliability, Execution Reliability。前三篇实际上正在完成这三层的拆解:第(二十六)篇解决“为什么允许”,第(二十七)篇解决“谁被允许执行什么”,第(二十八)篇解决“允许之后怎样可靠完成”。

第(二十七)篇结束时我们说:没有 Enforcement Point,Policy 只是建议。第(二十八)篇结束以后,还需要增加一句:没有 Durable Execution,Authorization 只保证动作“合法开始”,却不能保证它“可靠结束”。

真正成熟的自动化系统不能只回答 Can this Agent execute? 还必须持续回答:Has this command already executed? What exactly succeeded? What remains unfinished? Is the result unknown? Can it be retried safely? 只要其中任何一个问题系统无法回答,所谓 Fully Autonomous Agent 都仍然只是一个能够连续调用 API 的程序,而不是一个真正能够承担生产责任的执行系统。

第(二十八)篇真正完成的升级是:Tool Call → Authorized Tool Call → Governed Command → Durable Command → Idempotent Command → Saga Transaction → Recoverable Production Workflow。

系统的关注点从“执行成功了吗?”升级成“这笔生产事务当前处于什么状态,系统是否知道事实,是否可以安全继续,最终是否能够收敛到一个一致状态?”

可靠系统并不是“从来不失败”的系统,而是即使任意一步失败,它仍然知道已经发生了什么、下一步应该做什么,以及怎样安全地恢复。

07 第(二十九)篇预告

当 Command Bus、Execution State Machine、Idempotency、Saga 与 Compensation 建立以后,下一个问题自然出现:如果内部状态写着 SUCCESS,但 WordPress 实际不存在;如果 Worker 永久死亡留下 RUNNING 任务;如果补偿只完成一半;如果 DLQ 中积累了几十个无人处理的命令,系统怎样主动发现这些“幽灵事务”?

因此第(二十九)篇最自然的方向是进入 Reconciliation & Healing(对账与自愈),解决状态漂移、孤儿任务、永久失败、补偿失败和人工修复的问题。也就是从 Recoverable Execution 进一步进入 Operational Recoverability,让系统能够持续发现异常、自动对账、自动修复,并把真正无法自动解决的问题准确交给人。

08 来源与延伸阅读

本文中的 Command Bus、Execution Transaction Plane、Command Registry、Capability 与 Saga 的组合方式属于本项目架构设计;Saga、Compensating Transaction、HTTP Idempotency 与 Transactional Outbox 的基础机制则参考现有分布式系统标准与主流云架构实践:

  • Microsoft Azure Architecture Center: Saga Distributed Transactions Pattern; Compensating Transaction Pattern.
  • AWS Prescriptive Guidance: Saga Patterns / Saga Orchestration; Transactional Outbox Pattern.
  • RFC 9110: HTTP Semantics §9.2.2 Idempotent Methods.

推荐阅读:

SEO2026第263期 | SEO / GEO 工作自动化部署与实践规范(二十七)

SEO2026第262期 | SEO / GEO 工作自动化部署与实践规范(二十六)

SEO2026第260期 | SEO / GEO 工作自动化部署与实践规范(二十五)

【声明】内容源于网络
0
0
索未
各类跨境出海行业相关资讯
内容 906
粉丝 0
索未 各类跨境出海行业相关资讯
总阅读35.5k
粉丝0
内容906