Sign inConnect your agent
infochanged

Agents - New persistent browser tool in the Agents SDK, with tabs and logins that last between turns

Announced
Tags
Agents
Severity
info, set by reef/rss-rule-v1
Source
https://developers.cloudflare.com/changelog/post/2026-10-13-persistent-browser/

<p>The <a href="https://developers.cloudflare.com/agents/">Cloudflare Agents SDK</a> now provides a <code>browserTool</code> that gives your agent a <a href="https://developers.cloudflare.com/browser-run/">Browser Run</a> browser it can return to on later turns. Your agent can open a website, inspect a page, and come back to it with its tabs, cookies, and login session intact while the browser session remains alive.</p> <p>When you give <code>browserTool</code> to your agent, the model writes code that drives the browser through the <a href="https://developers.cloudflare.com/browser-run/cdp/">Chrome DevTools Protocol (CDP)</a>. Screenshots return as images that an image-capable model can inspect and your UI can display.</p> <p>To use <code>browserTool</code>, make sure you have <a href="https://github.com/cloudflare/agents/releases/tag/agents%400.28.0" target="_blank" rel="noopener">Agents SDK v0.28.0<span class="external-link"> ↗︎</span></a> or greater installed. Create a <code>Browser</code>, register it with your object's <a href="https://developers.cloudflare.com/agents/runtime/lifecycle/">Lifecycle</a>, and add the tool to a <a href="https://developers.cloudflare.com/agents/harnesses/pi/">Pi Durable</a> <a href="https://developers.cloudflare.com/agents/harnesses/pi/extensions/">extension registry</a> before opening the harness:</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"> { Browser, browserRun } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/browser"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { browserTool } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/browser/pi"</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"> MyAgent</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-21nrsd"> // ...</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1jdh33"> browser</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Browser</span><span class="nb-shiki-140thh">({ provider: </span><span class="nb-shiki-1t8gfj">browserRun</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">BROWSER</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-1itgoe">async</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-dzsirb"> this</span><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">"browser"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> tools: [</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> browserTool</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> ctx: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ctx,</span></span> <span class="line"><span class="nb-shiki-140thh"> browser: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.browser,</span></span> <span class="line"><span class="nb-shiki-140thh"> loader: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">LOADER</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 class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // ...</span></span> <span class="line"></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"> });</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">.browser).</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></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"> { Browser, browserRun } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/browser"</span><span class="nb-shiki-140thh">;</span></span> <span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { browserTool } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "agents/browser/pi"</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"> MyAgent</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-21nrsd"> // ...</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1jdh33"> browser</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Browser</span><span class="nb-shiki-140thh">({ provider: </span><span class="nb-shiki-1t8gfj">browserRun</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">BROWSER</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-1itgoe">async</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">=&gt;</span><span class="nb-shiki-140thh"> {</span></span> <span class="line"><span class="nb-shiki-dzsirb"> this</span><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">"browser"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> tools: [</span></span> <span class="line"><span class="nb-shiki-1t8gfj"> browserTool</span><span class="nb-shiki-140thh">({</span></span> <span class="line"><span class="nb-shiki-140thh"> ctx: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.ctx,</span></span> <span class="line"><span class="nb-shiki-140thh"> browser: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.browser,</span></span> <span class="line"><span class="nb-shiki-140thh"> loader: </span><span class="nb-shiki-dzsirb">this</span><span class="nb-shiki-140thh">.env.</span><span class="nb-shiki-dzsirb">LOADER</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 class="nb-shiki-140thh"> });</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-21nrsd"> // ...</span></span> <span class="line"></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"> });</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">.browser).</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></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>Each Pi conversation gets its own active tab by default. Cookies and logins remain shared within the browser.</p> <p>The browser stays alive between turns, including when the Durable Object hibernates. Its default idle timeout is 10 minutes. If the session expires or crashes, the tool creates a fresh browser and reports <code>restarted: true</code>. The old tabs and login state are gone.</p> <p>You can also use the persistent browser with the AI SDK and TanStack AI adapters, or connect another harness through the public Browser and CDP APIs.</p> <p>Refer to <a href="https://developers.cloudflare.com/agents/tools/browser/#return-to-the-same-browser">persistent browser tools</a> for the complete Pi Durable example, required bindings, and behavior when a tool call is interrupted.</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.