智能体
developers.cloudflare.com ·
@Cloudflare Developers
Cloudflare @cloudflare/computer 支持 Agent 代码暂停与恢复
Cloudflare 发布 @cloudflare/computer v0.7.0:在 WorkerJavaScriptBackend 上设置 onInterrupt: "replay" 后,Agent 运行的代码可在部署或崩溃后从断点继续,不重复已执行调用;自定义模块中的用户函数可调用 ctx.interrupt() 暂停运行,等待外部审批后再继续或失败。官方给出 GitHub 评论审批示例代码。
AI推荐理由 Cloudflare 官方 changelog 给出 @cloudflare/computer v0.7.0 的具体新能力:通过 onInterrupt: "replay" 让 Agent 运行的代码在部署或崩溃后恢复且不重复调用,并可用 ctx.interrupt() 在工具调用前暂停等待人工审批,附有代码示例。对构建可恢复、可审批的 Agent 执行环境有直接参考价值;局限是仅覆盖 WorkerJavaScriptBackend 场景,未给出性能或稳定性数据。
78
正文
[`@cloudflare/computer` ↗︎](https://github.com/cloudflare/computer) gives your agent a workspace to run code in. From v0.7.0, that code can resume after a deploy or crash, and pause on an external action, for example to approve a tool call.
#### Resume interrupted runs
Set `onInterrupt: "replay"` on `WorkerJavaScriptBackend`, or on a single run.
```
import { DurableObject } from "cloudflare:workers";
import { Workspace } from "@cloudflare/computer";
import { WorkerJavaScriptBackend } from "@cloudflare/computer/backends/worker-javascript";
export class MyAgent extends DurableObject {
workspace = new Workspace({
storage: this.ctx.storage,
backends: [
new WorkerJavaScriptBackend({
loader: this.env.LOADER,
onInterrupt: "replay",
}),
],
});
}
```
```
import { DurableObject } from "cloudflare:workers";
import { Workspace } from "@cloudflare/computer";
import { WorkerJavaScriptBackend } from "@cloudflare/computer/backends/worker-javascript";
export class MyAgent extends DurableObject {
workspace = new Workspace({
storage: this.ctx.storage,
backends: [
new WorkerJavaScriptBackend({
loader: this.env.LOADER,
onInterrupt: "replay",
}),
],
});
}
```
After a restart, the run carries on from where it was, without repeating calls it already made or printing its output twice.
#### Wait for approvals

User functionality can be provided to the agent's code, via [custom modules](https://developers.cloudflare.com/agents/tools/filesystem/#give-code-access-to-your-own-functions). The user function can now call `ctx.interrupt()` to pause the run until it receives an answer.
For example, to provide a GitHub module that allows an agent to post a comment on an issue with approval, an implementation of `postComment` could look like this:
```
new WorkerJavaScriptBackend({
loader: this.env.LOADER,
onInterrupt: "replay",
modules: {
// The agent's code imports this with `import { postComment } from "ws:github"`.
"ws:github": {
postComment: async ([issue, body], ctx) => {
const { approved } = await ctx.interrupt({
issue,
body,
});
if (!approved) throw new Error("The comment was rejected.");
return github.comment(issue, body, { idempotencyKey: ctx.callId });
},
},
},
});
```
```
new WorkerJavaScriptBackend({
loader: this.env.LOADER,
onInterrupt: "replay",
modules: {
// The agent's code imports this with `import { postComment } from "ws:github"`.
"ws:github": {
postComment: async ([issue, body], ctx) => {
const { approved } = await ctx.interrupt({
issue,
body,
});
if (!approved) throw new Error("The comment was rejected.");
return github.comment(issue, body, { idempotencyKey: ctx.callId });
},
},
},
});
```
When the agent's code calls `postComment()`, the run pauses at `ctx.interrupt()` until your app responds. The agent's code calls it like any other function:
```
import { postComment } from "ws:github";
export default async function ({ issue }) {
return postComment(issue, "Hello world");
}
```
The time spent waiting does not count toward its timeout. The wait also survives deploys. Fetch the pending calls with `workspace.runtime.pending()` and resolve them with `respond()`:
```
for (const call of await workspace.runtime.pending()) {
await workspace.runtime.respond(call.id, call.callId, { approved: true });
}
```
```
for (const call of await workspace.runtime.pending()) {
await workspace.runtime.respond(call.id, call.callId, { approved: true });
}
```
The run continues once all pending calls are resolved.
For setup, current limitations, and how replay works, refer to [Resume runs after a restart](https://developers.cloudflare.com/agents/tools/filesystem/#resume-runs-after-a-restart).