AI Agent 真正进入生产环境后,难点往往不在于能否调用模型,而在于一次跨越多个工具、服务和步骤的任务,能否在进程崩溃、网络超时或人工介入后继续执行,并且让团队确认这段执行历史没有被悄悄改写。Diagrid Catalyst 2.0 的重点,正是把 Dapr 提供的恢复能力、签名工作流历史和执行证明引入 Agent 工作流。
这类能力改变了架构讨论的重点:Agent 不再只是一个带工具调用循环的应用,而更像一个需要持久化状态、可审计事件和明确恢复语义的分布式工作流。
Durable Execution 解决的不是“记住上下文”
普通 Agent 通常把消息列表保存在数据库中,失败后重新把上下文交给模型。这种方式只能恢复对话内容,不能可靠恢复执行过程。模型可能重新调用已经成功的支付接口、重复发送通知,或者在外部副作用已经发生后选择另一条路径。
Durable execution 关注的是更窄也更关键的问题:
- 哪些步骤已经完成,结果是什么?
- 哪些步骤可以安全重试?
- 外部副作用是否具备幂等键?
- 工作流在第几个检查点停止?
- 恢复时应该重放历史,还是从某个持久化状态继续?
可以把一次 Agent 任务抽象成一串带状态的活动:
plan -> read_customer -> create_invoice -> send_email -> completed
|
+-- retryable failure
其中 create_invoice 和 send_email 可能已经触发外部副作用。仅仅重新运行 Python 函数并不等于恢复。生产实现需要为活动保存输入、输出、状态和幂等标识,并让重试策略与业务语义匹配。
Dapr 的分布式原语可以帮助应用组织状态存储、服务调用、发布订阅和工作流执行,但具体恢复行为仍取决于工作流引擎、存储后端和活动实现。架构评估时不能只看“支持 durable”这个标签。
可验证执行:从日志走向证据
传统日志主要回答“系统当时打印了什么”。签名工作流历史则试图回答“这份历史是否仍然可信”。如果每个事件都关联前一个事件的摘要,并由可信密钥签名,就可以形成一条不可轻易篡改的执行链。一个简化的事件结构如下:
{
"workflow_id": "invoice-8472",
"sequence": 3,
"event_type": "activity.completed",
"activity": "create_invoice",
"result_hash": "sha256:...",
"previous_event_hash": "sha256:...",
"signature": "base64:..."
}
这类历史可以服务于审计、故障调查和合规证明,但它不自动证明业务结果正确。签名只能证明某个持有私钥的组件签署了某个事件;它不能证明工具返回的数据真实,也不能证明 Agent 的决策符合公司的业务规则。因此,执行证明应与工具授权、输入校验、策略检查和人工审批结合使用。
密钥生命周期同样重要。生产系统需要明确签名密钥由谁托管、如何轮换、如何撤销,以及验证方如何获取对应公钥。把私钥放进应用镜像或普通环境变量,会让“可验证”失去实际价值。
与框架原生能力和工作流引擎比较
Catalyst 2.0 覆盖多个 Agent 框架,这对希望保留现有框架的团队有吸引力。但跨框架层也会引入抽象边界,至少需要比较以下三类方案:
| 方案 | 优势 | 需要核验的问题 |
|---|---|---|
| Agent 框架原生持久化 | 接入简单,保留框架语义 | 崩溃恢复、重试和副作用管理是否完整 |
| Diagrid Catalyst 2.0 | 通过 Dapr 组织恢复、历史和执行证明,并覆盖多个框架 | 框架适配范围、延迟、运维复杂度和证据格式 |
| 成熟工作流引擎 | 状态机、重试、定时器和可观测性通常较成熟 | Agent 集成成本、模型调用封装和平台运营成本 |
不要只用一次成功演示做选择。至少应设计包含以下情况的基准:模型调用超时、活动进程被杀、重复投递、状态存储短暂不可用、工具成功但响应丢失、签名验证失败,以及人工审批等待数小时。要记录恢复延迟、重复副作用数量、状态存储成本、端到端延迟和运维操作步骤。
一个可改造的最小工作流示例
下面的示例用 Python 表达 durable Agent 的核心结构。它是一个框架无关的最小实现,假设 store 提供持久化检查点,send_email 支持幂等键。接入具体 Agent 框架或 Dapr 工作流 SDK 时,可以把 run_activity 和 checkpoint 替换成对应 API。
运行前需要把通知服务替换为真实实现;示例中的内存字典只用于展示流程,进程退出后不会保留状态。
from dataclasses import dataclass, field
from typing import Any
import hashlib
import json
@dataclass
class WorkflowState:
completed: dict[str, Any] = field(default_factory=dict)
events: list[dict[str, Any]] = field(default_factory=list)
store: dict[str, WorkflowState] = {}
def checkpoint(workflow_id: str, state: WorkflowState) -> None:
# 生产环境应写入持久化状态存储,并使用事务或版本号防止并发覆盖。
store[workflow_id] = state
def run_activity(
workflow_id: str,
state: WorkflowState,
name: str,
input_data: dict[str, Any],
fn,
) -> Any:
if name in state.completed:
return state.completed[name]
result = fn(input_data)
previous = state.events[-1]["hash"] if state.events else "genesis"
event = {
"activity": name,
"input": input_data,
"result": result,
"previous": previous,
}
event["hash"] = hashlib.sha256(
json.dumps(event, sort_keys=True).encode()
).hexdigest()
state.events.append(event)
state.completed[name] = result
checkpoint(workflow_id, state)
return result
def create_invoice(data: dict[str, Any]) -> dict[str, str]:
# 真实服务应使用 data["idempotency_key"] 防止重复开票。
return {"invoice_id": f"inv-{data['customer_id']}"}
def send_email(data: dict[str, Any]) -> str:
# 真实服务应按 idempotency_key 去重。
return f"sent:{data['invoice_id']}:{data['idempotency_key']}"
def run_invoice_agent(workflow_id: str, customer_id: str) -> WorkflowState:
state = store.setdefault(workflow_id, WorkflowState())
invoice = run_activity(
workflow_id, state, "create_invoice",
{"customer_id": customer_id,
"idempotency_key": workflow_id},
create_invoice,
)
run_activity(
workflow_id, state, "send_email",
{"invoice_id": invoice["invoice_id"],
"idempotency_key": workflow_id},
send_email,
)
return state
if __name__ == "__main__":
result = run_invoice_agent("invoice-8472", "customer-19")
print(json.dumps(result.events, indent=2))
这个实现展示了三个关键约束:已完成活动不会因为恢复而重复执行;每个检查点都带有前序事件摘要;外部副作用使用工作流级幂等键。真实系统还需要把哈希链升级为非对称签名,并处理并发、版本迁移、超时、补偿操作和密钥轮换。
落地前的检查清单
在选择 Catalyst 2.0 或其他 durable workflow 方案前,可以按下面的顺序验证:
- 列出 Agent 的每个外部副作用,并为每个副作用定义幂等策略或补偿动作。
- 明确检查点保存什么:模型消息、工具参数、工具结果、策略判断,还是完整事件历史。
- 用故障注入测试进程终止、网络分区、超时和重复投递,而不是只测试正常路径。
- 核对签名算法、密钥托管、公钥分发、轮换和验证失败后的处理。
- 比较框架原生能力、Catalyst 适配层和成熟工作流引擎的延迟、成本及运维负担。
- 要求基准数据说明测试规模、模型、工具数量、存储配置和恢复目标。
Catalyst 2.0 的价值主张适合被理解为一组生产工程能力:让 Agent 更容易恢复,让执行历史更容易核验。是否值得采用,取决于这些能力能否覆盖团队最危险的失败模式,并且以可接受的延迟、成本和运营复杂度交付。
结语
Agent 的可靠性最终不是由提示词长度决定的,而是由状态、重试、副作用、证据和运维流程共同决定的。durable execution 可以减少故障后的人工接管,签名历史可以提高审计可信度,但二者都不能替代幂等设计、权限控制和真实的故障测试。把这些边界测清楚,再决定采用 Catalyst、框架原生能力还是成熟工作流引擎,通常比追逐单一功能名称更稳妥。