Skip to content
预计 1 分钟右侧目录可快速定位

长任务 Agent:持续进度、恢复与 Harness 演进 ​

前置:控制平面、执行平面与 Agent 协作模式
核心问题:当任务跨进程、跨 Context 甚至跨天继续时,系统靠什么证明“做到哪了”,而不是靠模型记住整段聊天?

长任务不是“让 Context 更长” ​

核心直觉:任务能跨进程、跨 Context 继续,靠的是外部可恢复事实,不是靠模型一直记住过去。

1. 为什么更大的 Context 仍然不够 ​

一个代码迁移任务可能持续两天。期间会发生:

  • Model Context 被压缩或重置;
  • Worker 进程重启;
  • 用户等待数小时后再批准;
  • Workspace、Git HEAD、依赖版本发生变化。

如果系统只保存 transcript,新进程仍然很难可靠回答:

  • 已经完成了哪些步骤?
  • 哪些文件真的改过?
  • 哪些测试真的运行并通过?
  • 哪个外部动作已经产生过副作用?

2. 三类外部事实 ​

  • Progress State:任务做到哪一步、下一步是什么。
  • Artifact:代码 diff、测试报告、搜索结果、计划等可复用工作成果。
  • Checkpoint:一个以后可以安全恢复的状态边界。

Checkpoint consistency、idempotency 与 crash window 的完整机制放在 Advanced。

3. Context 是工作集,不是唯一状态源 ​

可以把 Model Context 理解成当前回合的“工作桌面”。桌面上的东西可以被裁剪、压缩、重新组装;真正需要跨进程成立的事实应该放到 Runtime state、DB、artifact store、workspace 等外部载体。

text
Durable Progress / Artifact / State
             ↓
      Harness 重新组装
             ↓
        New Context
             ↓
            Model

因此 Resume 不是“把旧 Prompt 再发一遍”,而是读取仍然有效的事实,重新建立当前 Context。

4. 恢复时世界可能已经变了 ​

旧任务留下“准备修改 config.yaml”并不代表今天还应该直接修改。恢复时至少要意识到:代码版本、权限、依赖和用户意图可能已经变化。后续会把这个问题正式展开成 revalidation / environment reconciliation。

Advanced / Canonical 深入内容

1. 为什么“让 Agent 跑更久”不是长任务能力 ​

一个 Agent 连续运行 100 个 Turn,并不意味着它具备 Long-running 能力。

真正的长任务会跨越至少四种边界:

text
Context boundary
Process boundary
Human/external wait boundary
Environment change boundary

例如一个持续两天的代码迁移任务:

  • 第一天分析仓库并修改 20 个文件;
  • 中途 Context 接近上限,需要 compaction/reset;
  • 晚上服务升级,原进程结束;
  • 第二天等待人工审批;
  • 审批通过后继续测试;
  • 期间仓库可能出现新的 commit。

如果系统只有一个不断增长的 messages 数组,它无法可靠回答:

text
哪些工作真的完成?
哪些 side effect 已经提交?
恢复后从哪里继续?
哪些旧结论已经被环境变化推翻?

因此 Long-running Agent 的核心不是“更长的聊天”,而是:

跨不连续执行环境维持可验证进度,并在恢复时避免丢状态、重复副作用和错误继承。

Harness 还常包含对“当前模型能力”的补偿。模型升级以后,这些补偿可能由帮助变成负担,因此 Harness 本身也必须能够演进。


2. Mental Model:连续性不是一条 Context,而是多层持久状态 ​

可以把长任务理解成四层连续性:

text
┌───────────────────────────────────┐
│ Goal / Durable Task State         │  最终目标、约束、已完成工作
├───────────────────────────────────┤
│ Checkpoint / Execution Records    │  从哪里可以安全恢复
├───────────────────────────────────┤
│ Workspace / Artifacts             │  文件、patch、测试结果、产物
├───────────────────────────────────┤
│ Model Context                     │  当前这一轮真正看到的工作集
└───────────────────────────────────┘

四层生命周期不同。

最短的是 Model Context:可能几十分钟内就被 compaction/reset。

Workspace 可能持续数小时或数天。

Durable Task State 和 Execution Record 则可能需要保存到任务彻底结束甚至审计期之后。

因此:

text
Context continuity
≠
Task continuity

长任务恢复的核心,是从 durable facts 和 environment 中重新构建足够的 Context,而不是强行保存无限长的 transcript。


3. 核心机制 ​

3.1 Progress State:记录“已经完成什么” ​

长任务最容易犯的错误是只保存:

text
conversation history

但历史里可能充满探索、错误尝试、过期计划。

真正恢复需要的是结构化 Progress State,例如:

python
@dataclass
class TaskProgress:
    task_id: str
    objective: str
    constraints: list[str]
    completed_steps: list[str]
    pending_steps: list[str]
    blockers: list[str]
    important_decisions: list[str]
    artifact_refs: list[str]

Owner ​

Progress State 应由 Runtime / TaskStore 持有。

模型可以建议:

“Step 3 已完成。”

但 Runtime 应结合 execution evidence 决定是否写入 completed_steps。

生命周期 ​

text
task created
→ progress initialized
→ after meaningful boundary update
→ checkpoint
→ resume
→ final task complete

它可以跨多个 Run / Session / process。


3.2 Checkpoint:定义安全恢复边界 ​

Checkpoint 不是简单“把所有对象 pickle 一下”。

更准确的工程意义是:

在一个已知一致边界保存足够状态,使未来能够从该边界继续执行。

例如:

text
Node A succeeded
Node B succeeded
Node C not started

Checkpoint 应明确:

text
A/B 已提交
C 未执行

恢复后不能盲目重跑 A/B。

对于有副作用的 Node,这一点尤其关键。

例如:

text
send_email succeeded
process crashed before next node

如果恢复逻辑只知道:

“整个 step 没完成。”

就可能再次发送邮件。

所以 checkpoint 必须与:

  • execution record;
  • idempotency key;
  • pending writes;
  • external side-effect reconciliation

一起设计。


3.3 Artifact:把工作成果放到 Context 之外 ​

长任务中的很多状态天然适合外部化:

text
repo files
patch
report.md
progress.md
test-results.json
trace
dataset

Anthropic 在 long-running coding agent 实践里强调通过 progress artifacts 和环境状态跨 Context 继续工作。

Artifact 的优势是:

text
durable
addressable
re-readable
not permanently occupying context

模型需要时再读取:

text
artifact ref
   ↓
read relevant slice

这比把完整内容永远塞在聊天历史里更可控。


3.4 Context Handoff:新 Context 怎样接上旧工作 ​

新的模型 Context 不应该从“请继续”三个字开始。

恢复包至少应该包含:

text
objective
constraints
current progress
unresolved blockers
important decisions
artifact refs
latest environment state
next candidate actions

可以形成:

yaml
task:
  objective: migrate auth module

completed:
  - locate old token API
  - replace parser in 5 files

pending:
  - integration tests
  - deployment config approval

decisions:
  - keep backward-compatible token format

artifacts:
  - workspace://diff/42
  - artifact://test/last

checkpoint:
  id: cp-19

这个结构是为了执行,不是为了“总结得好看”。


3.5 Environment Reconciliation:恢复时不能假设世界没变 ​

长任务暂停期间,外部环境可能变化:

text
Git branch updated
API version changed
ticket state changed
file deleted
approval expired
database row modified

所以 Resume 不是:

text
load checkpoint
→ blindly continue

而应该:

text
load checkpoint
→ revalidate environment assumptions
→ reconcile conflicts
→ possibly replan
→ continue

例如代码任务:

text
checkpoint commit = abc123
current HEAD = def456

Runtime 应意识到工作基线改变,而不是把旧 patch 强行应用。


3.6 Harness Assumption:为什么模型升级会让旧策略过时 ​

Harness 往往会编码很多“因为模型目前不够强,所以系统替它做”的策略:

text
强制 planner → executor → critic
每两轮强制 summary
固定 Tool 顺序
大量 few-shot
人为限制一次只能调用一个 Tool
频繁 context reset

这些策略在某个模型版本上可能确实有净收益。

但模型能力变化后:

  • 更强的 planning 可能让固定 planner 链成为额外 latency;
  • 更大的有效 Context 可能让过频 compaction 损失信息;
  • 更好的 Tool Calling 可能让复杂路由 Prompt 变成噪音。

Anthropic Managed Agents 的经验明确指出:Harness 会携带关于模型能力的假设,而这些假设可能随着模型进步而失效。

因此 Harness 的 workaround 应该是:

text
explicit
versioned
replaceable
measurable

而不是永久写死。


4. 如何设计:长任务连续性与 Harness 演进的边界 ​

4.1 什么必须 Durable ​

如果丢失后会导致:

  • 无法恢复;
  • 重复副作用;
  • 违反用户约束;
  • 无法审计;

就应该 durable。

典型:

text
objective
approval state
committed side effects
checkpoint
artifact refs
idempotency records

4.2 什么不应该强行 Durable ​

运行时对象:

text
asyncio.Task
open socket
DB connection
file descriptor
HTTP client

不应该尝试跨进程恢复。

恢复时应该重建这些 ephemeral resources。

4.3 什么应该重新验证 ​

属于外部世界的事实:

text
branch HEAD
remote API state
inventory
ticket status
permission

恢复时应该重新获取,而不是把旧 Observation 当永恒事实。

4.4 Harness workaround 什么时候删除 ​

不能因为“新模型看起来更强”就删。

正确过程:

text
old policy ON baseline
       vs
old policy OFF candidate
       ↓
same eval set
       ↓
success / latency / token / error

只有证据支持,才删除或调整。


5. 真实执行案例:一个跨两天的代码迁移任务 ​

用户目标:

“把旧认证模块迁移到新 API,确保所有测试通过;部署配置修改必须审批。”

Day 1 / Step 1:初始化任务 ​

Runtime 创建:

text
task_id = T-17
run_id = R-1
workspace = W-9

保存:

text
objective
constraints
repo HEAD

Step 2:Agent 调查并修改代码 ​

模型逐步:

text
search
→ read
→ patch
→ test

Execution Plane 产生真实:

text
workspace diff
test results
tool execution records

Step 3:Context 接近阈值 ​

ContextManager 不保存全部 raw history,而生成结构化 handoff:

text
completed
pending
decisions
failed attempts
artifact refs

原 transcript 仍可归档用于 debug。

Step 4:写 Checkpoint ​

此时:

text
12 files patched
unit tests passed
integration tests pending
deployment config untouched

Runtime 保存:

text
checkpoint cp-4

并记录每个 patch/test execution。

Step 5:服务升级,进程退出 ​

丢失的是:

text
Python objects
model connection
event loop tasks

没有丢:

text
TaskProgress
Checkpoint
Workspace
Artifacts
Execution Records

Day 2 / Step 6:恢复 ​

新进程:

text
load cp-4
attach W-9

但首先发现:

text
remote branch HEAD changed

因此进入 reconciliation:

text
fetch latest
compare touched files

发现无冲突后继续。

Step 7:模型请求修改 deployment config ​

Policy 返回:

text
WAITING_APPROVAL

状态持久化,计算停止。

Step 8:用户批准 ​

Runtime 重新校验:

  • approval 仍有效;
  • target config 仍存在;
  • 当前 identity 仍有权限。

然后才执行 patch。

Step 9:全部测试通过 ​

完成证据:

text
integration test exit_code = 0
workspace diff recorded
deployment approval record exists
RunState = SUCCEEDED
TaskProgress = COMPLETE

注意:

“模型说迁移完成”不是完成证据。


6. 最小实现:Resume Bundle ​

python
from dataclasses import dataclass

@dataclass
class ResumeBundle:
    task_id: str
    checkpoint_id: str
    objective: str
    constraints: list[str]
    completed: list[str]
    pending: list[str]
    artifact_refs: list[str]
    workspace_ref: str
    environment_version: str

恢复:

python
async def resume(bundle: ResumeBundle):
    state = await checkpoint_store.load(
        bundle.checkpoint_id
    )

    workspace = await workspace_manager.attach(
        bundle.workspace_ref
    )

    current_env = await inspect_environment(workspace)

    if current_env.version != bundle.environment_version:
        await reconcile(state, current_env)

    context = await context_manager.rehydrate(
        state=state,
        artifacts=bundle.artifact_refs,
    )

    return await runtime.continue_run(
        state,
        context,
    )

这里有三个关键思想:

text
attach existing workspace
revalidate environment
rehydrate context

而不是“把旧 messages 再发一遍”。


7. Shadow Harness 中如何落地 ​

建议:

text
state/
├── task_store.py
├── checkpoint_store.py
└── execution_record.py

workspace/
├── manager.py
└── snapshot.py

context/
├── compactor.py
└── rehydrator.py

runtime/
├── resume.py
└── reconciliation.py

eval/
└── long_horizon.py

关键记录:

text
TaskProgress
Checkpoint
NodeExecutionRecord
ToolExecutionRecord
ApprovalRecord
ArtifactReference
WorkspaceSnapshot
RunManifest

其中 RunManifest 用来解释:

text
当时使用了哪个 model/prompt/tool schema/runtime version?

长任务没有版本信息,恢复和回归分析都容易变成猜测。


8. Production Engineering:长任务真正难在哪里 ​

8.1 Side Effect 必须幂等或可对账 ​

长任务 crash 很正常。

要假设:

text
外部动作已经成功
但本地确认记录可能还没写完

所以至少需要:

  • idempotency key;
  • operation record;
  • reconciliation。

8.2 Checkpoint 频率是 Trade-off ​

太频繁:

text
storage I/O ↑
latency ↑

太稀:

text
crash 后重做工作 ↑
副作用边界更难判断

应在有意义的一致边界保存,而不是每个 token checkpoint。

8.3 Artifact 需要 provenance ​

必须知道:

text
谁生成?
基于哪个 input/version?
是否仍然有效?

否则第二天读到一个旧测试报告,模型可能把它当成当前事实。

8.4 Resume 要有 deadline/budget 重新计算 ​

恢复不是无限延长原任务。

需要重新检查:

text
用户是否取消?
deadline 是否过期?
预算是否还有?
approval 是否失效?

8.5 Harness 策略需要版本化 Eval ​

Model upgrade 时至少重新跑:

  • long-horizon success;
  • tool trajectory;
  • compaction fidelity;
  • recovery;
  • cost/latency。

否则“升级模型”可能被旧 Harness 抵消。


9. Failure Modes ​

9.1 把完整 Transcript 当成唯一任务状态 ​

错误表现。 恢复只依赖历史 messages,没有结构化 progress/checkpoint。

为什么危险。 对话包含过期探索,且无法证明哪些 side effect 已成功;Context 还可能超过窗口。

修复方向。 分离 transcript、TaskProgress、Checkpoint、ExecutionRecord 和 Artifact。

验证方式。 删除模型 Context,仅依靠 durable state 恢复;断言任务仍能定位 pending work。

9.2 Resume 时重跑已经成功的副作用 ​

错误表现。 crash 后从整个 step 开始,重复发邮件、重复写 DB 或重复提交 patch。

为什么危险。 产生不可逆业务错误。

修复方向。 为 side effect 保存 execution/idempotency record,在恢复前查询已提交结果。

验证方式。 在“外部成功、本地即将 checkpoint”位置故障注入,恢复后断言 side effect 总次数仍为 1。

9.3 Compaction 丢失关键约束 ​

错误表现。 新 Context 记得“继续迁移”,却忘了“部署配置必须审批”。

为什么危险。 有损摘要把安全/业务约束永久丢失。

修复方向。 protected state 与自由 summary 分离,constraints 作为结构化 durable facts 注入新 Context。

验证方式。 多次 compaction 后检查 protected constraints 逐字/结构保持。

9.4 Resume 时相信过期环境 ​

错误表现。 两天前的 repo/API 状态被当成当前事实继续执行。

为什么危险。 patch 冲突、错误决策、权限变化都可能被忽略。

修复方向。 为外部环境保存 version/provenance,resume 时执行 reconciliation。

验证方式。 修改远端 branch 或资源状态后恢复,断言 Runtime 进入 revalidation/replan 而不是直接执行旧 Action。

9.5 Harness workaround 永久化 ​

错误表现。 新模型升级后仍保留大量旧 planner/critic/summary 链,从不做 ablation。

为什么危险。 增加 token/latency,甚至压制新模型能力。

修复方向。 把 workaround 做成 versioned policy,并为每项记录其假设和 Eval 证据。

验证方式。 Model upgrade 后运行 policy ON/OFF 对照,只有有统计/工程收益的策略继续保留。


10. 如何验证:Testing 与 Evaluation ​

10.1 Crash Injection Test:外部成功后立即崩溃 ​

流程:

text
execute side effect
→ external returns success
→ inject crash before next checkpoint
→ resume

断言:

text
side effect executed exactly once

这是 deterministic reliability test。

10.2 Context Reset Test:完全丢弃当前模型 Context ​

保留:

text
checkpoint
task progress
workspace
artifacts

创建全新 model session。

断言它能够恢复:

  • objective;
  • constraints;
  • completed/pending;
  • next valid action。

10.3 Environment Drift Test ​

Checkpoint 后修改:

text
repo HEAD

Resume 时断言:

text
reconciliation triggered

而不是继续使用旧基线。

10.4 Compaction Fidelity Test ​

构造 20 个必须保存的 facts:

text
5 constraints
5 decisions
5 completed steps
5 failed attempts

连续做多次 compaction/reset。

检查:

text
protected facts retained

10.5 Evaluation:Harness Policy Ablation ​

对真实长任务 Eval Set 比较:

text
old harness policy
new simplified policy

指标:

  • success rate;
  • turns;
  • input tokens;
  • latency;
  • repeated work;
  • recovery correctness。

语义任务质量属于 Eval;crash/recovery/idempotency contract 属于 Testing。


11. 常见问题(Q&A) ​

Q1:Long-running Agent 最大的问题是不是 Context Window 不够大? ​

不是。

Context Window 只是其中一个限制。真正难的是跨 Context、进程、人工等待和外部环境变化保持可验证连续性。

即使模型有超大 Context,如果进程 crash 后会重复付款/重复发邮件,这个系统仍然没有 Long-running reliability。

Q2:Checkpoint 和 Compaction 有什么区别? ​

Compaction 解决:

下一次模型推理应该怎样用更短表示继续理解任务。

Checkpoint 解决:

程序未来从哪个一致执行边界安全恢复。

一个偏 Context representation,一个偏 durable execution。它们可能在同一时机触发,但语义不同。

Q3:为什么不能直接序列化整个 Runtime 对象? ​

因为很多对象没有稳定的跨进程语义,例如 socket、DB connection、event-loop Task、open file descriptor。

Durable State 应保存领域事实和 reference;恢复时重新建立 ephemeral resource。

Q4:Progress State 和 Memory 是一回事吗? ​

不是。

Progress State 是某个长任务必须依赖的执行事实,例如“Node A 已完成”“正在等审批”。

Memory 通常是跨任务/会话可选择检索的经验或用户信息。Progress State 的一致性要求更高,也不应依赖语义检索“碰巧找到”。

Q5:为什么 Resume 时还要重新检查环境? ​

因为外部世界在暂停期间可能变化。

Checkpoint 只能证明“当时是什么状态”,不能保证当前 Git、API、权限、资源仍然一样。

所以 Resume 应包含 environment revalidation。

Q6:Artifact 为什么比把所有内容塞进 Context 更适合长任务? ​

Artifact 可以持久化、按引用读取、保留 provenance,而且不永久占用 Token。

Context 只在当前 inference 中需要工作集;Artifact 是外部工作成果。二者生命周期不同。

Q7:Harness 为什么会随着模型能力变强而需要删除代码? ​

因为 Harness 经常承担模型弱点的补偿。

当模型能力变化后,旧的分步、critic、summary 或 tool workaround 可能不再产生收益,却继续消耗 Token 和 latency。

所以 Harness 需要“可删除的脚手架”,而不是只会不断加层。

Q8:怎么判断某个旧 Harness 策略是否还能保留? ​

不要凭感觉,也不要因为策略“以前有用”就默认永久保留。

应该在同一版本化 Eval Set 上做 controlled ablation:

text
policy ON
vs
policy OFF

除了最终任务成功率,还要同时观察 token、latency、Tool trajectory、recovery correctness 和新出现的 failure mode。如果关闭策略后质量不下降而成本更低,就应该考虑删除;如果某类任务明显退化,则保留策略并记录它依赖的模型/任务假设。这样 Harness 才能随着模型能力演进,而不是只会不断堆补丁。


12. Long-running Harness 的稳定边界 ​

Long-running Agent 的稳定结构可以表示为:

text
不是:
一个永远不断的聊天

而是:
durable task facts
+ recoverable execution boundary
+ persistent artifacts/workspace
+ replaceable model context
+ side-effect consistency
+ environment reconciliation

Harness 也需要随模型能力变化持续校准:

text
Model capability changes
        ↓
old assumptions become questionable
        ↓
versioned Eval / ablation
        ↓
keep / simplify / remove policy

所以长任务工程的两条主线是:

让任务状态比单次 Context 活得更久;让 Harness 假设不要比它的证据活得更久。


13. Sources ​

  1. Anthropic — Effective harnesses for long-running agents
    https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents

  2. Anthropic — Scaling Managed Agents: Decoupling the brain from the hands
    https://www.anthropic.com/engineering/managed-agents

  3. OpenAI Agents SDK — Running agents
    https://openai.github.io/openai-agents-python/running_agents/

  4. LangGraph — Persistence
    https://docs.langchain.com/oss/python/langgraph/persistence

自测 ​

  1. 一个两天的代码迁移任务在 Worker 重启、Context reset 后继续。哪些事实必须存在 Context 之外,才能判断“已经做过什么”?
  2. 为什么保存完整 transcript 仍不足以安全 Resume?举一个环境已经变化、旧对话却仍然成立不了的例子。
  3. Progress、Artifact、Checkpoint 各自回答什么问题?哪一种最接近“从哪里可以安全继续执行”的边界?

AI Engineering · Agent · Harness · Backend Systems