Agents - Agents SDK now supports Pi 1.5 with fewer storage writes and lower memory use
- Announced
- Tags
- Agents
- Severity
- info, set by
reef/rss-rule-v1 - Source
- https://developers.cloudflare.com/changelog/post/2026-11-03-pi-harness-pi-1-5/
<p>Agents SDK v0.33.0 upgrades <a href="https://developers.cloudflare.com/agents/harnesses/pi/"><code>PiHarness</code></a> to <a href="https://github.com/earendil-works/pi/blob/v1.5.0/packages/durable/CHANGELOG.md#150---2026-11-02" target="_blank" rel="noopener">Pi 1.5<span class="external-link"> ↗︎</span></a>. The release reduces storage transactions while streaming, improves throughput across many sessions, and reduces memory use when streaming large tool calls.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="performance-improvements">Performance improvements</h4><a class="anchor-link" href="#performance-improvements"><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><strong>Far fewer storage writes while streaming.</strong> Pi stores streamed answers and tool output in batches, within a second of each update, instead of on every update. Over SQLite, this cuts storage transactions by about 27x for long answers and 5.7x for turns with parallel tools, and CPU by about a quarter.</li> <li><strong>Higher throughput across many sessions.</strong> Pi's scheduler no longer rechecks every conversation on each commit. In a SQLite benchmark with 2,048 sessions, one Pi harness went from 88 to 459 agent runs per second.</li> <li><strong>Less memory on large answers.</strong> Streaming a 500 KB tool call used to take about 20 seconds of CPU and a 100 MB heap. Pi now appends new text instead of copying it on every update.</li> </ul> <p>Streaming updates remain visible immediately, but are persisted in batches. With the default settings, a crash can lose up to about one second of streamed progress. Refer to <a href="https://developers.cloudflare.com/agents/harnesses/pi/#recovery">Recovery</a> to configure this interval.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="session-and-tool-updates">Session and tool updates</h4><a class="anchor-link" href="#session-and-tool-updates"><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><strong>A view of each session.</strong> <a href="https://developers.cloudflare.com/agents/harnesses/pi/#watch-sessions-from-clients"><code>session.watch()</code></a> replaces <code>session.events()</code>. It returns the newest transcript entries and the session's live state, such as the answer being streamed, running tools, and why the last run ended without an answer.</li> <li><strong>Continue without adding a message.</strong> The new <code>session.continue()</code> API starts a new run using the existing transcript, for example after a model error or when a run reaches its turn limit.</li> <li><strong>Turn limit.</strong> <code>defaults.maxTurns</code> caps the tool rounds a run can take in new sessions.</li> <li><strong>Tasks that keep crashing end.</strong> Pi now ends a task cut off by its restart limit instead of parking it. <code>retry()</code> and the <code>parked</code> status are removed.</li> <li><strong>Browser in Pi's code mode.</strong> Scripts in <a href="https://developers.cloudflare.com/agents/tools/browser/#use-it-in-pis-code-mode">Pi's code mode</a> can call <code>browserTool</code> and pass its screenshots to <code>image()</code>. <code>browserTool</code> also stops when the harness aborts its call.</li> </ul> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="continue-an-unanswered-conversation">Continue an unanswered conversation</h4><a class="anchor-link" href="#continue-an-unanswered-conversation"><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>For an existing session and submission <code>operationId</code>, check the result before offering a continuation. For example, after resolving a model error:</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">const</span><span class="nb-shiki-dzsirb"> result</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">wait</span><span class="nb-shiki-140thh">(operationId);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">if</span><span class="nb-shiki-140thh"> (result.status </span><span class="nb-shiki-1itgoe">===</span><span class="nb-shiki-mdbnqw"> "unanswered"</span><span class="nb-shiki-1itgoe"> &&</span><span class="nb-shiki-140thh"> result.reason </span><span class="nb-shiki-1itgoe">===</span><span class="nb-shiki-mdbnqw"> "model_error"</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> receipt</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">continue</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> operationId: </span><span class="nb-shiki-mdbnqw">${</span><span class="nb-shiki-140thh">operationId</span><span class="nb-shiki-mdbnqw">}:continue</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-1itgoe"> const</span><span class="nb-shiki-dzsirb"> continued</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">wait</span><span class="nb-shiki-140thh">(receipt.operationId);</span></span> <span class="line"><span class="nb-shiki-140thh"> console.</span><span class="nb-shiki-1t8gfj">log</span><span class="nb-shiki-140thh">(continued.status, continued.text);</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">const</span><span class="nb-shiki-dzsirb"> result</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">wait</span><span class="nb-shiki-140thh">(operationId);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">if</span><span class="nb-shiki-140thh"> (result.status </span><span class="nb-shiki-1itgoe">===</span><span class="nb-shiki-mdbnqw"> "unanswered"</span><span class="nb-shiki-1itgoe"> &&</span><span class="nb-shiki-140thh"> result.reason </span><span class="nb-shiki-1itgoe">===</span><span class="nb-shiki-mdbnqw"> "model_error"</span><span class="nb-shiki-140thh">) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> const</span><span class="nb-shiki-dzsirb"> receipt</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">continue</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> operationId: </span><span class="nb-shiki-mdbnqw">${</span><span class="nb-shiki-140thh">operationId</span><span class="nb-shiki-mdbnqw">}:continue</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-1itgoe"> const</span><span class="nb-shiki-dzsirb"> continued</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> session.</span><span class="nb-shiki-1t8gfj">wait</span><span class="nb-shiki-140thh">(receipt.operationId);</span></span> <span class="line"><span class="nb-shiki-140thh"> console.</span><span class="nb-shiki-1t8gfj">log</span><span class="nb-shiki-140thh">(continued.status, continued.text);</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>This starts a new run without appending a user message. The session must be idle. If the transcript already ends in an answer, the operation returns <code>unanswered</code> with reason <code>nothing_to_answer</code>. Refer to <a href="https://developers.cloudflare.com/agents/harnesses/pi/#work-with-sessions">Work with sessions</a>.</p> <div tabindex="-1" class="heading-wrapper level-h4"><h4 id="upgrade">Upgrade</h4><a class="anchor-link" href="#upgrade"><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>Once a conversation runs on Pi 1.5, Pi 1.4 cannot read it. After upgrading, roll forward to fix deployment issues rather than rolling back to Pi 1.4.</p> <p>Update callers of <code>session.events()</code> to use <code>session.watch()</code>, and remove uses of <code>retry()</code> and the <code>parked</code> status. Refer to the <a href="https://github.com/earendil-works/pi/blob/v1.5.0/packages/durable/CHANGELOG.md#150---2026-11-02" target="_blank" rel="noopener">Pi Durable 1.5.0 changelog<span class="external-link"> ↗︎</span></a> for the full list of breaking changes.</p> <p>The <a href="https://github.com/cloudflare/agents/blob/main/packages/agents/CHANGELOG.md#0330" target="_blank" rel="noopener">Agents SDK v0.33.0 changelog<span class="external-link"> ↗︎</span></a> has step-by-step upgrade instructions. Point your coding agent at them and upgrade today:</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="Upgrade my Pi harness agent to Agents SDK v0.33.0 and Pi 1.5 by following the upgrade steps at https://github.com/cloudflare/agents/blob/main/packages/agents/CHANGELOG.md#0330. Refer to https://developers.cloudflare.com/agents/harnesses/pi/ for the current PiHarness API." data-tooltip="Upgrade to Pi 1.5"><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>
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.