Skip to main content
Source: cloudflare-agents — requires 0.0.1-beta.2 or later.
The Cloudflare Agents example. Every conversation is a Cloudflare Agent that drives a Devin cloud session through @cognition-ai/sdk; useAgentChat streams Devin’s typed events — text, reasoning, tool calls, plans, permission prompts, pull requests — into the browser, and the chat, its transcript and its Devin session survive refreshes, hibernation and deploys in Durable Object storage. The console is laid out like harness chat: chats on the left, the transcript in the middle, and on the right a Session panel (status, activity, cost, a link to the session in the Devin app) and a Workspace panel (Devin’s plan, its pull requests, and the files it touched). Unlike harness chat, nothing runs in a sandbox you own: Devin works in its own cloud VM, and the Worker only holds the API key and relays events. That is also why this example can continue a session you started in the Devin app.
Cloudflare Agents chat: a chat list, a transcript with reasoning, write and bash cards showing a passing npm test run and Devin's reply, a Session panel with the session id and status, and a Workspace panel listing three files with +/− counts

The console: Devin's reasoning, file writes and a test run as typed cards; the Session panel with the cloud session's status; the Workspace panel with the files it touched

How it fits together

  • Workspace extends Agent (src/server.ts) is the sidebar: createChat, deleteChat and recentSessions are @callable() methods, the chat list lives in SQLite and is broadcast as Agent state, and onBeforeSubAgent only lets clients reach chats this workspace created.
  • DevinChat extends DevinChatAgent is one chat, a facet of the workspace. @cognition-ai/cloudflare-agents does all of the Devin work — session create and attach, one turn per message, stop, permissions as tool approvals, start over, importing a session, recovery. The example adds onChatResponse (the chat’s sidebar entry), sessionSnapshot (what the cloud says about the session between turns) and respondToPermission.
  • src/console.tsx and src/components/ are the React app: one chronological message.parts.map() per message, and a card per tool call rendered from the SDK’s normalized ToolCallDetail.
The DEVIN_API_KEY secret only exists in the Worker. The browser talks to your Agents, never to Devin.

The key pattern

The server is a DevinChatAgent plus whatever your app needs around it:
src/server.ts (excerpt)
The client is the stock Agents hooks, typed with the package’s state and message types:
src/console.tsx (excerpt)

What maps to what

Internal bookkeeping the cloud reports as tool calls is hidden, as in the Devin app. The full mapping is in AI SDK UI.

Lifecycle

Nothing here stops a Devin session remotely; archive or end sessions in the Devin app or with devin.api.

Run it

bun run test runs the Worker in workerd against a fake Devin ACP server; bun run deploy publishes it (wrangler secret put DEVIN_API_KEY first).
This is a single-user demo: there is no login, and anyone who can reach the Worker can use your Devin key through it. Put Cloudflare Access in front of it or add your own auth before sharing a URL; the example’s README has the three changes that take.