Skip to main content
@cognition-ai/cloudflare-agents puts a Devin cloud session behind a Cloudflare Agents AIChatAgent, so useAgentChat drives Devin the way it drives a model. Each chat is a Durable Object that owns one Devin session: the API key stays in the Worker, the transcript persists in the object’s SQLite storage, and the session keeps working in Devin’s cloud while the Durable Object hibernates. It is built on @cognition-ai/ai-sdk, which does the event-to-UI-message mapping. The Cloudflare Agents chat example is a complete app on top of it.

Setup

The @cognition-ai packages are in beta. Every release is a 0.0.1-beta.N prerelease on the beta dist-tag (currently 0.0.1-beta.7), so the @beta suffix is required: a bare npm install @cognition-ai/sdk fails on purpose. Pin the exact version in your lockfile, and keep every @cognition-ai package you use (sdk, ai-sdk, cloudflare-agents, harness-devin) on the same version; they release together. Each published version is stable, but the API can change between beta bumps; see the changelog for what moved.

Server

The whole agent is one class and a route:
src/server.ts
wrangler.jsonc
DevinChatAgent reads DEVIN_API_KEY, and optionally DEVIN_ORG_ID and DEVIN_BASE_URL, from the Worker’s bindings. Override the hooks for anything else, such as per-user keys or scoping new sessions to repositories:

Client

agent.state holds the session id and URL, status, activity, plan and pull requests, and updates live while a turn streams. Messages carry text, reasoning, dynamic-tool parts whose input is the SDK’s ToolCallDetail, and data-devin-plan / data-devin-pull-request parts; see AI SDK UI for the full mapping.

What the agent does

  • One turn per message. The first message creates a Devin session; later ones attach to it, including after hibernation, a deploy, or from another client. Messages sent mid-turn queue.
  • Stop. chat.stop() cancels the Devin turn. A command Devin was already running finishes in its cloud VM; its late output is dropped rather than folded into the next turn.
  • Permissions. Devin’s permission requests arrive as AI SDK tool approvals. Answer them with chat.addToolApprovalResponse({ id, approved }), and the same turn resumes. Approving picks allow-once; denying picks reject-once.
  • Start over. agent.stub.startOver() detaches from the session and stops the turn, so the next message starts a new session. Clear the transcript with chat.clearHistory(). The old session keeps running in the cloud.
  • Continue an existing session. agent.stub.importSession(id) rebuilds the transcript from the session’s replay and attaches future turns to it — the way to pick up a session started in the Devin app. It throws on a chat that already has a session or messages. parseSessionId(input) accepts a session id or a Devin web app URL.
  • Recovery. If the Durable Object restarts mid-turn, what already streamed is kept and the prompt is not sent again: Devin already has it.
  • Late events. Events from a turn the chat moved on from (stopped, started over) never touch the new session’s state.
Workers can’t start processes, so this is cloud sessions only; LocalDevin needs Node.js or Bun.

Building your own agent

For a different agent shape, connectDevin(env) opens a connection from the bindings, and reduceDevinChatState(state, event) projects session events onto DevinChatState. Combine them with toUIMessageStream, toUIMessages and ToolApprovals from @cognition-ai/ai-sdk.