一、引言:当 Agent 需要跑 25 小时
OpenAI 的 Harness Engineering 实验中有一个令人震惊的数据:
Codex Agent 的最长单次运行时间达到了 25 小时。
这意味着 Agent 需要:
- 在长时间运行中保持稳定
- 在故障后能够恢复继续
- 在资源变化时能够自适应
这就是**持久化执行(Durable Execution)**的核心挑战。本文将深入探讨长时运行 Agent 的状态管理技术。
二、为什么需要持久化执行?
2.1 长时运行任务的典型场景
场景
持续时间
特点
大型代码库重构
数小时
涉及多个模块,需要保持一致性
复杂系统生成
数小时到数天
从零构建完整系统,步骤繁多
深度代码审查
数小时
分析大量代码,识别潜在问题
自动化测试生成
数小时
为遗留代码生成完整测试覆盖
数据迁移和转换
数小时到数天
处理大量数据,保证完整性
2.2 传统方式的局限
┌─────────────────────────────────────────────────────────┐
│ 传统方式的局限 │
├─────────────────────────────────────────────────────────┤
│ │
│ 问题 1:进程崩溃导致任务失败 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Agent 运行中... │ │
│ │ [===========> ] 35% │ │
│ │ │ │
│ │ *进程崩溃* │ │
│ │ │ │
│ │ 结果:所有进度丢失,需要从头开始 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 问题 2:资源不足导致任务中断 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Agent 运行中... │ │
│ │ [===================> ] 60% │ │
│ │ │ │
│ │ *内存不足,进程被杀死* │ │
│ │ │ │
│ │ 结果:任务中断,进度无法恢复 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 问题 3:网络中断导致外部调用失败 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Agent 调用外部 API... │ │
│ │ [========================> ] 75% │ │
│ │ │ │
│ │ *网络超时* │ │
│ │ │ │
│ │ 结果:调用失败,任务无法继续 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
2.3 持久化执行的核心价值
- 可靠性:故障后可恢复,不丢失进度
- 弹性:支持动态资源调整
- 可观测性:全程状态可追踪
- 效率性:避免重复工作
三、持久化执行的核心概念
3.1 什么是持久化执行?
持久化执行(Durable Execution)是指将任务的执行状态定期持久化到存储中,使得任务在故障后可以从上次保存的状态恢复继续执行,而不是从头开始。
┌─────────────────────────────────────────────────────────┐
│ 持久化执行 vs 普通执行 │
├─────────────────────────────────────────────────────────┤
│ │
│ 普通执行 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 开始 → 步骤1 → 步骤2 → 步骤3 → ... → 完成 │ │
│ │ ↑ │ │
│ │ └── 崩溃,全部丢失 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 持久化执行 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 开始 → 步骤1 → [CP] → 步骤2 → [CP] → 步骤3 → ... │ │
│ │ ↑ ↑ │ │
│ │ │ └── 崩溃,从这里恢复 │ │
│ │ └── 检查点(Checkpoint) │ │
│ │ │ │
│ │ [CP] = Checkpoint,定期保存状态 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
3.2 核心概念
概念
说明
作用
检查点(Checkpoint)
任务执行状态的快照
故障恢复的基础
状态(State)
任务当前的完整上下文
恢复后继续执行的依据
事件(Event)
任务执行过程中的关键动作记录
重放和审计
工作流(Workflow)
任务的完整执行计划
确定执行顺序和依赖
活动(Activity)
工作流中的单个执行单元
可重试、可补偿的操作
四、持久化执行架构设计
4.1 整体架构
┌─────────────────────────────────────────────────────────┐
│ 持久化执行系统架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 工作流引擎(Workflow Engine) │ │
│ │ │ │
│ │ • 解析工作流定义 │ │
│ │ • 调度活动执行 │ │
│ │ • 管理执行状态 │ │
│ │ • 处理故障恢复 │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────┼───────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 状态存储 │ │ 事件存储 │ │ 检查点存储│ │
│ │ │ │ │ │ │ │
│ │ 当前状态 │ │ 执行历史 │ │ 状态快照 │ │
│ │ 变量值 │ │ 活动记录 │ │ 恢复点 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │
│ └───────────┼───────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 活动执行器(Activity Worker) │ │
│ │ │ │
│ │ • 执行具体任务(代码生成、测试等) │ │
│ │ • 报告执行结果 │ │
│ │ • 支持超时和重试 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
4.2 状态管理设计
┌─────────────────────────────────────────────────────────┐
│ 状态管理层次 │
├─────────────────────────────────────────────────────────┤
│ │
│ 第 3 层:业务状态 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ • Agent 的当前目标 │ │
│ │ • 已完成的子任务列表 │ │
│ │ • 生成的代码文件 │ │
│ │ • 中间计算结果 │ │
│ └─────────────────────────────────────────────────┘ │
│ ↑ │
│ 第 2 层:执行状态 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ • 当前执行的活动 │ │
│ │ • 活动执行进度 │ │
│ │ • 等待的外部事件 │ │
│ │ • 并行活动的协调状态 │ │
│ └─────────────────────────────────────────────────┘ │
│ ↑ │
│ 第 1 层:系统状态 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ • 工作流实例 ID │ │
│ │ • 启动时间和超时设置 │ │
│ │ • 重试次数和策略 │ │
│ │ • 资源分配信息 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
4.3 检查点策略
yaml
复制
# 检查点配置
checkpoint:
# 自动检查点触发条件
triggers:
# 时间触发
- type: time_interval
interval: 5m # 每5分钟
# 事件触发
- type: event
events:
- activity_completed
- external_api_called
- file_written
# 状态变化触发
- type: state_change
paths:
- business_state.current_goal
- execution_state.active_activities
# 检查点内容
include:
- full_state: true # 完整状态
- event_history: last_100 # 最近100个事件
- generated_artifacts: references # 产物引用
# 存储配置
storage:
type: distributed_storage # 分布式存储
backend: s3 # 或 GCS, Azure Blob
replication: 3 # 副本数
# 保留策略
retention:
successful: 7d # 成功任务保留7天
failed: 30d # 失败任务保留30天
五、故障恢复机制
5.1 故障类型与恢复策略
故障类型
场景
恢复策略
进程崩溃
Agent 进程意外终止
从最新检查点重启
资源不足
内存/CPU 不足
扩容后从检查点恢复
网络中断
外部 API 调用失败
重试或等待后恢复
超时
任务执行超过时限
根据策略重试或人工介入
逻辑错误
Agent 生成错误代码
回滚到上一检查点重试
5.2 恢复流程
┌─────────────────────────────────────────────────────────┐
│ 故障恢复流程 │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. 故障检测 │
│ ├── 心跳超时 │
│ ├── 进程退出 │
│ └── 资源告警 │
│ ↓ │
│ 2. 状态评估 │
│ ├── 查找最新的检查点 │
│ ├── 验证检查点完整性 │
│ └── 确定恢复点 │
│ ↓ │
│ 3. 资源准备 │
│ ├── 分配新的执行资源 │
│ ├── 恢复执行环境 │
│ └── 加载依赖状态 │
│ ↓ │
│ 4. 状态恢复 │
│ ├── 加载检查点状态 │
│ ├── 重放事件历史(如有必要) │
│ └── 恢复业务上下文 │
│ ↓ │
│ 5. 继续执行 │
│ ├── 从恢复点继续工作流 │
│ ├── 通知 Agent 当前状态 │
│ └── 恢复正常监控 │
│ ↓ │
│ 6. 恢复验证 │
│ ├── 验证恢复后状态一致性 │
│ ├── 记录恢复事件 │
│ └── 更新监控指标 │
│ │
└─────────────────────────────────────────────────────────┘
5.3 幂等性设计
持久化执行的关键是幂等性——同样的操作执行多次,结果一致。
┌─────────────────────────────────────────────────────────┐
│ 幂等性设计模式 │
├─────────────────────────────────────────────────────────┤
│ │
│ 模式 1:唯一标识符 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 每个活动生成唯一 ID │ │
│ │ 重复执行时检查 ID,已执行则跳过 │ │
│ │ │ │
│ │ generate_code(task_id="abc123") │ │
│ │ if executed(task_id="abc123"): │ │
│ │ return cached_result │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 模式 2:状态检查 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 执行前检查当前状态 │ │
│ │ 如果目标状态已达成,跳过执行 │ │
│ │ │ │
│ │ if file_exists("src/utils/helper.js"): │ │
│ │ return # 已生成,跳过 │ │
│ │ generate_helper_file() │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 模式 3:补偿操作 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 对于不可逆操作,提供补偿机制 │ │
│ │ 失败时执行补偿,恢复到之前状态 │ │
│ │ │ │
│ │ try: │ │
│ │ deploy_to_production() │ │
│ │ except: │ │
│ │ rollback_deployment() # 补偿操作 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
六、事件溯源与审计
6.1 事件溯源架构
┌─────────────────────────────────────────────────────────┐
│ 事件溯源架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ Agent 执行活动 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 事件生成 │ │
│ │ • ActivityStarted │ │
│ │ • CodeGenerated │ │
│ │ • TestExecuted │ │
│ │ • ErrorOccurred │ │
│ │ • ActivityCompleted │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 事件存储(Event Store) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Event ID │ Timestamp │ Type │ Payload │ │ │
│ │ ├─────────────────────────────────────────┤ │ │
│ │ │ evt_001 │ 10:00:00 │ Start│ {...} │ │ │
│ │ │ evt_002 │ 10:05:23 │ Gen │ {...} │ │ │
│ │ │ evt_003 │ 10:08:45 │ Test │ {...} │ │ │
│ │ │ ... │ ... │ ... │ ... │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ │ │ │
│ │ 特点: │ │
│ │ • 不可变(Immutable) │ │
│ │ • 有序(Ordered) │ │
│ │ • 可追溯(Traceable) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ├──→ 状态重建(State Rebuild) │
│ │ 重放事件 → 重建任意时刻状态 │
│ │ │
│ ├──→ 审计追踪(Audit Trail) │
│ │ 完整的执行历史记录 │
│ │ │
│ └──→ 分析优化(Analytics) │
│ 识别模式,优化 Harness │
│ │
└─────────────────────────────────────────────────────────┘
6.2 事件结构设计
json
复制
{
"event_id": "evt_20260323_001",
"event_type": "CodeGenerated",
"timestamp": "2026-03-23T10:05:23.456Z",
"workflow_id": "wf_feature_login_001",
"activity_id": "act_generate_auth",
"payload": {
"files_generated": [
{
"path": "src/auth/login.ts",
"lines": 45,
"checksum": "sha256:abc123..."
}
],
"dependencies_added": ["bcrypt", "jsonwebtoken"],
"test_coverage": 85
},
"metadata": {
"agent_version": "codex-2026-03",
"execution_time_ms": 12500,
"resource_usage": {
"cpu": "2 cores",
"memory": "4 GB"
}
},
"correlation": {
"parent_event": "evt_20260323_000",
"triggered_events": ["evt_20260323_002"]
}
}
七、实践案例:长时任务的状态管理
7.1 场景:大型代码库重构
任务描述:将一个 10 万行代码的 JavaScript 项目迁移到 TypeScript
预计耗时:12-24 小时
┌─────────────────────────────────────────────────────────┐
│ 代码迁移任务的工作流设计 │
├─────────────────────────────────────────────────────────┤
│ │
│ 阶段 1:分析和准备(1-2小时) │
│ ├── 扫描项目结构 │
│ ├── 识别文件依赖关系 │
│ ├── 生成迁移计划 │
│ └── [检查点 1] │
│ ↓ │
│ 阶段 2:核心文件迁移(4-8小时) │
│ ├── 迁移入口文件 │
│ ├── 迁移核心模块(分批进行) │
│ │ ├── 批次 1: utils/ [检查点 2.1] │
│ │ ├── 批次 2: services/ [检查点 2.2] │
│ │ └── 批次 3: components/ [检查点 2.3] │
│ └── [检查点 2] │
│ ↓ │
│ 阶段 3:测试和验证(2-4小时) │
│ ├── 生成类型测试 │
│ ├── 运行单元测试 │
│ ├── 修复类型错误 │
│ └── [检查点 3] │
│ ↓ │
│ 阶段 4:清理和优化(1-2小时) │
│ ├── 删除冗余文件 │
│ ├── 优化类型定义 │
│ ├── 更新文档 │
│ └── [检查点 4 - 完成] │
│ │
│ 故障恢复场景: │
│ • 如果在阶段 2.2 崩溃 → 从检查点 2.1 恢复,重新迁移批次 2 │
│ • 如果在阶段 3 崩溃 → 从检查点 2 恢复,继续测试验证 │
│ │
└─────────────────────────────────────────────────────────┘
7.2 状态监控面板
┌─────────────────────────────────────────────────────────┐
│ Agent 执行状态监控 │
├─────────────────────────────────────────────────────────┤
│ │
│ 任务:TypeScript Migration │
│ ID: wf_ts_mig_001 │
│ 状态: RUNNING (已运行 8小时32分) │
│ │
│ 进度: [████████████████████░░░░░░░░] 65% │
│ │
│ 当前阶段: 核心文件迁移 - 批次 3/3 │
│ 活动: 迁移 components/UserProfile.tsx │
│ 预计剩余: 4小时 │
│ │
│ 资源使用: │
│ CPU: [████████░░░░░░░░░░] 45% │
│ 内存: [████████████░░░░░░] 62% (4.2GB / 6.8GB) │
│ 磁盘: [██████░░░░░░░░░░░░] 28% │
│ │
│ 最近检查点: 10分钟前 (cp_20260323_0842) │
│ 下次检查点: 5分钟后 │
│ │
│ 操作: [暂停] [恢复] [终止] [查看日志] │
│ │
└─────────────────────────────────────────────────────────┘
八、技术选型与实现
8.1 持久化执行技术选型
技术
适用场景
代表项目
Temporal
复杂工作流,强一致性要求
Temporal.io
Cadence
大规模分布式工作流
Uber Cadence
Camunda
BPMN 工作流,可视化
Camunda Platform
自研
特定需求,深度定制
OpenAI Harness
8.2 存储选型
存储类型
用途
推荐技术
关系数据库
状态存储,事务支持
PostgreSQL
对象存储
检查点文件,大对象
S3, GCS, MinIO
消息队列
事件流,异步处理
Kafka, Pulsar
缓存
热点状态,快速访问
Redis
8.3 简单实现示例
python
复制
# 持久化执行框架简化示例
class DurableExecution:
def __init__(self, workflow_id, storage):
self.workflow_id = workflow_id
self.storage = storage
self.state = None
self.checkpoint_interval = 300 # 5分钟
async def execute(self, workflow):
"""执行工作流,支持故障恢复"""
try:
# 1. 尝试恢复状态
self.state = await self.load_checkpoint()
if self.state:
# 从检查点恢复
current_step = self.state['current_step']
print(f"Resuming from step {current_step}")
else:
# 新任务
current_step = 0
self.state = {
'workflow_id': self.workflow_id,
'current_step': 0,
'status': 'running',
'data': {}
}
# 2. 执行工作流步骤
for i, step in enumerate(workflow.steps[current_step:]):
# 执行步骤
result = await self.execute_step(step)
# 更新状态
self.state['current_step'] = current_step + i + 1
self.state['data'][step.name] = result
# 定期保存检查点
if (current_step + i + 1) % self.checkpoint_interval == 0:
await self.save_checkpoint()
# 记录事件
await self.record_event({
'type': 'step_completed',
'step': step.name,
'result': result
})
# 3. 完成
self.state['status'] = 'completed'
await self.save_checkpoint()
except Exception as e:
# 保存失败状态
self.state['status'] = 'failed'
self.state['error'] = str(e)
await self.save_checkpoint()
raise
async def save_checkpoint(self):
"""保存检查点"""
checkpoint_id = f"cp_{self.workflow_id}_{int(time.time())}"
await self.storage.save(
f"checkpoints/{self.workflow_id}/{checkpoint_id}",
self.state
)
print(f"Checkpoint saved: {checkpoint_id}")
async def load_checkpoint(self):
"""加载最新检查点"""
checkpoints = await self.storage.list(
f"checkpoints/{self.workflow_id}/"
)
if not checkpoints:
return None
latest = max(checkpoints, key=lambda x: x['timestamp'])
return await self.storage.load(latest['path'])
async def record_event(self, event):
"""记录事件"""
event['timestamp'] = time.time()
event['workflow_id'] = self.workflow_id
await self.storage.append(
f"events/{self.workflow_id}/events.log",
event
)
九、最佳实践与陷阱
9.1 最佳实践
实践
说明
频繁检查点
平衡性能和可靠性,通常 5-10 分钟
增量状态
只保存变化的部分,减少存储和传输
异步保存
检查点保存不阻塞主执行流程
状态验证
恢复后验证状态完整性
优雅降级
持久化失败时,继续执行但告警
9.2 常见陷阱
陷阱
问题
解决
检查点过大
保存和恢复耗时
增量检查点,压缩存储
状态不一致
检查点与实际情况不符
幂等设计,状态验证
恢复失败
检查点损坏或格式不兼容
多副本,版本管理
事件丢失
事件未持久化
同步写入,确认机制
十、结语:可靠是规模化的前提
持久化执行是 Harness Engineering 的基础设施能力。没有它,Agent 无法承担复杂、长时的任务;有了它,Agent 才能真正的 7×24 小时可靠工作。
可靠是规模化的前提。只有单个 Agent 能够可靠工作,我们才能放心地部署成百上千个 Agent。
这是 Harness Engineering 的技术基石,也是 AI 时代软件工程的核心能力。
参考与延伸阅读
- Temporal - Durable Execution - 持久化执行框架
- Designing Data-Intensive Applications - Martin Kleppmann
- Event Sourcing Pattern - Microservices.io