@rauchg:Pi 是如今 AI 领域最酷的项目之一。我加入了他们的团队。让开发者和企业自由选择模型……
摘要
Vercel 宣布推出 durable-harness,可让 Pi、OpenCode、Codex、Claude Code 等任意编码 agent 框架在云端持久运行,崩溃或超时后能从日志恢复并继续中断的任务。Rauch(Vercel CEO)同时公开表示自己加入了 Pi 团队。
查看缓存全文
缓存时间: 2026/10/22 21:49
Pi 是当今 AI 领域最酷的项目之一。我在他们的团队。让开发者和公司拥有模型选择权、对运行时、数据、技能、插件的控制权……很高兴能在 @vercel 上获得如此强大的支持:https://vercel.com/blog/making-every-harness-durable…
让每个 Harness 都持久可靠
来源:https://vercel.com/blog/making-every-harness-durable 开发者们对在本地通过 Pi、Claude Code 等 Harness 运行编程代理已经非常熟悉了。它们是日常生成代码的可靠工具,但要让代理全天候运行,就需要你的电脑一直开着且不休眠,这催生了各种合上笔记本盖子的梗图和 Mac mini 的需求激增。
Cormac (https://x.com/cormachayden_/status/2050773588521992642)https://x.com/cormachayden_/status/2050773588521992642 软件工程师:有代理 vs 无代理
Harness 现在可以在云端运行了,所以你可以合上盖子了。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#running-harnesses-in-the-cloud)在云端运行 Harness
Harness 的工作负载正在向云端迁移。独立开发者正在部署全天候运行的编程代理工作流,OpenWork 和 HanaAgent 等项目使用开源 Harness 作为其应用背后的引擎,工程师们也在构建自己的 Harness 产品。
这些 Harness 是为将会话保存在内存中的长驻进程而设计的,代理任务通常运行几分钟到几小时。在本地,Harness 可以直接、持续地访问同一磁盘上的工作区和会话历史,因此恢复中断的工作只需要一个简单的提示。
在云端,你可以用虚拟机和持久化存储来复刻这种设置,但虚拟机不会自动记录哪些模型调用和工具调用已完成,也无法在崩溃后恢复中断的轮次。一次失败的调用或网络错误就意味着工作丢失。
另外,并非每个通过 Harness 执行的代理任务都需要沙箱。数据库查询和 API 调用可以在函数中安全运行,这也意味着所需凭证永远不需要进入沙箱。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#making-every-harness-durable)让每个 Harness 都持久可靠
我们构建的eve (https://eve.dev/)和fx (https://fx.sh/)开箱即可在云端持久运行,今天我们要介绍durable-harness,它将这种持久性扩展到任何 Harness,包括Pi (https://github.com/earendil-works/pi)、OpenCode (https://opencode.ai/)、Codex (https://github.com/openai/codex)和Claude Code (https://docs.claude.com/en/docs/claude-code/overview)。它使用驱动Workflow SDK (https://workflow-sdk.dev/)的同一套机制来抵御崩溃和函数超时。
有了durable-harness,你可以:
- 在 Vercel 上持久运行任意这些 Harness
- 使用自己的 Postgres 实例自托管 Harness
- 让你本地的 Harness 工作流变得持久可靠
- 构建你自己的持久 Harness
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#sessions-that-survive-a-crash-mid-turn)能挺过轮次中途崩溃的会话
以一个编程代理为现有应用添加定价页面为例。代理读取现有页面,编写新页面,打开一个 Pull Request,然后等待 CI 完成后再返回报告。
如果它的函数在 CI 仍在运行时超时了,会发生什么?
在下面的演示中杀死函数或断开连接,比较两个代理的恢复方式以及哪些工作被重复执行。
没有持久性时,代理会停止工作,直到被手动重启,已完成的工作会被不必要地重复。
有了durable-harness,新的函数会从日志中读取已完成的结果并恢复轮次。如果浏览器断开连接,代理会继续运行,重新连接后会从日志中追赶进度。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#logs-and-queues)日志与队列
durable-harness是我们开源组合中最新的包。它是一组适配器和工具,让你已经在使用的 Harness 将会话保存在World (https://workflow-sdk.dev/worlds)中——这是 Workflow SDK 的持久后端。
它将轮次的每一步都写入持久日志。在模型调用或工具调用执行之前,它先记录一个意图,调用完成后再记录结果。轮次本身由一条队列消息兜底,因此如果函数挂掉,队列会把该轮次交给一个新函数,新函数读取日志并从中断处继续。
崩溃之后,日志会告诉你什么已完成、什么正在运行、什么还没开始:
- 已完成的调用不会再运行,因为它们的结果直接从日志中读取,所以你永远不会为已完成的模型调用的 token 被重复计费。
- 模型会记住之前的调用,而不会重复执行。
- 标记为
replay: 'safe'的被中断工具会重新运行。其他任何工具都会以“可能已执行“的状态返回给模型,由模型决定是否需要检查。
那些维护自己会话文件的 Harness,例如 Claude Code 的 transcript、Codex 的 rollout 和 OpenCode 的 event store,它们的每条记录都会镜像到日志中,因此新的函数或 Sandbox 可以从日志中重建这些文件。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#pick-your-harness)选择你的 Harness
fx (https://fx.sh/)和eve (https://eve.dev/)本身就具备持久性。对于其他 Harness,durable-harness从外部为其添加持久性,而无需修改 Harness 本身。
每个 Harness 的完整配置指南,请查看文档 (https://vercel.com/docs/agent-harnesses/harnesses)。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#runs-everywhere)到处都能跑
持久代理需要三样东西:每一步的日志、在进程死亡时恢复轮次的能力,以及面向观察者的事件流。
Workflow SDK 将这三者统一在一个接口后面——即World (https://workflow-sdk.dev/worlds)。
import type { Queue, Storage, Streamer } from '@workflow/world'
interface World extends Storage, Queue, Streamer {}
World 就是日志、兜底和事件流的统一体。
durable-harness写入这个接口,因此你可以将同一个代理从一个 World 迁移到另一个 World,而无需修改代码:
- 在 Vercel 上,它使用Vercel World (https://workflow-sdk.dev/worlds/vercel)。
- 在开发时,它使用你机器上的文件 (https://workflow-sdk.dev/worlds/local)。
- 在你自己的服务器上,它使用Postgres (https://workflow-sdk.dev/worlds/postgres)、MongoDB、Redis 或 Turso。
两个变量即可让所有使用durable-harness的代理迁移到 Postgres。
WORKFLOW_TARGET_WORLD="@workflow/world-postgres"
WORKFLOW_POSTGRES_URL="postgres://user:password@host:5432/database"
将 durable-harness 重定向到使用 Postgres World 进行持久化。
如需更多控制,例如设置命名空间或在服务器启动时恢复会话,可以在代码中创建 World 并传给你的代理:
请查看自托管文档 (https://vercel.com/docs/agent-harnesses/self-hosting)了解更多信息。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#see-every-session-in-agent-runs)在 Agent Runs 中查看每个会话
Vercel 上的Agent Runs (https://vercel.com/docs/agent-harnesses/observability)会显示每个会话的追踪记录,包括每次模型调用和工具调用。崩溃后恢复的轮次会出现在同一条追踪中,因此你可以准确看到轮次在哪里停止又从哪里继续。
Agent Runs 标签页中的一个 Pi 会话,包含一个被中断并重试的模型调用。
代理只有你赋予它的工具,而且这些工具在你的函数中运行。每个工具都声明了在崩溃中断时应该如何处理。标记为'safe'的工具,例如查询操作,可以重新运行。标记为'never'的工具,例如退款操作,绝不会运行两次:模型会被告知该调用可能已执行,因此它会在再次尝试前先进行检查。
以下是如何为上面演示中的编程代理定义工具:
- 读取文件或检查 CI 状态的工具标记为
'safe',以便自动重新运行。 - 发布 PR 评论的工具标记为
'never',以避免评论被发布两次。
以下示例以一个处理退款的代理为例,为每种策略定义一个工具:
import { pi } from 'durable-harness/pi';
import type { HostTool } from 'durable-harness';
import { getOrder, refundOrder } from './orders'; // 你自己的代码
const tools: HostTool[] = [
{
name: 'get_order',
description: 'Looks up an order',
replay: 'safe', // 崩溃后可以安全地重新运行
inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
execute: async ({ id }) => JSON.stringify(await getOrder(id)),
},
{
name: 'refund_order',
description: 'Refunds an order',
replay: 'never', // 绝不运行两次
inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
execute: async ({ id }) => JSON.stringify(await refundOrder(id)),
},
];
export const agent = pi({ model: 'anthropic/claude-sonnet-5.5', tools });
查询操作在崩溃后可以重新运行,而退款操作绝不会运行两次。
关于每个 Harness 的内置工具(如 shell 和文件编辑),请继续往下看。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#files)文件
当 Harness 需要 shell 和文件时,直接在共享的无服务器函数主机上运行是不安全的。多个会话可能共用同一个函数,而它的文件系统不保证在调用之间持久存在。
为了解决这个问题,durable-harness提供了几个选项:
virtual()将文件保存在会话的日志中,配备一个兼容 bash 的 shell,无法访问你函数的文件或网络。它适合短任务和小型工作区,无需启动完整的沙箱。virtual({ durable: false })将文件保存在内存中用于临时工作,每轮结束时清除。sandbox()为会话提供独立的Vercel Sandbox (https://vercel.com/docs/sandbox),其中的/workspace位于一个Drive (https://vercel.com/kb/guide/vercel-drives)上,该 Drive 的生命周期超过所有沙箱和函数。它适合真实项目和长时间运行的工作。
在文档 (https://vercel.com/docs/agent-harnesses/tools#files)中对比这三个选项。
每个 Harness 的内置工具在你选择的工作区上运行。对于 Pi,CodingTools会安装 Pi 自带的read、write、edit和bash,而virtualEnv()或sandboxEnv()为它们提供工作区:
import { BACKGROUND_CONTEXT as ctx } from '@earendil-works/chord/context';
import { createRegistry, Harness, type Storage } from '@earendil-works/pi-durable';
import { CodingTools, gatewayModels, resumeWith, virtualEnv } from 'durable-harness/pi-durable';
const models = gatewayModels();
const registry = createRegistry();
registry.install(CodingTools); // Pi 的 read、write、edit 和 bash
// 文件保存在会话日志中,或使用 sandboxEnv() 为会话提供独立的 Vercel Sandbox
const env = virtualEnv();
export const open = resumeWith((storage: Storage) => Harness.open(storage, { models, registry, env }, ctx));
在虚拟工作区或 Vercel Sandbox 中为 Pi 提供编程工具。
对于 OpenCode,将工作区作为workspace传入;对于 fx,传给fxTools()。Claude Code 和 Codex 始终在 Vercel Sandbox 中运行,因为它们期望真实的 shell 和文件系统,不适合多租户使用。启用builtins: true后,它们的内置工具会在会话的 Drive 上工作。每个harness 指南 (https://vercel.com/docs/agent-harnesses/harnesses)都列出了其内置工具。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#documents)文档
有些状态属于会话但不属于对话,例如待办事项列表、计划或代理填写的表单。文档是带有类型的 JSON,存在于会话的日志中,因此能在崩溃后存活并随会话一起移动。
工具可以通过io.docs编辑文档,每次编辑都会与工具结果一起提交到日志中,因此文档的持久状态与工具调用本身保持一致:
import { defineDoc, type HostTool } from 'durable-harness';
export const Todos = defineDoc<{ items: string[] }>({
kind: 'app.todos',
version: 1,
initial: () => ({ items: [] }),
});
export const addTodo: HostTool<{ item: string }> = {
name: 'add_todo',
description: 'Adds a todo',
replay: 'safe',
inputSchema: { type: 'object', properties: { item: { type: 'string' } }, required: ['item'] },
async execute({ item }, io) {
const todos = io.docs!.update(Todos, (draft) => {
draft.items.push(item);
});
return `${todos.items.length} todos`;
},
};
定义一个待办事项列表文档以及向其中添加条目的工具。
你的应用可以读取和编辑同一份文档,无需自己的数据库,聊天路由甚至可以将每次变更流式传输到你的 UI:
import { agent } from '@/lib/agent';
import { Todos } from '@/lib/todos';
// 在路由或 webhook 中:无需自己的数据库即可读取列表
const { value } = await agent.sessions.doc(sessionId, Todos);
// 在聊天路由中:将每次变更流式传输到浏览器
export const { GET, POST } = agent.chatRoute({ authorize, docs: [Todos] }); // 你的鉴权检查
从你的应用中读取待办列表,并将其变更流式传输到 UI。
事实上,前面提到的virtual()工作区就是建立在文档之上的:它的文件树是会话日志中的一个文档,每次工具调用的更改都与其结果一起提交。
了解更多关于工具、文件和文档 (https://vercel.com/docs/agent-harnesses/tools)以及如何保护代理安全 (https://vercel.com/docs/agent-harnesses/security)的信息。
复制标题链接 (https://vercel.com/blog/making-every-harness-durable#wrapping-up)总结
开发者选择一个 Harness,是因为它在提示词、工具和上下文方面的设计决策。而它如何应对崩溃不应成为选择的考量因素之一。有了durable-harness,一个在轮次中途丢失函数的调用可以在新函数上从日志继续,无需手动重试,也不会重复已完成的工作。自托管和可移植性开箱即用,因为它们建立在 Workflow SDK 的 World 接口之上。
durable-harness已在GitHub 开源 (https://github.com/vercel-labs/durable-harness)。
让你的 Harness 持久可靠 适配器,让 Pi、OpenCode、Claude Code 和 Codex 在 Vercel、Postgres 或你的笔记本电脑上都能持久运行。阅读文档 (https://vercel.com/docs/agent-harnesses)
Pi (@pidotdev): 我们对 Vercel 的工程能力充满敬意,也很高兴他们正在基于 Pi-Durable 进行构建。
相似文章
@oragnes: 最近挖到一个 Harness 硬核的开源项目:pi(前阵子刚从 badlogic 迁到 earendil-works 旗下)。 是一套为开发者兜底的 AI Agent 基础设施全家桶 + 终端编程助手 CLI。 少造点轮子:直接提供了一套…
Pi 是一个开源的 AI Agent 基础设施套件和终端编程助手 CLI,提供统一 API 以抹平多模型差异,支持并发工具调用以降低延迟,并允许开发者控制思考预算。
让每个 harness 都具备持久性(7 分钟阅读)
Vercel 发布开源工具 durable-harness,让 Pi、OpenCode、Codex、Claude Code 等编码代理在云端具备持久性,可在崩溃或函数超时后从日志恢复会话与工作。
@rauchg:Vercel CI 通过以下方式解决“AI 编程瓶颈”:① 快速稳定的基础设施(工作更高效)② Turborepo 集成……
Vercel 推出 Vercel CI,通过 Turborepo 智能缓存跳过任务、全球集群基础设施,以及面向 AI 代理的 MCP 和 CLI 支持,实现 2 至 6 倍的 CI 加速,主打“智能体 CI”理念,现已面向所有套餐开放 Beta 测试。
@JoshARosen: https://x.com/JoshARosen/status/2107840212915077350
一篇架构对比文章,分析 Pi Durable 与 OpenCode 的设计差异:Pi Durable 将模型生成、工具调用等序列化为可调度的持久任务,使工作不再绑定于单个进程,而传统会话式 harness(如 OpenCode、Claude Code、Codex)仍依赖进程内的活动 agent 循环。
@yibie: https://x.com/yibie/status/2108478625653862637
Armin Ronacher 详解 Pi Durable 如何让 agent 进程崩溃后能从中断处继续运行:通过"效果三明治"(意图、执行、结果存储)实现持久化,而非事件溯源,并结合版本化文档存储管理 agent 应用状态,支持部署到 Vercel、Cloudflare DO、E2B 等平台。