OpenCode v2 在 Cloudflare 上怎么用:使用场景与 SDK 入门
官方文档:OpenCode v2 · Cloudflare SDK
AI 参与说明(Agent:Codex):本文依据上述官方入口及相关 SDK、Plugins 和 Cloudflare 文档,讲解使用场景、接入步骤与运行边界。资料核验于 2026-09-09;场景中的业务工具由应用自行实现。
AI 参与及修订记录
AI 参与说明(Agent:Cursor):本文由 Cursor 根据 OpenCode 官方 V2 文档、Cloudflare 官方文档、npm registry 当前包信息与站内既有 Durable Object / Agents SDK / Sandbox 资料辅助调研、撰写和校验。资料核验于 2026-09-09。OpenCode V2 SDK 仍处于 beta,包名、入口与 API 可能变化。运行记录:模型
grok-4.6,提供方xAI,执行入口 Cursor。reasoning effort 与 CLI 版本未取得运行记录。
本次重写与校验(2026-09-09,Agent:Codex):以官方 Cloudflare SDK 入口重组使用场景和调用步骤。运行记录:模型
gpt-6-astra,reasoning effortultra,执行入口 Codex Desktop,提供方openai,CLI 版本0.153.4(不代表桌面 App 版本)。历史记录仅对应此前阶段。
OpenCode v2 可以作为 SDK 嵌入 Cloudflare 上的应用:用户在网页里提出任务,服务端的 OpenCode 调用模型和工具完成工作,并保存对话上下文。它适合做仓库审查助手、Cloudflare 运维助手,以及接入远程执行环境的在线编码助手。
下面先说明这三类场景,再走一遍安装、初始化、创建 Session 和添加 Plugin 的过程。
| 英文术语 | 中文名称 | 简要解释 |
|---|---|---|
| Cloudflare Workers | 保留原名 | 承接网页请求、运行服务端代码的平台 |
| workerd | 保留原名 | Workers 使用的 JavaScript 运行时 |
| Durable Object | 持久对象 | 有稳定身份、自带持久存储的服务端对象 |
| Embedded host | 嵌入式宿主 | 在应用内部运行的 OpenCode 实例 |
| Session | 会话 | 保存用户输入、模型回复和任务上下文的单位 |
| Plugin | 插件 | 为 OpenCode 配置角色、模型和工具的扩展 |
| Tool | 工具 | 模型可调用的具体操作,例如读取文档或执行测试 |
| Sandbox SDK | 沙箱 SDK | 为命令执行、文件操作等提供隔离环境的 Cloudflare SDK |
OpenCode 在 Cloudflare 上能做什么
The workerd SDK embeds OpenCode in a Durable Object and uses its SQLite storage to retain state and durable events across eviction. 官方 Cloudflare SDK 文档
对使用者而言,最直接的变化是:可以在自己的网页或 API 背后运行 OpenCode。前端把任务交给 Worker,Worker 找到对应的 Durable Object,再由其中的 OpenCode 处理。你负责应用入口、模型配置与业务 Tool;SDK 提供 OpenCode 的运行与交互能力。
下面是基于这些能力的应用场景,并非安装 SDK 后自动附送的产品功能。
场景一:仓库审查与迁移方案助手
用户提供一段代码、一次变更或一个仓库地址,要求“检查这个 API 是否适合迁移到 Workers”。OpenCode 可以根据用户提供的材料,结合 Tool 读取的代码和文档,给出问题定位、修改建议与迁移步骤。
最容易开始的方式是直接把小段代码作为任务输入。需要按需浏览完整仓库时,再提供访问 GitHub API 或代码快照的 Tool;仅把仓库 URL 发给 SDK,不等于已经下载仓库或获得读取权限。
这个场景的输出是审查报告。开始时不必具备安装依赖和执行构建的能力,也能检验 OpenCode 是否适合嵌入自己的产品。
场景二:Cloudflare 运维与知识助手
用户问:“这次部署之后为什么报错?”应用提供读取已授权日志、部署信息或 R2 文档的 Tool,OpenCode 根据返回结果继续查询并组织解释。
Cloudflare 的服务通过你的代码接入。例如 R2 binding 交给 Tool 实现,Tool 再把选定文档返回给模型。模型本身不需要持有整个 Cloudflare 账户的凭据。
这类助手的价值在于围绕问题连续取证。若要进一步执行部署或修改配置,需增加对应 Tool,并在实际执行代码里落实权限校验;这不是修改一句 Agent 描述就能完成的能力。
场景三:能够改代码、跑测试的在线助手
用户在网页提交“修复这个失败的测试”,OpenCode 分析任务、决定调用哪些 Tool,再依据执行结果继续修改。
这里需要补上实际工作环境:由 Sandbox SDK、Container 或其他远程服务负责代码文件、命令和测试,Tool 把操作请求和结果接回 OpenCode。@opencode/sdk/workerd 的本地文件系统与进程服务有运行时适配边界,不能直接假定本机 CLI 的全部操作都能在 Worker 内执行。Cloudflare SDK · Sandbox SDK 架构
如果目标只是前两个场景,可以先接读取类 Tool。只有当任务确实需要执行代码时,再增加 Sandbox SDK。
它在应用里怎样运行
flowchart TD
user["网页:提交任务、查看结果"] --> worker["Worker:接收并路由请求"]
worker --> object["Durable Object<br/>提供 SQLite 存储"]
object --> host["OpenCode Embedded host<br/>组织 Session,调用模型"]
host -->|按需调用| tool["Plugin Tool<br/>读取数据或调用 Sandbox SDK"]
Worker 是对外入口;Durable Object 为 OpenCode 提供存储与实例生命周期;OpenCode 组织 Session 和模型、Tool 的交互。前端展示结果的界面仍由应用实现。
官方这篇文档的接入方式是在 Durable Object 中创建 Embedded host。下文所有代码都围绕这个入口,不需要先启动一个独立的 OpenCode HTTP 服务。SDK Overview
第一步:安装并启动一个最小实例
下面是 TypeScript 的最小健康检查示例。它验证 Worker 能否调用 Durable Object 中的 OpenCode;模型调用放在下一步。
准备一个已有的 Workers TypeScript 项目。如果尚未创建,可按 Durable Objects Getting started 选择 Worker + Durable Objects 模板。
官方当前安装入口是 bun add @opencode/sdk@dev;使用 npm 时对应 npm install @opencode/sdk@dev。V2 SDK is beta; pin the tested package version before relying on its API. SDK 安装说明
本文核验的版本为 0.0.0-dev-19380。在项目根目录安装固定版本:
npm install --save-exact @opencode/sdk@0.0.0-dev-19380
在 wrangler.jsonc 中配置入口、兼容标志,以及使用 SQLite 的 Durable Object:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "opencode-cloudflare-demo",
"main": "src/index.ts",
"compatibility_date": "2026-09-09",
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [
{ "name": "OPENCODE", "class_name": "OpenCodeDO" }
]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["OpenCodeDO"] }
]
}
这是新示例项目的配置;已有项目应保留原配置和 migration 历史,只合并所需项。nodejs_compat 来自 OpenCode 的 Cloudflare 指南,binding 和 new_sqlite_classes 来自 Durable Objects 配置说明。
src/index.ts:
import { OpenCodeWorkerd } from "@opencode/sdk/workerd"
interface Env {
OPENCODE: DurableObjectNamespace
}
export class OpenCodeDO {
private readonly host: Promise<OpenCodeWorkerd.Interface>
constructor(state: DurableObjectState) {
this.host = state.blockConcurrencyWhile(() =>
OpenCodeWorkerd.create({ storage: state.storage }),
)
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url)
if (request.method !== "GET" || url.pathname !== "/health") {
return new Response("Not found", { status: 404 })
}
const host = await this.host
const health = await host.health.get()
return Response.json(health)
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const object = env.OPENCODE.getByName("local-demo")
return object.fetch(request)
},
} satisfies ExportedHandler<Env>
这里的固定名称 local-demo 只用于本地验证,让重复请求访问同一个 Durable Object。实际应用应根据已经验证的用户或项目身份选择对象,不能让所有用户共享这个示例对象。
运行并检查:
npx wrangler types
npx wrangler dev
在另一个终端中请求:
curl --fail http://localhost:8787/health
预期得到 HTTP 200 和 OpenCode 的健康检查 JSON。blockConcurrencyWhile() 让请求等待初始化完成;实例存活期间复用同一个 host,不在每次 fetch() 中重新创建。对象被逐出后会重新构造,所以不能依赖 close() 一定执行来保存状态。初始化与生命周期说明
本次固定版本示例已通过 TypeScript 检查、Wrangler 4.129.0 打包和本地 workerd 健康检查,实际返回 HTTP 200、healthy: true;没有进行云端部署。
第二步:接入模型,创建 Session 并提交任务
健康检查通过后,需要配置一个可用模型及其凭据,再执行任务。Cloudflare 上不要照搬本机已登录 CLI 的假设:模型连接需要在这套服务端实例里配置,凭据通过 Worker 的 Secret 提供。OpenCode Plugins:Integrations
以 Anthropic 为例,在已被 Git 忽略的 .dev.vars 中设置 ANTHROPIC_API_KEY,值为自己的有效 API Key;线上通过 Worker Secret 配置同名变量。不要把真实值写进源码或 wrangler.jsonc。Cloudflare Secrets
模型连接可以通过 Plugin 初始化。先安装同版依赖:
npm install --save-exact @opencode/plugin@0.0.0-dev-19380
src/model-plugin.ts:
import { Plugin } from "@opencode/plugin"
export function modelPlugin(apiKey: string) {
return Plugin.define({
id: "model-credentials",
async setup(ctx) {
const active = await ctx.integration.connection.active("anthropic")
const credential = active
? await ctx.integration.connection.resolve(active)
: undefined
if (credential?.type === "key" && credential.key === apiKey) return
await ctx.integration.connect.key({
integrationID: "anthropic",
key: apiKey,
})
},
})
}
在 src/index.ts 顶部导入 modelPlugin,为 Env 增加 ANTHROPIC_API_KEY: string,并将构造函数替换为:
constructor(state: DurableObjectState, env: Env) {
this.host = state.blockConcurrencyWhile(() =>
OpenCodeWorkerd.create({
storage: state.storage,
config: { model: "anthropic/claude-sonnet-4-6" },
plugins: [modelPlugin(env.ANTHROPIC_API_KEY)],
}),
)
}
导入语句为 import { modelPlugin } from "./model-plugin"。模型 ID 应替换为该账户实际可用的模型;上例展示凭据如何从 env 进入 OpenCode,随后任务中的模型请求会使用这个服务端连接。
Plugin 先检查当前连接,避免 Durable Object 重新构造时重复保存相同凭据。示例将服务端模型连接提供给该实例,不应让浏览器传入或读取 API Key。
接着将 OpenCodeDO.fetch() 替换为以下方法。它保留 /health,并用 POST /review 接收纯文本任务、等待本轮处理,再返回 Session ID 与消息;Worker 的转发入口无需改动:
async fetch(request: Request): Promise<Response> {
const host = await this.host
const path = new URL(request.url).pathname
if (request.method === "GET" && path === "/health") {
return Response.json(await host.health.get())
}
if (request.method !== "POST" || path !== "/review") {
return new Response("Not found", { status: 404 })
}
const text = (await request.text()).trim()
if (!text) return new Response("Task text is required", { status: 400 })
const session = await host.sessions.create({ title: "Review a Worker" })
const admitted = await host.sessions.prompt({ sessionID: session.id, text })
await host.sessions.wait({ sessionID: session.id })
const messages = await host.sessions.context({ sessionID: session.id })
return Response.json({ sessionID: session.id, admitted, messages })
}
在本地开发服务中提交一个不需要仓库的任务:
curl --fail http://localhost:8787/review \
-H 'Content-Type: text/plain' \
--data-raw "Review this Worker: export default { fetch() { return new Response('Hello') } }"
模型凭据有效且本轮生成结束后,JSON 的 messages 中可读取模型回复;admitted 是提交记录。这个本地教学接口每次创建新 Session,并在同一请求内等待;给多人使用前,应接入用户认证、Session 归属校验和请求错误处理。
session.id 是后续继续提问和读取上下文的依据,应用应保留它并关联到对应用户。上述任务把待审查代码直接放入文本,因此不需要先准备真实仓库目录。
prompt() returns an admitted inbox item, not the final assistant response. admitted 用来确认输入已接收;wait() 等待 Session 的运行循环空闲,context() 获取当前上下文中的消息(发生 compaction 后不等于全部历史)。wait() 返回不等于任务成功;界面仍需检查消息和 Session 状态,处理权限请求与错误。Session API · Plugins:Sessions
需要边生成边展示时,SDK 还提供 host.events.subscribe(),返回可用 for await 消费的事件流。应用把属于当前用户和 Session 的事件转发给网页;不要把整个实例的事件直接广播给所有访问者。SDK:Stream events
通用 SDK 文档中的 location: { directory: "/workspace" } 是本地工作区示例。给 workerd 传入这个字符串不会创建 Linux 目录,也不会自动检出代码;这里直接使用文本输入来开始。
模型连接、Session 与下文 Plugin 片段已按同版包的实际类型检查;本次没有使用真实 API Key 发起模型生成。
第三步:通过 Plugin 接入自己的能力
Plugin 是把 OpenCode 用到具体业务中的扩展入口。可以修改 Agent 描述、配置模型,或者提供读取文档、查询状态等 Tool。Cloudflare 指南采用随 Worker 打包的 Plugin,并通过 plugins 传入初始化配置。官方 Customize 示例
沿用上一步安装的 @opencode/plugin,添加一个返回代码审查检查项的只读 Tool。示例内容固定,便于先观察 OpenCode 如何调用 Tool;之后再把执行函数接到实际文档源。
src/review-plugin.ts:
import { Plugin } from "@opencode/plugin"
export const reviewPlugin = Plugin.define({
id: "worker-review",
async setup(ctx) {
await ctx.tool.transform((tools) => {
tools.add({
name: "review_checklist",
description: "Read the checklist for reviewing a Cloudflare Worker",
input: { type: "object", properties: {}, additionalProperties: false },
execute: async () => ({
content: "Check HTTP methods, input validation, error responses, and secret handling.",
}),
})
})
},
})
然后在 src/index.ts 中导入,并在上一步初始化配置里保留模型连接、追加 reviewPlugin:
import { reviewPlugin } from "./review-plugin"
// 放在原有 blockConcurrencyWhile 回调中。
OpenCodeWorkerd.create({
storage: state.storage,
config: {
default_agent: "build",
model: "anthropic/claude-sonnet-4-6",
},
plugins: [modelPlugin(env.ANTHROPIC_API_KEY), reviewPlugin],
})
再次调用 /review,可以把任务写成 Use review_checklist, then review this Worker: ...。OpenCode 能调用这个 Tool,获得检查项后继续审查。若要读取 R2 中实际维护的检查项,就将 binding 通过 Plugin 工厂传入,在 execute() 中读取限定对象并返回文本。Plugins:Tools
官方 Cloudflare 页面还展示了通过 ctx.agent.transform() 修改 Agent 描述的方式。那适合定制角色说明;实际业务能力来自 Tool 的执行代码,访问权限也应在执行代码中落实。
按场景扩展时,可以这样对应:
| 想让 OpenCode 做的事 | 应用需要提供的 Tool 实现 |
|---|---|
| 解释项目中的某个文件 | 读取获授权的 GitHub 文件或代码快照 |
| 根据内部文档回答问题 | 查询文档索引,读取选定 R2 对象 |
| 分析部署失败原因 | 读取对应项目的部署状态和日志 |
| 修改代码并执行测试 | 调用 Sandbox SDK,返回变更、日志和退出码 |
这些 Tool 名称和业务操作由应用定义。Cloudflare binding 留在服务端代码中;每个 Tool 只暴露完成该任务所需的输入与结果。
使用时最需要记住的边界
- 模型需要单独接入:SDK 启动和健康检查成功,不代表模型凭据、模型权限或实际生成已经可用。
- 代码执行需要工作环境:需要 shell、依赖安装或测试时,接 Sandbox SDK 等执行服务;SQLite 保存 OpenCode 状态,不等于代码仓库工作区。
- 持久化不等于任何任务都会自动继续:官方明确保存 durable events 以支持 eviction recovery;这不直接证明任意 Tool、外部副作用或浏览器断线后的整个任务都能恢复。实际任务应验证中断、重试和恢复行为。
- Plugin 需要适配 workerd:随 Worker 打包,并检查自身及依赖是否要求本地文件系统、子进程或原生二进制。
nodejs_compat不会把 Worker 变成完整 Linux 主机。
前两类场景可以从“文本任务 → Session → 模型回复”开始,再接一个真实读取类 Tool。在线编码助手则继续补上“Tool → Sandbox SDK → 执行结果”的链路。这样的顺序能逐步验证 OpenCode 在 Cloudflare 上如何完成实际工作。