Sign inConnect your agent
infochanged

Agents, Workers - Run OpenCode 2.0 on Cloudflare with the Agents SDK

Announced
Tags
Agents, Workers
Severity
info, set by reef/rss-rule-v1
Source
https://developers.cloudflare.com/changelog/post/2026-10-12-opencode-harness/

<p>The <a href="https://developers.cloudflare.com/agents/">Agents SDK</a> now supports <a href="https://opencode.ai/v2/docs/build/sdk/" target="_blank" rel="noopener">OpenCode 2.0<span class="external-link"> ↗︎</span></a> through the experimental <code>OpenCodeHarness</code>. Run OpenCode inside a plain Durable Object, with sessions stored in SQLite and Lifecycle jobs that wake interrupted work after eviction.</p> <p>The <code>agents/models/opencode</code> provider connects OpenCode to Workers AI through the <code>AI</code> binding. OpenCode plugins extend the harness with custom tools, remote MCP servers, and skills. Refer to <a href="https://opencode.ai/v2/docs/build/sdk/cloudflare/" target="_blank" rel="noopener">OpenCode's Cloudflare SDK documentation<span class="external-link"> ↗︎</span></a> for the embedded host API.</p> <button type="button" data-nb-button class="group inline-flex w-max shrink-0 items-center justify-center rounded-full font-medium whitespace-nowrap no-underline shadow-xs transition-colors select-none focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50 bg-card text-foreground ring ring-border hover:bg-accent hover:ring-border-strong h-10 gap-2 px-4 text-sm copy-prompt-btn group/copy cursor-copy" data-prompt="Read https://developers.cloudflare.com/agents/harnesses/opencode/ and the example at https://github.com/cloudflare/agents/tree/main/examples/next/harnesses/opencode, then use them to build and deploy an OpenCode 2.0 agent on Cloudflare with the Agents SDK. Use a plain Durable Object with OpenCodeHarness and Workers AI, remove unsupported local tools, and add authentication and prompt quotas before exposing user sessions. Explain the experimental API and recovery limitations. Give me the deployed URL." data-tooltip="Build and deploy an OpenCode agent"><span class="inline-flex items-center gap-2.5 text-base font-medium"><span class="relative flex h-5 shrink-0 items-center justify-start gap-[3px]" aria-hidden="true"><img src="https://developers.cloudflare.com/icons/agents/claude/light.svg" alt="" class="block h-5 w-5 dark:hidden" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/claude/dark.svg" alt="" class="hidden h-5 w-5 dark:block" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/codex/light.svg" alt="" class="block h-5 w-5 dark:hidden" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/codex/dark.svg" alt="" class="hidden h-5 w-5 dark:block" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/cursor/light.svg" alt="" class="block h-5 w-5 dark:hidden" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/cursor/dark.svg" alt="" class="hidden h-5 w-5 dark:block" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/opencode/light.svg" alt="" class="block h-5 w-5 dark:hidden" loading="lazy" decoding="async"><img src="https://developers.cloudflare.com/icons/agents/opencode/dark.svg" alt="" class="hidden h-5 w-5 dark:block" loading="lazy" decoding="async"></span><span class="group-data-[copied=true]/copy:hidden">Copy prompt</span><span class="hidden group-data-[copied=true]/copy:inline">Prompt copied!</span></span></button><script type="module" src="https://developers.cloudflare.com/home/runner/work/cloudflare-docs/cloudflare-docs/src/components/CopyPromptButton.astro?astro&type=script&index=0&lang.ts"></script> <p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/agents/tree/main/examples/next/harnesses/opencode" target="_blank" rel="noopener"><img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare"></a></p> <p>Install Agents SDK 0.28.0 or later with the OpenCode packages:</p> <script> if (!customElements.get("nb-pm-restore")) { customElements.define( "nb-pm-restore", class extends HTMLElement { connectedCallback() { const card = this.closest("[data-nb-pm]"); if (!card) return; let saved; try { saved = sessionStorage.getItem("ui-pm-tab"); } catch { return; } if (!saved) return; const tabs = card.querySelectorAll("[data-nb-pm-tab]"); let idx = -1; tabs.forEach(function (t, i) { if (t.textContent.trim() === saved) idx = i; }); if (idx < 1) return; tabs.forEach(function (t, i) { t.setAttribute("aria-selected", String(i === idx)); }); card.querySelectorAll("[data-nb-pm-panel]").forEach(function (p, i) { p.hidden = i !== idx; }); } }, ); } </script><div data-nb-pm class="w-full"><div class="flex w-full flex-col overflow-hidden rounded-lg text-sm ring ring-border bg-card"><div class="flex items-center gap-2 px-3 py-2 text-[0.8125rem] font-medium leading-5 text-muted-foreground bg-[var(--nb-surface-sunken)]" role="tablist" aria-label="Package manager"><button role="tab" type="button" aria-selected="true" aria-controls="pm-panel-pm-c6b82042-npm" id="pm-tab-pm-c6b82042-npm" data-nb-pm-tab class="text-muted-foreground hover:bg-accent hover:text-foreground aria-selected:bg-selected aria-selected:text-foreground focus-visible:outline-ring m-0 cursor-pointer rounded-md border-0 bg-transparent px-2 py-0.5 text-xs leading-5 font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2">npm</button><button role="tab" type="button" aria-selected="false" aria-controls="pm-panel-pm-c6b82042-yarn" id="pm-tab-pm-c6b82042-yarn" data-nb-pm-tab class="text-muted-foreground hover:bg-accent hover:text-foreground aria-selected:bg-selected aria-selected:text-foreground focus-visible:outline-ring m-0 cursor-pointer rounded-md border-0 bg-transparent px-2 py-0.5 text-xs leading-5 font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2">yarn</button><button role="tab" type="button" aria-selected="false" aria-controls="pm-panel-pm-c6b82042-pnpm" id="pm-tab-pm-c6b82042-pnpm" data-nb-pm-tab class="text-muted-foreground hover:bg-accent hover:text-foreground aria-selected:bg-selected aria-selected:text-foreground focus-visible:outline-ring m-0 cursor-pointer rounded-md border-0 bg-transparent px-2 py-0.5 text-xs leading-5 font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2">pnpm</button><button role="tab" type="button" aria-selected="false" aria-controls="pm-panel-pm-c6b82042-bun" id="pm-tab-pm-c6b82042-bun" data-nb-pm-tab class="text-muted-foreground hover:bg-accent hover:text-foreground aria-selected:bg-selected aria-selected:text-foreground focus-visible:outline-ring m-0 cursor-pointer rounded-md border-0 bg-transparent px-2 py-0.5 text-xs leading-5 font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2">bun</button></div><div role="tabpanel" id="pm-panel-pm-c6b82042-npm" aria-labelledby="pm-tab-pm-c6b82042-npm" data-nb-pm-panel class="bg-card ring-border relative overflow-hidden rounded-lg text-inherit ring"><div class="flex items-stretch"><pre class="text-foreground my-0 min-w-0 grow overflow-x-auto border-0 bg-transparent px-4 py-3 font-mono text-sm leading-relaxed whitespace-pre"><code data-nb-pm-code><span class="text-success">npm</span><span class="text-warning"> i agents@latest @opencode/sdk@2 @opencode/plugin@2</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="npm i agents@latest @opencode/sdk@2 @opencode/plugin@2" aria-label="Copy to clipboard" class="border-border text-muted-foreground hover:text-foreground focus-visible:outline-ring m-0 flex shrink-0 cursor-pointer items-center justify-center border-0 border-l border-solid bg-transparent px-3 transition-colors focus-visible:outline-2 focus-visible:-outline-offset-2"><svg width="1em" height="1em" viewBox="0 0 256 256" class="h-[18px] w-[18px]" data-icon="ph:copy"><path fill="currentColor" d="M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8m-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"/></svg><svg width="1em" height="1em" viewBox="0 0 256 256" class="hidden h-[18px] w-[18px]" data-icon="ph:check"><path fill="currentColor" d="m229.66 77.66l-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69L218.34 66.34a8 8 0 0 1 11.32 11.32"/></svg></button></div></div><div role="tabpanel" id="pm-panel-pm-c6b82042-yarn" aria-labelledby="pm-tab-pm-c6b82042-yarn" hidden data-nb-pm-panel class="bg-card ring-border relative overflow-hidden rounded-lg text-inherit ring"><div class="flex items-stretch"><pre class="text-foreground my-0 min-w-0 grow overflow-x-auto border-0 bg-transparent px-4 py-3 font-mono text-sm leading-relaxed whitespace-pre"><code data-nb-pm-code><span class="text-success">yarn</span><span class="text-warning"> add agents@latest @opencode/sdk@2 @opencode/plugin@2</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="yarn add agents@latest @opencode/sdk@2 @opencode/plugin@2" aria-label="Copy to clipboard" class="border-border text-muted-foreground hover:text-foreground focus-visible:outline-ring m-0 flex shrink-0 cursor-pointer items-center justify-center border-0 border-l border-solid bg-transparent px-3 transition-colors focus-visible:outline-2 focus-visible:-outline-offset-2"><svg width="1em" height="1em" viewBox="0 0 256 256" class="h-[18px] w-[18px]" data-icon="ph:copy"><path fill="currentColor" d="M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8m-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"/></svg><svg width="1em" height="1em" viewBox="0 0 256 256" class="hidden h-[18px] w-[18px]" data-icon="ph:check"><path fill="currentColor" d="m229.66 77.66l-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69L218.34 66.34a8 8 0 0 1 11.32 11.32"/></svg></button></div></div><div role="tabpanel" id="pm-panel-pm-c6b82042-pnpm" aria-labelledby="pm-tab-pm-c6b82042-pnpm" hidden data-nb-pm-panel class="bg-card ring-border relative overflow-hidden rounded-lg text-inherit ring"><div class="flex items-stretch"><pre class="text-foreground my-0 min-w-0 grow overflow-x-auto border-0 bg-transparent px-4 py-3 font-mono text-sm leading-relaxed whitespace-pre"><code data-nb-pm-code><span class="text-success">pnpm</span><span class="text-warning"> add agents@latest @opencode/sdk@2 @opencode/plugin@2</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="pnpm add agents@latest @opencode/sdk@2 @opencode/plugin@2" aria-label="Copy to clipboard" class="border-border text-muted-foreground hover:text-foreground focus-visible:outline-ring m-0 flex shrink-0 cursor-pointer items-center justify-center border-0 border-l border-solid bg-transparent px-3 transition-colors focus-visible:outline-2 focus-visible:-outline-offset-2"><svg width="1em" height="1em" viewBox="0 0 256 256" class="h-[18px] w-[18px]" data-icon="ph:copy"><path fill="currentColor" d="M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8m-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"/></svg><svg width="1em" height="1em" viewBox="0 0 256 256" class="hidden h-[18px] w-[18px]" data-icon="ph:check"><path fill="currentColor" d="m229.66 77.66l-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69L218.34 66.34a8 8 0 0 1 11.32 11.32"/></svg></button></div></div><div role="tabpanel" id="pm-panel-pm-c6b82042-bun" aria-labelledby="pm-tab-pm-c6b82042-bun" hidden data-nb-pm-panel class="bg-card ring-border relative overflow-hidden rounded-lg text-inherit ring"><div class="flex items-stretch"><pre class="text-foreground my-0 min-w-0 grow overflow-x-auto border-0 bg-transparent px-4 py-3 font-mono text-sm leading-relaxed whitespace-pre"><code data-nb-pm-code><span class="text-success">bun</span><span class="text-warning"> add agents@latest @opencode/sdk@2 @opencode/plugin@2</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="bun add agents@latest @opencode/sdk@2 @opencode/plugin@2" aria-label="Copy to clipboard" class="border-border text-muted-foreground hover:text-foreground focus-visible:outline-ring m-0 flex shrink-0 cursor-pointer items-center justify-center border-0 border-l border-solid bg-transparent px-3 transition-colors focus-visible:outline-2 focus-visible:-outline-offset-2"><svg width="1em" height="1em" viewBox="0 0 256 256" class="h-[18px] w-[18px]" data-icon="ph:copy"><path fill="currentColor" d="M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8m-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"/></svg><svg width="1em" height="1em" viewBox="0 0 256 256" class="hidden h-[18px] w-[18px]" data-icon="ph:check"><path fill="currentColor" d="m229.66 77.66l-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69L218.34 66.34a8 8 0 0 1 11.32 11.32"/></svg></button></div></div><nb-pm-restore style="display:contents"></nb-pm-restore></div></div><script type="module" src="https://developers.cloudflare.com/home/runner/work/cloudflare-docs/cloudflare-docs/src/components/ui/package-managers/PackageManagerTabs.astro?astro&type=script&index=0&lang.ts"></script> <p>Create a harness and install a Lifecycle on your Durable Object:</p> <div><div data-nb-tabs data-nb-sync-key="workersExamples" class><div class="relative flex border-b border-border" role="tablist" data-nb-tabs-list><span class="bg-primary pointer-events-none absolute -bottom-px h-0.5 rounded-t-sm transition-[left,width] duration-200 ease-out" data-nb-tabs-indicator aria-hidden="true"></span></div><div class="mt-3"><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="JavaScript" class><figure class="nb-code-figure" data-nb-lang="js"><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="js" data-nb-lang="js"><code><span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { DurableObject } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { Lifecycle } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/lifecycle"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { OpenCodeWorkerd } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@opencode/sdk/workerd"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { OpenCodeHarness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/opencode"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createAI } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/models/opencode"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> workerTools </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "./worker-tools"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> class</span><span class="nb-shiki-1t8gfj"> Assistant</span><span class="nb-shiki-1itgoe"> extends</span><span class="nb-shiki-1t8gfj"> DurableObject</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-1jdh33"> ai</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createAI</span><span class="nb-shiki-140thh">({ binding: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">AI</span><span class="nb-shiki-140thh"> });</span></span> <span class="line"><span class="nb-shiki-1jdh33"> harness</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> OpenCodeHarness</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> opencode</span><span class="nb-shiki-140thh">: ({ </span><span class="nb-shiki-1jdh33">storage</span><span class="nb-shiki-140thh"> }) </span><span class="nb-shiki-1itgoe">=></span></span> <span class="line"><span class="nb-shiki-140thh"> OpenCodeWorkerd.</span><span class="nb-shiki-1t8gfj">create</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> storage,</span></span> <span class="line"><span class="nb-shiki-140thh"> models: { fetch: </span><span class="nb-shiki-dzsirb">false</span><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> plugins: [</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ai.plugin, workerTools],</span></span> <span class="line"><span class="nb-shiki-140thh"> }),</span></span> <span class="line"><span class="nb-shiki-140thh"> defaults: {</span></span> <span class="line"><span class="nb-shiki-140thh"> model: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.</span><span class="nb-shiki-1t8gfj">ai</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"@cf/moonshotai/kimi-k2.7-code"</span><span class="nb-shiki-140thh">, {</span></span> <span class="line"><span class="nb-shiki-140thh"> reasoningEffort: </span><span class="nb-shiki-mdbnqw">"low"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> }),</span></span> <span class="line"><span class="nb-shiki-140thh"> agent: </span><span class="nb-shiki-mdbnqw">"build"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1jdh33"> lifecycle</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> Lifecycle.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">).</span><span class="nb-shiki-1t8gfj">use</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.harness);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> ask</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">prompt</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-140thh"> { </span><span class="nb-shiki-dzsirb">status</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">text</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">reason</span><span class="nb-shiki-140thh"> } </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-dzsirb"> this</span><span class="nb-shiki-140thh">.harness.</span><span class="nb-shiki-1t8gfj">prompt</span><span class="nb-shiki-140thh">(prompt);</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> { status, text, reason };</span></span> <span class="line"><span class="nb-shiki-140thh"> }</span></span> <span class="line"><span class="nb-shiki-140thh">}</span></span></code></pre></figure></div><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="TypeScript" class><figure class="nb-code-figure" data-nb-lang="ts"><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="ts" data-nb-lang="ts"><code><span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { DurableObject } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { Lifecycle } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/lifecycle"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { OpenCodeWorkerd } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@opencode/sdk/workerd"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { OpenCodeHarness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/opencode"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createAI } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/models/opencode"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> workerTools </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "./worker-tools"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> class</span><span class="nb-shiki-1t8gfj"> Assistant</span><span class="nb-shiki-1itgoe"> extends</span><span class="nb-shiki-1t8gfj"> DurableObject</span><span class="nb-shiki-140thh">&lt;</span><span class="nb-shiki-1t8gfj">Env</span><span class="nb-shiki-140thh">&gt; {</span></span> <span class="line"><span class="nb-shiki-1jdh33"> ai</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createAI</span><span class="nb-shiki-140thh">({ binding: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">AI</span><span class="nb-shiki-140thh"> });</span></span> <span class="line"><span class="nb-shiki-1jdh33"> harness</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> OpenCodeHarness</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> opencode</span><span class="nb-shiki-140thh">: ({ </span><span class="nb-shiki-1jdh33">storage</span><span class="nb-shiki-140thh"> }) </span><span class="nb-shiki-1itgoe">=&gt;</span></span> <span class="line"><span class="nb-shiki-140thh"> OpenCodeWorkerd.</span><span class="nb-shiki-1t8gfj">create</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> storage,</span></span> <span class="line"><span class="nb-shiki-140thh"> models: { fetch: </span><span class="nb-shiki-dzsirb">false</span><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> plugins: [</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ai.plugin, workerTools],</span></span> <span class="line"><span class="nb-shiki-140thh"> }),</span></span> <span class="line"><span class="nb-shiki-140thh"> defaults: {</span></span> <span class="line"><span class="nb-shiki-140thh"> model: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.</span><span class="nb-shiki-1t8gfj">ai</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"@cf/moonshotai/kimi-k2.7-code"</span><span class="nb-shiki-140thh">, {</span></span> <span class="line"><span class="nb-shiki-140thh"> reasoningEffort: </span><span class="nb-shiki-mdbnqw">"low"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> }),</span></span> <span class="line"><span class="nb-shiki-140thh"> agent: </span><span class="nb-shiki-mdbnqw">"build"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> },</span></span> <span class="line"><span class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1jdh33"> lifecycle</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> Lifecycle.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">).</span><span class="nb-shiki-1t8gfj">use</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.harness);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> ask</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">prompt</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-dzsirb"> string</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-140thh"> { </span><span class="nb-shiki-dzsirb">status</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">text</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">reason</span><span class="nb-shiki-140thh"> } </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-dzsirb"> this</span><span class="nb-shiki-140thh">.harness.</span><span class="nb-shiki-1t8gfj">prompt</span><span class="nb-shiki-140thh">(prompt);</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> { status, text, reason };</span></span> <span class="line"><span class="nb-shiki-140thh"> }</span></span> <span class="line"><span class="nb-shiki-140thh">}</span></span></code></pre></figure></div></div></div><script type="module" src="https://developers.cloudflare.com/home/runner/work/cloudflare-docs/cloudflare-docs/src/components/ui/tabs/Tabs.astro?astro&type=script&index=0&lang.ts"></script></div> <p>The <a href="https://developers.cloudflare.com/agents/harnesses/opencode/">OpenCode harness guide</a> includes the <code>workerTools</code> plugin, Wrangler configuration, and session APIs. The <a href="https://github.com/cloudflare/agents/tree/main/examples/next/harnesses/opencode" target="_blank" rel="noopener">working example<span class="external-link"> ↗︎</span></a> adds a browser UI, WebSocket streaming, and Workspace tools from <code>@cloudflare/computer</code> for files and code execution.</p>

The text above is the source's. reef added the severity, the dates it could read from the text, and the endpoints and scopes named in code.