Agents, Workers - Run the Pi Durable harness 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-02-pi-harness/
<p>The <a href="https://developers.cloudflare.com/agents/">Agents SDK</a> now provides first-class support for building agents using the Pi harness. You can build long-running agents using the combination of <a href="https://earendil.com/posts/pi-1-0/" target="_blank" rel="noopener">Pi 1.0<span class="external-link"> ↗︎</span></a>, <a href="https://earendil.com/posts/pi-durable/" target="_blank" rel="noopener">Pi Durable<span class="external-link"> ↗︎</span></a>, and the new <code>PiHarness</code> class that the Cloudflare Agents SDK provides, ensuring your agent's work is durably persisted, even if interrupted mid-turn.</p> <p>Built with <a href="https://earendil.com/" target="_blank" rel="noopener">Earendil<span class="external-link"> ↗︎</span></a>, this integration is our first step toward first-class support for third-party agent harnesses on Cloudflare.</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/pi/ and the example at https://github.com/cloudflare/agents/tree/main/examples/next/harnesses/pi, then use them to build and deploy my first Pi Durable agent on Cloudflare with the Agents SDK. Give me the deployed URL." data-tooltip="Build and deploy a Pi Durable 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/pi" target="_blank" rel="noopener"><img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare"></a></p> <aside role="note" aria-label="Beta" class="aside-card flex items-start gap-3 rounded-lg px-4 py-3 my-4" style="--_c: var(--nb-warning); --_t: var(--nb-warning-muted);" data-astro-cid-znle5jil><span class="flex h-[1.375em] shrink-0 items-center" aria-hidden="true" data-astro-cid-znle5jil><svg width="1em" height="1em" viewBox="0 0 256 256" class="h-[1em] w-[1em]" data-astro-cid-znle5jil="true" data-icon="ph:warning"><path fill="currentColor" d="M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72m-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72M120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0m20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12"/></svg></span><div class="flex min-w-0 flex-1 flex-col gap-0.5" data-astro-cid-znle5jil><p class="m-0 text-base leading-snug font-semibold" data-astro-cid-znle5jil>Beta</p><div class="aside-card-body text-sm leading-normal" data-astro-cid-znle5jil><p><code>PiHarness</code> is in beta. <a href="https://earendil.com/posts/pi-durable/" target="_blank" rel="noopener">Pi Durable<span class="external-link"> ↗︎</span></a> is a new, experimental package, and the <code>PiHarness</code> API will likely change as Pi Durable matures.</p></div></div></aside> <p><code>PiHarness</code> is a new "Lifecycle capability" provided by the Cloudflare Agents SDK. Pi Durable provides the agent harness and the Lifecycle is responsible for keeping the agent running in the Durable Object. The Lifecycle is a core concept in the Agents SDK ensuring that long-running work can run in a Durable Object, surviving restarts, crashes, and network issues. We will share more on Lifecycle capabilities in the near future.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="install">Install</h4><a class="anchor-link" href="#install"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <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-3c6fc231-npm" id="pm-tab-pm-3c6fc231-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-3c6fc231-yarn" id="pm-tab-pm-3c6fc231-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-3c6fc231-pnpm" id="pm-tab-pm-3c6fc231-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-3c6fc231-bun" id="pm-tab-pm-3c6fc231-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-3c6fc231-npm" aria-labelledby="pm-tab-pm-3c6fc231-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 @earendil-works/pi-durable @earendil-works/pi-ai</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="npm i agents@latest @earendil-works/pi-durable @earendil-works/pi-ai" 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-3c6fc231-yarn" aria-labelledby="pm-tab-pm-3c6fc231-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 @earendil-works/pi-durable @earendil-works/pi-ai</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="yarn add agents@latest @earendil-works/pi-durable @earendil-works/pi-ai" 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-3c6fc231-pnpm" aria-labelledby="pm-tab-pm-3c6fc231-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 @earendil-works/pi-durable @earendil-works/pi-ai</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="pnpm add agents@latest @earendil-works/pi-durable @earendil-works/pi-ai" 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-3c6fc231-bun" aria-labelledby="pm-tab-pm-3c6fc231-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 @earendil-works/pi-durable @earendil-works/pi-ai</span></code></pre><button type="button" data-nb-pm-copy data-nb-command="bun add agents@latest @earendil-works/pi-durable @earendil-works/pi-ai" 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>Both Pi packages are optional peer dependencies of <code>agents</code>, so you only install them if you use the harness.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="use-it-in-an-agent">Use it in an Agent</h4><a class="anchor-link" href="#use-it-in-an-agent"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <p>Creating a Pi agent requires configuring the Pi <code>Harness</code> with a model, skills, and tools, then registering the <code>PiHarness</code> with the <code>Agent</code> class.</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"> { Agent } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createModels } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-ai/models"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createRegistry, Harness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-durable"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { PiHarness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/pi"</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/pi-ai"</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"> Agent</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"> registry</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createRegistry</span><span class="nb-shiki-140thh">();</span></span> <span class="line"></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"> PiHarness</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> harness</span><span class="nb-shiki-140thh">: ({ </span><span class="nb-shiki-1jdh33">storage</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">context</span><span class="nb-shiki-140thh"> }) </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> models</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createModels</span><span class="nb-shiki-140thh">();</span></span> <span class="line"><span class="nb-shiki-140thh"> models.</span><span class="nb-shiki-1t8gfj">setProvider</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ai.provider);</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> Harness.</span><span class="nb-shiki-1t8gfj">open</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, registry: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.registry },</span></span> <span class="line"><span class="nb-shiki-140thh"> context,</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 class="nb-shiki-140thh"> defaults: { 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"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe"> constructor</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">ctx</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-dzsirb"> super</span><span class="nb-shiki-140thh">(ctx, env);</span></span> <span class="line"><span class="nb-shiki-dzsirb"> this</span><span class="nb-shiki-140thh">.lifecycle.</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 class="nb-shiki-140thh"> }</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">text</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"> text;</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"> { Agent } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createModels } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-ai/models"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { createRegistry, Harness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-durable"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { PiHarness } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/pi"</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/pi-ai"</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"> Agent</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1t8gfj">Env</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"> registry</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createRegistry</span><span class="nb-shiki-140thh">();</span></span> <span class="line"></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"> PiHarness</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> harness</span><span class="nb-shiki-140thh">: ({ </span><span class="nb-shiki-1jdh33">storage</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">context</span><span class="nb-shiki-140thh"> }) </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> models</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1t8gfj"> createModels</span><span class="nb-shiki-140thh">();</span></span> <span class="line"><span class="nb-shiki-140thh"> models.</span><span class="nb-shiki-1t8gfj">setProvider</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ai.provider);</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> Harness.</span><span class="nb-shiki-1t8gfj">open</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, registry: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.registry },</span></span> <span class="line"><span class="nb-shiki-140thh"> context,</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 class="nb-shiki-140thh"> defaults: { 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"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe"> constructor</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">ctx</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> DurableObjectState</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1jdh33">env</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> Env</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-dzsirb"> super</span><span class="nb-shiki-140thh">(ctx, env);</span></span> <span class="line"><span class="nb-shiki-dzsirb"> this</span><span class="nb-shiki-140thh">.lifecycle.</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 class="nb-shiki-140thh"> }</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">text</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"> text;</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 <code>agents/models/pi-ai</code> entry point supports AI Gateway and Workers AI models, so you can get started with Cloudflare models right away or use your existing Pi AI provider.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="add-tools-with-extensions">Add tools with extensions</h4><a class="anchor-link" href="#add-tools-with-extensions"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <p>Both tools and system prompt sections are provided to the Pi <code>Harness</code> via extensions.</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"> { Type } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-ai"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { skills } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/pi"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> WordCount</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> Type.</span><span class="nb-shiki-1t8gfj">Object</span><span class="nb-shiki-140thh">({ text: Type.</span><span class="nb-shiki-1t8gfj">String</span><span class="nb-shiki-140thh">() });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> wordCount</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-140thh"> name: </span><span class="nb-shiki-mdbnqw">"word_count"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> description: </span><span class="nb-shiki-mdbnqw">"Count the words in a text."</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> parameters: WordCount,</span></span> <span class="line"><span class="nb-shiki-140thh"> replay: </span><span class="nb-shiki-mdbnqw">"safe"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> execute</span><span class="nb-shiki-140thh">({ </span><span class="nb-shiki-1jdh33">text</span><span class="nb-shiki-140thh"> }) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> words</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> text.</span><span class="nb-shiki-1t8gfj">split</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">/</span><span class="nb-shiki-dzsirb">\s</span><span class="nb-shiki-1itgoe">+</span><span class="nb-shiki-mdbnqw">/</span><span class="nb-shiki-140thh">).</span><span class="nb-shiki-1t8gfj">filter</span><span class="nb-shiki-140thh">(Boolean).</span><span class="nb-shiki-dzsirb">length</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> { content: [{ type: </span><span class="nb-shiki-mdbnqw">"text"</span><span class="nb-shiki-140thh">, text: </span><span class="nb-shiki-1t8gfj">String</span><span class="nb-shiki-140thh">(words) }] };</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-21nrsd">// In the harness factory, before Harness.open():</span></span> <span class="line"><span class="nb-shiki-140thh">registry.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> name: </span><span class="nb-shiki-mdbnqw">"editor"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> sections: [</span></span> <span class="line"><span class="nb-shiki-140thh"> { key: </span><span class="nb-shiki-mdbnqw">"preamble"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1t8gfj">render</span><span class="nb-shiki-140thh">: () </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-mdbnqw"> "You are an editor."</span><span class="nb-shiki-140thh">, tag: </span><span class="nb-shiki-dzsirb">false</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"> tools: [wordCount],</span></span> <span class="line"><span class="nb-shiki-140thh">});</span></span> <span class="line"><span class="nb-shiki-140thh">registry.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1itgoe">await</span><span class="nb-shiki-1t8gfj"> skills</span><span class="nb-shiki-140thh">(sources));</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"> { Type } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-ai"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-1itgoe"> type</span><span class="nb-shiki-140thh"> { ToolRegistration } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "@earendil-works/pi-durable"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { skills } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/harness/pi"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> WordCount</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> Type.</span><span class="nb-shiki-1t8gfj">Object</span><span class="nb-shiki-140thh">({ text: Type.</span><span class="nb-shiki-1t8gfj">String</span><span class="nb-shiki-140thh">() });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> wordCount</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> ToolRegistration</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1itgoe">typeof</span><span class="nb-shiki-140thh"> WordCount> </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-140thh"> name: </span><span class="nb-shiki-mdbnqw">"word_count"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> description: </span><span class="nb-shiki-mdbnqw">"Count the words in a text."</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> parameters: WordCount,</span></span> <span class="line"><span class="nb-shiki-140thh"> replay: </span><span class="nb-shiki-mdbnqw">"safe"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-1itgoe"> async</span><span class="nb-shiki-1t8gfj"> execute</span><span class="nb-shiki-140thh">({ </span><span class="nb-shiki-1jdh33">text</span><span class="nb-shiki-140thh"> }) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> words</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-140thh"> text.</span><span class="nb-shiki-1t8gfj">split</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">/</span><span class="nb-shiki-dzsirb">\s</span><span class="nb-shiki-1itgoe">+</span><span class="nb-shiki-mdbnqw">/</span><span class="nb-shiki-140thh">).</span><span class="nb-shiki-1t8gfj">filter</span><span class="nb-shiki-140thh">(Boolean).</span><span class="nb-shiki-dzsirb">length</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe"> return</span><span class="nb-shiki-140thh"> { content: [{ type: </span><span class="nb-shiki-mdbnqw">"text"</span><span class="nb-shiki-140thh">, text: </span><span class="nb-shiki-1t8gfj">String</span><span class="nb-shiki-140thh">(words) }] };</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-21nrsd">// In the harness factory, before Harness.open():</span></span> <span class="line"><span class="nb-shiki-140thh">registry.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> name: </span><span class="nb-shiki-mdbnqw">"editor"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> sections: [</span></span> <span class="line"><span class="nb-shiki-140thh"> { key: </span><span class="nb-shiki-mdbnqw">"preamble"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-1t8gfj">render</span><span class="nb-shiki-140thh">: () </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-mdbnqw"> "You are an editor."</span><span class="nb-shiki-140thh">, tag: </span><span class="nb-shiki-dzsirb">false</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"> tools: [wordCount],</span></span> <span class="line"><span class="nb-shiki-140thh">});</span></span> <span class="line"><span class="nb-shiki-140thh">registry.</span><span class="nb-shiki-1t8gfj">install</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1itgoe">await</span><span class="nb-shiki-1t8gfj"> skills</span><span class="nb-shiki-140thh">(sources));</span></span></code></pre></figure></div></div></div></div> <p>For more information on creating and configuring extensions, refer to <a href="https://developers.cloudflare.com/agents/harnesses/pi/extensions/">Extensions</a>.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="learn-more">Learn more</h4><a class="anchor-link" href="#learn-more"><span aria-hidden="true" class="anchor-icon"><svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentcolor" d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 0 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 1 0-1.42-1.42Zm8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 0 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 1 0 1.42 1.42l3.88-3.89a4.49 4.49 0 0 0 0-6.33ZM8.83 15.17a1 1 0 0 0 1.1.22 1 1 0 0 0 .32-.22l4.92-4.92a1 1 0 0 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42Z"></path></svg></span></a></div> <ul> <li><a href="https://developers.cloudflare.com/agents/harnesses/pi/">Pi harness documentation</a></li> <li><a href="https://developers.cloudflare.com/agents/harnesses/pi/extensions/">Pi harness extensions</a></li> <li><a href="https://developers.cloudflare.com/agents/models/pi-ai/">pi-ai model provider</a></li> <li><a href="https://github.com/cloudflare/agents/tree/main/examples/next/harnesses/pi" target="_blank" rel="noopener">Pi harness example<span class="external-link"> ↗︎</span></a>, with WebSockets, a browser UI, and a <code>@cloudflare/computer</code> Workspace for the model's tools</li> <li><a href="https://github.com/cloudflare/agents/blob/main/docs/agents/lifecycle.md" target="_blank" rel="noopener">Lifecycle<span class="external-link"> ↗︎</span></a></li> <li><a href="https://earendil.com/posts/pi-durable/" target="_blank" rel="noopener">Pi Durable announcement<span class="external-link"> ↗︎</span></a> from Earendil</li> </ul>
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.