Skip to content

Add experimental package for working with OpenCode sessions#1274

Draft
aron-cf wants to merge 7 commits intomainfrom
example-opencode-2
Draft

Add experimental package for working with OpenCode sessions#1274
aron-cf wants to merge 7 commits intomainfrom
example-opencode-2

Conversation

@aron-cf
Copy link
Copy Markdown

@aron-cf aron-cf commented Apr 7, 2026

This PR adds @cloudflare/agents-opencode, a new package that wraps the OpenCode coding agent for use inside Cloudflare sandbox containers. It handles session lifecycle, provider detection, streaming, backup and restore, and file watching — so you can drop a single tool into any streamText call and get a fully autonomous coding agent.

The package exposes two levels of API. The high-level opencodeTask() function returns an AI SDK compatible tool that manages everything automatically. The low-level OpenCodeSession class gives full control over the session lifecycle for custom integrations. Both yield OpenCodeRunOutput snapshots as the agent works, containing the sub-conversation messages, file diffs, diagnostics, process info, and todos.

The outer model can set an outputFile parameter on the tool call to designate a sandbox file as the task's downloadable output. The value flows through to OpenCodeRunOutput so clients can render a download button or link.

An example project at examples/opencode demonstrates the full integration as a chat application backed by a SandboxChatAgent durable object. It includes a React frontend that renders the OpenCode sub-conversation inline with collapsible panels, file change summaries, process status, and — when a task produces an output file — a download button. The server exposes an /artifacts/<sandboxId>/<path> route that streams files directly from the sandbox container.

API

The high-level entry point is opencodeTask(). It returns an AI SDK tool that you wire into any streamText or generateText call. It handles sandbox provisioning, provider credential detection, session creation, streaming, and backup automatically.

import { opencodeTask } from "@cloudflare/agents-opencode";
import { streamText } from "ai";

const result = streamText({
  model: workersai("@cf/moonshotai/kimi-k2.5"),
  tools: {
    opencode: opencodeTask({
      sandbox: env.Sandbox, // DurableObjectNamespace binding
      name: this.name, // sandbox instance name
      env, // environment bindings (for credential detection)
      storage: this.ctx.storage // durable object storage for session state
    })
  }
});

The tool itself accepts three parameters from the calling model. prompt is the coding task description. sessionId optionally continues a previous session. outputFile optionally designates a sandbox file path as the downloadable output artifact. Provider credentials are auto-detected from environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, or CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_KEY), or you can pass them explicitly via the credentials option. You can also pass a userConfig to override the OpenCode configuration, including the model.

opencode: opencodeTask({
  sandbox: env.Sandbox,
  name: this.name,
  env,
  storage: this.ctx.storage,
  credentials: [{ provider: "anthropic", apiKey: env.ANTHROPIC_API_KEY }],
  userConfig: { model: "anthropic/claude-sonnet-4-20250514" },
  description: "Custom tool description for your use case",
}),

For full lifecycle control, use OpenCodeSession directly. This is useful when you need to manage the sandbox session outside of the AI SDK tool abstraction, for example to integrate file watching or custom backup strategies.

import { OpenCodeSession } from "@cloudflare/agents-opencode";

const session = new OpenCodeSession(env.Sandbox, "my-agent");
await session.start(env, storage);

// Run a prompt and stream snapshots
for await (const snapshot of session.run("Build a REST API with Hono")) {
  // snapshot.status: "working" | "complete" | "error"
  // snapshot.messages: UIMessage[] (the agent's sub-conversation)
  // snapshot.filesEdited: string[]
  // snapshot.diffs: FileDiff[]
  // snapshot.processes: ProcessInfo[]
  // snapshot.outputFile?: string (if set by the caller)
}

// Backup sandbox filesystem and session state (persisted to R2 via wrangler.jsonc config)
await session.backup(storage);

// Restore a previous session from R2 backup
const restored = await restoreSession(session.sandbox, storage);

// Watch for file changes in /workspace — useful for displaying file trees in the UI
session.startFileWatcher((msg) => broadcast(msg));

Each OpenCodeRunOutput snapshot contains the full state of the run: status, sessionId, messages (an array of AI SDK UIMessage objects representing the agent's sub-conversation), filesEdited, fileChanges, diffs, diagnostics, processes, todos, modelID, summary, error, and outputFile.

The package also exports lower-level utilities for provider detection (detectProviders, resolveProviders), stream accumulation to track changes over time (OpenCodeStreamAccumulator), file watching (FileWatcher), and backup management (backupSession, restoreSession).

examples/opencode

The example project is a full chat application that delegates coding tasks to OpenCode. It uses @cloudflare/ai-chat for the chat agent framework and @cloudflare/sandbox for the container runtime.

image

To run it locally you need Docker running (the sandbox container builds from a Dockerfile) and at least one provider credential set. Copy .env.example to .env and fill in your keys.

cd examples/opencode
cp .env.example .env

# Edit .env with at least one provider credential set:
#   ANTHROPIC_API_KEY, OPENAI_API_KEY,
#   or CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_KEY

npm install
npm run dev

The worker configuration in wrangler.jsonc sets up the sandbox container binding, an R2 bucket for workspace backup, and the Workers AI binding. The SandboxChatAgent durable object in server.ts wires up opencodeTask() with a system prompt that instructs the outer model to delegate coding tasks and use the outputFile parameter for downloadable artifacts. The React client in client.tsx connects via WebSocket and renders the chat with inline OpenCode sub-conversations, file diffs, process panels, and download buttons.

Important

An R2 bucket is required for sandbox backup and restore. The bucket binding is configured in wrangler.jsonc under r2_buckets. Without it the sandbox filesystem will not persist across container evictions.

Verification

Testing covers:

  • Stream accumulation — verifies that server-sent events are correctly accumulated into OpenCodeRunOutput snapshots with the right status transitions, message assembly, and metadata extraction
  • Provider detection — verifies that credentials are correctly auto-detected from environment variables across all supported providers (Anthropic, OpenAI, Cloudflare Workers AI) and that explicit credentials take precedence
  • End-to-end example — the example project was run locally against multiple providers to verify session lifecycle, streaming, backup and restore, and file watching

To manually verify the artifact download feature, start the example locally and ask the agent to produce a file (for example, "Create a CSV file with sample user data"). The completed sub-conversation panel should show a download button linking to /artifacts/<sessionId>/<path>. Clicking it streams the file from the sandbox. Tasks that do not produce output files render normally with no download button.

@aron added 7 commits April 7, 2026 21:16
Wrap the OpenCode coding agent for use inside Cloudflare sandbox
containers. The package handles session lifecycle, provider detection,
streaming, backup and restore, and file watching.

The high-level entry point is `opencodeTask()`, which returns an AI SDK
compatible tool you can drop into any `streamText` call. It auto-detects
provider credentials from environment variables, manages the sandbox
session, and streams `OpenCodeRunOutput` snapshots containing the
agent's sub-conversation, file diffs, diagnostics, and process info.

For full lifecycle control, `OpenCodeSession` gives direct access to
start, run, backup, restore, and file watch operations.

The `packages/agents/README.md` is updated with a section pointing to
the new package.
A full chat application at `examples/opencode` that delegates coding
tasks to an autonomous OpenCode agent running inside a sandbox
container. Uses `@cloudflare/ai-chat` for the agent framework and
`@cloudflare/sandbox` for the container runtime.

The server wires up `opencodeTask()` with a system prompt, exposes an
`/artifacts/<sandboxId>/<path>` route for downloading files from the
sandbox, and handles session backup and restore via R2.

The React client renders the chat with inline OpenCode sub-conversations
showing collapsible message panels, file change summaries, process
status, and a download button when a task produces an output file.
All @vitest/* projects needed to be pinned to 4.1.3.
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 7, 2026

⚠️ No Changeset found

Latest commit: e00de2d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant