<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Workers on RockB</title><link>https://baeseokjae.github.io/tags/workers/</link><description>Recent content in Workers on RockB</description><image><title>RockB</title><url>https://baeseokjae.github.io/images/og-default.png</url><link>https://baeseokjae.github.io/images/og-default.png</link></image><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 03 May 2026 00:06:10 +0000</lastBuildDate><atom:link href="https://baeseokjae.github.io/tags/workers/index.xml" rel="self" type="application/rss+xml"/><item><title>Cloudflare Project Think Guide 2026: Build Long-Running AI Agents with Durable Execution</title><link>https://baeseokjae.github.io/posts/cloudflare-project-think-ai-agents-guide/</link><pubDate>Sun, 03 May 2026 00:06:10 +0000</pubDate><guid>https://baeseokjae.github.io/posts/cloudflare-project-think-ai-agents-guide/</guid><description>Cloudflare Project Think을 이용해 내구성 있는 장기 실행 AI 에이전트를 구축하는 완전 가이드.</description><content:encoded><![CDATA[<p>Cloudflare Project Think은 서버리스 인프라 위에서 다단계 추론을 수행하는 AI 에이전트를 구축하기 위한 새로운 기반 클래스(base class)와 런타임 프리미티브 세트입니다. Fibers, Facets, Sessions, Dynamic Workers 네 가지 핵심 개념을 결합해 에이전트가 플랫폼 재시작 후에도 상태를 유지하고, 비용 효율적으로 대기하며, 필요할 때 코드를 직접 생성·실행할 수 있습니다.</p>
<h2 id="what-is-cloudflare-project-think">What is Cloudflare Project Think?</h2>
<p>Cloudflare Project Think은 2026년 4월 Agents Week에 공개된, AI 에이전트를 위한 내구성 있는 실행 환경입니다. 기존 서버리스 함수가 요청 하나에 응답하고 상태를 버리는 방식과 달리, Think 기반 에이전트는 Durable Object 위에서 동작하여 명령 포인터(instruction pointer)를 SQLite에 체크포인트로 저장합니다. 이 덕분에 GPT-o3나 Claude Opus처럼 수 분이 걸리는 추론 모델도 Workers 환경에서 중단 없이 실행됩니다. Cloudflare Agents Week 기간 중 Workers AI는 2,410억 개의 토큰을 처리했고, AI Gateway를 통해 2,000만 건의 요청이 라우팅되었습니다. Project Think는 현재 프리뷰 상태이며 API는 피드백에 따라 변경될 수 있습니다. 핵심 가치는 단순합니다: 에이전트 로직을 네트워크 프리미티브 수준으로 끌어내려, 프레임워크 코드에 의존하지 않고 프로덕션 수준의 내구성을 확보하는 것입니다. Project Think는 Fibers(내구성 실행), Facets(서브에이전트), Sessions(대화 트리), Dynamic Workers(샌드박스 코드 실행)라는 네 프리미티브로 구성됩니다. 이 구조는 에이전트가 플랫폼 재시작 후에도 상태를 유지하고, 사용자 없이도 스케줄에 따라 자율적으로 작업을 처리하며, LLM이 생성한 코드를 안전하게 실행하는 데 필요한 모든 기반을 제공합니다. 단일 Durable Object가 에이전트의 모든 상태를 소유하는 액터 모델 덕분에, 외부 데이터베이스 의존성 없이 에지 네트워크 300개 이상의 도시에서 일관된 성능을 보장합니다.</p>
<h3 id="why-stateless-request-response-falls-short-for-agents">Why Stateless Request-Response Falls Short for Agents</h3>
<p>전통적인 서버리스 에이전트는 요청마다 새로 시작해 외부 KV 스토리지에 상태를 저장합니다. AWS Bedrock AgentCore와 Google ADK가 이 모델을 따릅니다. 문제는 긴 추론 루프에서 발생합니다. 타임아웃, 네트워크 레이턴시, 직렬화 오버헤드가 누적되면서 복잡한 다단계 작업이 깨집니다. Think는 이 문제를 액터(actor) 모델로 해결합니다. 각 에이전트는 영구적인 Durable Object이고, 상태는 외부로 나가지 않습니다.</p>
<h2 id="core-primitives-fibers-facets-sessions-and-sandboxed-execution">Core Primitives: Fibers, Facets, Sessions, and Sandboxed Execution</h2>
<p>Project Think의 네 가지 핵심 프리미티브는 각각 에이전트 내구성, 병렬 서브에이전트, 대화 지속성, 안전한 코드 실행이라는 서로 다른 문제를 해결합니다. Fibers는 async/await 스타일로 작성된 긴 실행 흐름을 SQLite 체크포인트로 변환해 플랫폼 재시작 후에도 정확히 중단된 지점에서 재개합니다. Facets는 부모 Durable Object와 같은 노드에 배치(colocated)된 자식 Durable Objects로, RPC 레이턴시가 HTTP 왕복이 아닌 함수 호출 수준입니다. Sessions API는 대화를 <code>parent_id</code>로 연결된 관계형 트리로 저장해 브랜칭과 포크를 지원합니다. Dynamic Workers는 V8 아이솔레이트 기반 샌드박스로, 에이전트가 생성한 코드를 외부 접근 없이 실행합니다. 이 네 프리미티브가 결합되면 에이전트는 수면(sleep) → 작업(work) → 수면 사이클을 플랫폼 관여 없이 반복할 수 있습니다. 전통적인 서버리스 에이전트 프레임워크에서 내구성, 서브에이전트 통신, 대화 저장, 코드 실행은 각각 다른 서드파티 서비스에 아웃소싱되었습니다. Project Think는 이 네 가지를 하나의 Durable Object 런타임 안에 통합해 외부 의존성 없이 에이전트가 동작하도록 설계합니다. 이는 레이턴시와 운영 복잡도를 동시에 낮추는 아키텍처 결정으로, Agents Week 2026에서 Cloudflare가 &ldquo;에이전트 인프라를 프레임워크 코드에서 네트워크 프리미티브로&rdquo; 이동시킨다고 발표한 비전의 핵심입니다.</p>
<h3 id="fibers-durable-execution-under-the-hood">Fibers: Durable Execution Under the Hood</h3>
<p>Fiber는 Think의 핵심 내구성 메커니즘입니다. <code>runFiber()</code> 함수를 호출하면 런타임은 해당 async 함수의 실행 상태를 SQLite에 직렬화합니다. 중간에 Workers 인스턴스가 재시작되거나 요금제 한도로 인한 일시 정지가 발생해도, Fiber는 마지막 체크포인트에서 재개됩니다. 아래는 기본 패턴입니다:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">ThinkAgent</span> } <span style="color:#66d9ef">from</span> <span style="color:#e6db74">&#34;@cloudflare/think&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ResearchAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">run</span>(<span style="color:#a6e22e">topic</span>: <span style="color:#66d9ef">string</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">outline</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;outline&#34;</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">ai</span>.<span style="color:#a6e22e">run</span>(<span style="color:#e6db74">&#34;@cf/meta/llama-3.3-70b-instruct&#34;</span>, {
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">messages</span><span style="color:#f92672">:</span> [{ <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;user&#34;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`Outline: </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">topic</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span> }],
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>      );
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">draft</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;draft&#34;</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">ai</span>.<span style="color:#a6e22e">run</span>(<span style="color:#e6db74">&#34;@cf/meta/llama-3.3-70b-instruct&#34;</span>, {
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">messages</span><span style="color:#f92672">:</span> [{ <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;user&#34;</span>, <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`Write: </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">outline</span>.<span style="color:#a6e22e">response</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span> }],
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>      );
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">draft</span>.<span style="color:#a6e22e">response</span>;
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>step()</code> 호출은 자동으로 멱등성(idempotency)을 보장합니다. 같은 step ID가 이미 완료된 상태라면 캐시된 결과를 반환합니다.</p>
<h3 id="facets-colocated-sub-agents-with-rpc-speed">Facets: Colocated Sub-Agents with RPC Speed</h3>
<p>Facets는 부모 에이전트가 필요할 때 생성하는 자식 Durable Objects입니다. 핵심 장점은 배치 위치입니다. 부모와 같은 PoP에서 실행되므로 Facet 호출은 HTTP 왕복 없이 프로세스 내 RPC로 처리됩니다. 이 레이턴시 특성 덕분에 병렬 서브에이전트가 현실적인 옵션이 됩니다. Facet은 <code>createFacet()</code> API로 생성하고, 부모의 바인딩을 상속받거나 별도로 구성할 수 있습니다.</p>
<h2 id="getting-started-with-the-think-base-class-cloudflarethink">Getting Started with the Think Base Class (@cloudflare/think)</h2>
<p><code>@cloudflare/think</code>는 Durable Object를 상속한 opinionated base class로, Fiber, Facets, Sessions, Dynamic Workers에 대한 고수준 API를 제공합니다. 2026년 4월 기준 npm 프리뷰 패키지로 배포 중이며, 공식 <code>cloudflare/agents</code> GitHub 저장소에는 30개 이상의 자급자족(self-contained) 데모 예제가 포함되어 있습니다. 시작하려면 Workers Paid 플랜($5/월 최소)이 필요하며, 이 플랜에는 Durable Objects, Workers, KV, Hyperdrive가 포함됩니다. 설치는 <code>npm install @cloudflare/think</code>로 패키지를 추가하고, <code>wrangler.toml</code>에 <code>new_sqlite_classes</code>로 Durable Object 바인딩을 설정하는 두 단계로 이루어집니다. SQLite 기반 Durable Objects는 2026년 1월부터 스토리지 요금이 청구되므로, <code>wrangler.toml</code> migrations 섹션에 <code>new_sqlite_classes</code>를 정확히 설정하는 것이 중요합니다. 첫 에이전트를 실행하기까지 실제 코드 줄 수는 약 30줄이며, <code>ThinkAgent</code>를 상속해 <code>runFiber()</code> 안에 로직을 작성하면 내구성, 체크포인트, 재개 기능이 자동으로 활성화됩니다. Wrangler CLI 4.x 이상에서는 <code>wrangler dev --remote</code> 옵션으로 로컬에서도 실제 Durable Object 환경을 시뮬레이션할 수 있어 프로덕션 배포 전 검증이 용이합니다. 프리뷰 단계이므로 프로덕션 크리티컬 워크로드 적용 전 API 변경 공지를 주시해야 합니다.</p>
<h3 id="installation-and-wranglertoml-setup">Installation and wrangler.toml Setup</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>npm install @cloudflare/think
</span></span></code></pre></div><p><code>wrangler.toml</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;my-think-agent&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span> = <span style="color:#e6db74">&#34;src/index.ts&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">compatibility_date</span> = <span style="color:#e6db74">&#34;2026-04-01&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[[<span style="color:#a6e22e">durable_objects</span>.<span style="color:#a6e22e">bindings</span>]]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;MY_AGENT&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">class_name</span> = <span style="color:#e6db74">&#34;MyAgent&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[[<span style="color:#a6e22e">migrations</span>]]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">tag</span> = <span style="color:#e6db74">&#34;v1&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">new_sqlite_classes</span> = [<span style="color:#e6db74">&#34;MyAgent&#34;</span>]
</span></span></code></pre></div><p><code>new_sqlite_classes</code>는 SQLite 기반 Durable Object임을 나타내는 필수 설정입니다. SQLite 기반 Durable Objects의 스토리지 요금은 2026년 1월부터 청구 활성화됐습니다.</p>
<h3 id="your-first-think-agent-step-by-step">Your First Think Agent: Step-by-Step</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">ThinkAgent</span> } <span style="color:#66d9ef">from</span> <span style="color:#e6db74">&#34;@cloudflare/think&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Env</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">MY_AGENT</span>: <span style="color:#66d9ef">DurableObjectNamespace</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">AI</span>: <span style="color:#66d9ef">Ai</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span>&lt;<span style="color:#f92672">Env</span>&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>: <span style="color:#66d9ef">Request</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">Response</span>&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> { <span style="color:#a6e22e">searchParams</span> } <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">task</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">searchParams</span>.<span style="color:#66d9ef">get</span>(<span style="color:#e6db74">&#34;task&#34;</span>) <span style="color:#f92672">??</span> <span style="color:#e6db74">&#34;Hello!&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;main&#34;</span>, <span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">resp</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;@cf/meta/llama-3.3-70b-instruct&#34;</span>,
</span></span><span style="display:flex;"><span>          { <span style="color:#a6e22e">messages</span><span style="color:#f92672">:</span> [{ <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;user&#34;</span>, <span style="color:#a6e22e">content</span>: <span style="color:#66d9ef">task</span> }] }
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">resp</span>.<span style="color:#a6e22e">response</span>;
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">Response</span>.<span style="color:#a6e22e">json</span>({ <span style="color:#a6e22e">result</span> });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">default</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>: <span style="color:#66d9ef">Request</span>, <span style="color:#a6e22e">env</span>: <span style="color:#66d9ef">Env</span>)<span style="color:#f92672">:</span> <span style="color:#a6e22e">Promise</span>&lt;<span style="color:#f92672">Response</span>&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">id</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">MY_AGENT</span>.<span style="color:#a6e22e">idFromName</span>(<span style="color:#e6db74">&#34;default&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">stub</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">MY_AGENT</span>.<span style="color:#66d9ef">get</span>(<span style="color:#a6e22e">id</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">stub</span>.<span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p><code>wrangler dev</code>로 로컬 테스트 후 <code>wrangler deploy</code>로 배포하면 에이전트가 Cloudflare 글로벌 네트워크(300개 이상의 도시)에 자동 배포됩니다.</p>
<h2 id="the-execution-ladder-progressive-security-for-ai-generated-code">The Execution Ladder: Progressive Security for AI-Generated Code</h2>
<p>실행 사다리(Execution Ladder)는 에이전트가 생성한 코드를 신뢰 수준에 따라 단계적으로 실행하는 보안 모델로, Cloudflare가 Agents Week 2026에서 발표한 핵심 보안 아키텍처입니다. Tier 0, 1, 2로 구분되며, 각 단계는 명시적으로 부여된 역량만 허용하는 최소 권한 원칙을 따릅니다. Tier 0은 에이전트 자체 Workspace와 SQLite로, 외부 네트워크 없이 로컬 계산만 허용합니다. Tier 1은 Dynamic Worker로 실행하되 네트워크 없음(<code>globalOutbound: null</code>)으로 순수 계산 작업에 사용됩니다. Tier 2는 npm 접근과 번들링이 추가된 Dynamic Worker로, <code>worker-bundler</code>가 런타임에 npm 레지스트리에서 패키지를 가져와 esbuild로 번들링합니다. Dynamic Workers는 전통적인 컨테이너 대비 약 100배 빠르고 최대 100배 더 메모리 효율적입니다. 에이전트는 작업 요구사항에 따라 자동으로 적절한 Tier를 선택하거나, <code>ExtensionManager</code>를 통해 명시적으로 Tier를 지정할 수 있습니다. 이 설계는 LLM이 생성한 임의의 코드가 우발적으로 외부 시스템에 접근하거나 인프라를 손상시키는 리스크를 구조적으로 차단합니다. 가장 강력한 Tier 2 권한은 명시적 바인딩 설정 없이는 활성화되지 않으며, 이는 기업 보안 팀이 에이전트 코드 실행을 감사하기 쉽게 만드는 설계 결정입니다.</p>
<h3 id="dynamic-workers-v8-isolates-for-agent-generated-code">Dynamic Workers: V8 Isolates for Agent-Generated Code</h3>
<p>Dynamic Worker는 에이전트가 생성한 임의의 JavaScript/TypeScript 코드를 안전하게 실행하는 V8 아이솔레이트입니다. 각 Dynamic Worker는 거의 아무런 권한 없이 시작합니다(<code>globalOutbound: null</code>). 필요한 역량은 바인딩을 통해 명시적으로 부여됩니다. 이 최소 권한 설계는 LLM이 생성한 코드가 우발적으로 외부 시스템에 접근하는 것을 방지합니다. Tier 2에서는 <code>worker-bundler</code>가 런타임에 npm 패키지를 가져와 번들링하므로, 에이전트는 사전 설치된 라이브러리 없이도 새로운 도구를 즉석에서 사용할 수 있습니다.</p>
<h2 id="building-modular-agents-with-facets-sub-agents">Building Modular Agents with Facets (Sub-Agents)</h2>
<p>Facets는 Project Think의 멀티에이전트 아키텍처 핵심으로, 부모 Durable Object와 동일한 Cloudflare PoP에 colocated된 자식 Durable Objects입니다. 기존 HTTP 기반 서브에이전트와 달리 Facets의 RPC 레이턴시는 함수 호출 수준(마이크로초)이며, InfoQ 분석에 따르면 이는 HTTP 왕복의 수십~수백 배 빠른 통신 속도입니다. 단일 거대 에이전트 대신, 각각 전문 역량을 가진 여러 Facet을 조합해 복잡한 작업을 병렬로 처리할 수 있습니다. 예를 들어 리서치 에이전트는 웹 검색 Facet, 요약 Facet, 사실 검증 Facet을 동시에 생성해 <code>Promise.all()</code>로 병렬 실행하면 전체 작업 시간이 직렬 실행 대비 극적으로 단축됩니다. Facet은 <code>createFacet()</code> API로 생성하며, 부모의 바인딩을 상속하거나 별도로 구성할 수 있습니다. Facet 수명은 부모가 관리하며, 작업 완료 후 명시적으로 종료해 Durable Object 비용을 최소화할 수 있습니다. 각 Facet은 독립적인 SQLite 공간에 중간 결과를 저장할 수 있어, 부모 에이전트가 모든 결과를 메모리에 유지할 필요 없이 필요할 때 각 Facet에서 결과를 가져옵니다. 이 패턴은 마이크로서비스 아키텍처의 모듈성을 유지하면서 네트워크 오버헤드를 제거하는 절충점입니다.</p>
<h3 id="designing-a-multi-facet-research-pipeline">Designing a Multi-Facet Research Pipeline</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">import</span> { <span style="color:#a6e22e">ThinkAgent</span> } <span style="color:#66d9ef">from</span> <span style="color:#e6db74">&#34;@cloudflare/think&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">OrchestratorAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span>&lt;<span style="color:#f92672">Env</span>&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">research</span>(<span style="color:#a6e22e">topic</span>: <span style="color:#66d9ef">string</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// Facets를 병렬로 생성
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> [<span style="color:#a6e22e">searchFacet</span>, <span style="color:#a6e22e">analysisFacet</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">Promise</span>.<span style="color:#a6e22e">all</span>([
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">createFacet</span>(<span style="color:#e6db74">&#34;search-agent&#34;</span>, <span style="color:#a6e22e">SearchFacet</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">createFacet</span>(<span style="color:#e6db74">&#34;analysis-agent&#34;</span>, <span style="color:#a6e22e">AnalysisFacet</span>),
</span></span><span style="display:flex;"><span>      ]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 검색 실행
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">rawResults</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;search&#34;</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">searchFacet</span>.<span style="color:#a6e22e">search</span>(<span style="color:#a6e22e">topic</span>)
</span></span><span style="display:flex;"><span>      );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 분석 실행
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">analysis</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;analyze&#34;</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">analysisFacet</span>.<span style="color:#a6e22e">analyze</span>(<span style="color:#a6e22e">rawResults</span>)
</span></span><span style="display:flex;"><span>      );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">analysis</span>;
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Facets는 부모와 독립적으로 상태를 유지하므로, 각자의 SQLite 공간에 중간 결과를 저장할 수 있습니다.</p>
<h2 id="persistent-sessions-tree-structured-conversations-and-branching">Persistent Sessions: Tree-Structured Conversations and Branching</h2>
<p>Sessions API는 AI 에이전트의 대화 히스토리를 플랫 리스트가 아닌 <code>parent_id</code>로 연결된 관계형 트리로 관리하는 Project Think의 대화 지속성 레이어입니다. 전통적인 챗 기록 저장 방식이 단순 배열이라면, Sessions는 각 메시지를 노드로, 응답을 자식 노드로 구성하는 트리 구조를 채택합니다. 이 설계 덕분에 대화 브랜칭과 병렬 추론 경로가 자연스럽게 표현됩니다. 예를 들어 에이전트가 동일한 맥락에서 &ldquo;자세한 설명&rdquo; 버전과 &ldquo;간결한 요약&rdquo; 버전을 동시에 생성할 때, Sessions API는 두 브랜치를 동일한 트리 구조 안에 저장하고 나중에 병합하거나 개별적으로 추적할 수 있습니다. Sessions는 Durable Object의 colocated SQLite에 저장되므로 외부 데이터베이스 없이 완전한 대화 지속성을 제공합니다. <code>this.session.addMessage()</code>, <code>this.session.getHistory()</code>, <code>this.session.branch()</code> 같은 고수준 API가 SQL 쿼리를 추상화하며, 긴 리서치 세션이나 멀티-라운드 문서 편집 작업처럼 수십 번의 교환이 필요한 에이전트 워크플로우에서도 맥락 손실 없이 상태를 유지합니다. SQLite 트리 구조 덕분에 특정 브랜치만 잘라내거나, 이전 상태로 롤백하거나, 두 브랜치의 결과를 비교하는 작업이 단순 SQL 쿼리 수준으로 가능합니다.</p>
<h3 id="branching-conversations-for-parallel-reasoning">Branching Conversations for Parallel Reasoning</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DialogAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span>&lt;<span style="color:#f92672">Env</span>&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">handleTurn</span>(<span style="color:#a6e22e">userMessage</span>: <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">sessionId</span>: <span style="color:#66d9ef">string</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 현재 세션에 사용자 메시지 추가
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">msgId</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">session</span>.<span style="color:#a6e22e">addMessage</span>(<span style="color:#a6e22e">sessionId</span>, {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;user&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">content</span>: <span style="color:#66d9ef">userMessage</span>,
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 두 가지 응답 스타일을 병렬 브랜치로 생성
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> [<span style="color:#a6e22e">detailedBranch</span>, <span style="color:#a6e22e">conciseBranch</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">Promise</span>.<span style="color:#a6e22e">all</span>([
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">session</span>.<span style="color:#a6e22e">branch</span>(<span style="color:#a6e22e">msgId</span>, <span style="color:#e6db74">&#34;detailed&#34;</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">session</span>.<span style="color:#a6e22e">branch</span>(<span style="color:#a6e22e">msgId</span>, <span style="color:#e6db74">&#34;concise&#34;</span>),
</span></span><span style="display:flex;"><span>      ]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 각 브랜치에서 독립적으로 추론
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> [<span style="color:#a6e22e">detailed</span>, <span style="color:#a6e22e">concise</span>] <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">Promise</span>.<span style="color:#a6e22e">all</span>([
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">`detailed-</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">msgId</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">generateResponse</span>(<span style="color:#a6e22e">detailedBranch</span>, <span style="color:#e6db74">&#34;자세하게&#34;</span>)
</span></span><span style="display:flex;"><span>        ),
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">`concise-</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">msgId</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">generateResponse</span>(<span style="color:#a6e22e">conciseBranch</span>, <span style="color:#e6db74">&#34;간결하게&#34;</span>)
</span></span><span style="display:flex;"><span>        ),
</span></span><span style="display:flex;"><span>      ]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> { <span style="color:#a6e22e">detailed</span>, <span style="color:#a6e22e">concise</span> };
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="self-authored-extensions-agents-that-build-their-own-tools">Self-Authored Extensions: Agents That Build Their Own Tools</h2>
<p>Self-authored extensions는 Project Think의 <code>ExtensionManager</code>를 통해 에이전트가 런타임에 새로운 도구를 코드로 직접 생성하고, Dynamic Worker 샌드박스에 즉시 배포해 사용하는 기능입니다. 재배포 없이 에이전트가 스스로 역량을 확장한다는 점에서, 기존 함수 호출(function calling) 패러다임을 넘어선 새로운 에이전트 자율성 수준을 보여줍니다. 이 패턴은 사용 사례가 예측 불가능한 범용 에이전트에 특히 유용합니다. 예를 들어 사용자가 &ldquo;Stripe API에서 결제 데이터를 가져와 분석해줘&quot;라고 요청하면, 에이전트는 LLM을 통해 Stripe SDK를 임포트하는 코드를 생성하고, <code>worker-bundler</code>가 런타임에 npm에서 패키지를 번들링하고, Tier 2 Dynamic Worker에서 실행한 뒤 결과를 반환합니다. 이 전체 과정이 사전 정의된 도구 없이 이루어집니다. 보안은 실행 사다리의 Tier 시스템이 담당하며, 에이전트가 생성한 코드는 명시적으로 부여된 바인딩 외에 아무것도 접근할 수 없습니다. 생성된 도구는 같은 세션 내에서 캐시되어 동일 요청에 재사용되며, 세션 종료 시 자동으로 정리됩니다. Agents Week 2026에서 Cloudflare는 이 기능을 &ldquo;에이전트가 자신만의 운영 체제를 구축하는 것&quot;에 비유하며, 장기적으로 에이전트 생태계를 자가 발전시키는 메커니즘으로 설명했습니다.</p>
<h3 id="extensionmanager-in-practice">ExtensionManager in Practice</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AutoToolAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span>&lt;<span style="color:#f92672">Env</span>&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">executeWithDynamicTool</span>(<span style="color:#a6e22e">taskDescription</span>: <span style="color:#66d9ef">string</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// LLM에게 필요한 도구 코드 생성 요청
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">toolCode</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;generate-tool&#34;</span>, <span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">resp</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">env</span>.<span style="color:#a6e22e">AI</span>.<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#34;@cf/meta/llama-3.3-70b-instruct&#34;</span>,
</span></span><span style="display:flex;"><span>          {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">messages</span><span style="color:#f92672">:</span> [
</span></span><span style="display:flex;"><span>              {
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;system&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#34;Write a JavaScript function that accomplishes the task. Return only code.&#34;</span>,
</span></span><span style="display:flex;"><span>              },
</span></span><span style="display:flex;"><span>              { <span style="color:#a6e22e">role</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;user&#34;</span>, <span style="color:#a6e22e">content</span>: <span style="color:#66d9ef">taskDescription</span> },
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>          }
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">resp</span>.<span style="color:#a6e22e">response</span>;
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// ExtensionManager로 동적 도구 등록 및 실행 (Tier 1: 네트워크 없음)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;run-tool&#34;</span>, () <span style="color:#f92672">=&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">extensions</span>.<span style="color:#a6e22e">run</span>(<span style="color:#a6e22e">toolCode</span>, {
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">tier</span>: <span style="color:#66d9ef">1</span>, <span style="color:#75715e">// 네트워크 없는 순수 계산
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>          <span style="color:#a6e22e">timeout</span>: <span style="color:#66d9ef">30_000</span>,
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>      );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">result</span>;
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="project-think-vs-aws-bedrock-agentcore-vs-google-adk">Project Think vs AWS Bedrock AgentCore vs Google ADK</h2>
<p>Cloudflare Project Think, AWS Bedrock AgentCore, Google ADK는 AI 에이전트 인프라에 대해 근본적으로 다른 실행 철학을 가집니다. Cloudflare Project Think는 액터(actor) 모델을 채택해 에이전트 상태를 Durable Object의 로컬 SQLite에 보관하며, Durable Object가 에이전트 생명주기를 전적으로 소유합니다. InfoQ 분석에 따르면 이 모델은 &ldquo;stateless 오케스트레이션에서 내구성 있는 액터 기반 인프라로의 전환&quot;을 의미합니다. AWS Bedrock AgentCore는 요청-응답 모델로 상태를 외부 DynamoDB 또는 ElastiCache에 저장하며, 각 에이전트 단계가 Lambda 호출로 매핑됩니다. Google ADK는 Python/Java SDK로 에이전트를 정의하고 Vertex AI Pipelines 또는 Cloud Run에 배포합니다. Project Think의 핵심 차별점은 colocation입니다. 에이전트, 상태, 서브에이전트가 모두 같은 노드에 있어 외부 DB 왕복 레이턴시가 없습니다. AWS와 Google은 관리형 클라우드 인프라의 풍부한 에코시스템이 강점이지만, 에이전트 레이턴시와 외부 의존성은 비교적 높습니다. Cloudflare는 에지 배치와 내구성이 강점이나 2026년 4월 기준 프리뷰 단계이며, GA 전 API 변경이 있을 수 있습니다.</p>
<h3 id="side-by-side-comparison-table">Side-by-Side Comparison Table</h3>
<table>
  <thead>
      <tr>
          <th>Feature</th>
          <th>Cloudflare Project Think</th>
          <th>AWS Bedrock AgentCore</th>
          <th>Google ADK</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>실행 모델</strong></td>
          <td>Actor (Durable Object)</td>
          <td>Request-Response (Lambda)</td>
          <td>Pipeline (Cloud Run)</td>
      </tr>
      <tr>
          <td><strong>상태 저장</strong></td>
          <td>로컬 SQLite</td>
          <td>외부 DynamoDB/ElastiCache</td>
          <td>외부 Cloud Spanner/Redis</td>
      </tr>
      <tr>
          <td><strong>서브에이전트</strong></td>
          <td>Facets (colocated RPC)</td>
          <td>Step Functions 오케스트레이션</td>
          <td>Sub-agents (HTTP)</td>
      </tr>
      <tr>
          <td><strong>코드 샌드박스</strong></td>
          <td>Dynamic Workers (V8)</td>
          <td>Lambda 레이어</td>
          <td>Cloud Run 컨테이너</td>
      </tr>
      <tr>
          <td><strong>배포 위치</strong></td>
          <td>300+ PoPs (에지)</td>
          <td>리전 기반</td>
          <td>리전 기반</td>
      </tr>
      <tr>
          <td><strong>대기 비용</strong></td>
          <td>하이버네이션 (무료 대기)</td>
          <td>Lambda 대기 과금</td>
          <td>Cloud Run 최소 인스턴스</td>
      </tr>
      <tr>
          <td><strong>현재 상태</strong></td>
          <td>프리뷰 (2026-04)</td>
          <td>GA</td>
          <td>GA</td>
      </tr>
      <tr>
          <td><strong>오픈소스 데모</strong></td>
          <td>30+ 예제</td>
          <td>제한적</td>
          <td>SDK 예제</td>
      </tr>
  </tbody>
</table>
<p>Project Think는 에지 레이턴시와 비용 효율이 중요한 글로벌 서비스에 유리하고, AWS는 기존 AWS 인프라와 통합이 필요한 엔터프라이즈에 적합하며, Google ADK는 Vertex AI 모델 에코시스템을 활용하는 팀에게 맞습니다.</p>
<h2 id="production-deployment-cost-scheduling-and-hibernation">Production Deployment: Cost, Scheduling, and Hibernation</h2>
<p>Cloudflare Project Think 기반 에이전트의 프로덕션 배포는 비용 모델, 스케줄링, 하이버네이션 세 가지 운영 요소를 이해하는 것에서 시작됩니다. Workers Paid 플랜은 월 $5 최소 요금으로 Durable Objects, Workers, KV, Hyperdrive를 포함하며, SQLite 기반 Durable Objects 스토리지 요금은 2026년 1월부터 활성화됐습니다. 장기 실행 에이전트의 비용 최적화 핵심은 하이버네이션(hibernation)입니다. Think 기반 에이전트는 작업이 없을 때 자동으로 하이버네이션 상태로 전환되고, HTTP 요청, Durable Object 알람, 크론 트리거 같은 이벤트가 발생하면 밀리초 단위로 재개됩니다. 하이버네이션 중에는 CPU 요금이 발생하지 않아, 24시간 대기하다 하루 한 번만 실행되는 에이전트의 비용이 극적으로 낮아집니다. 스케줄링은 지연 실행(<code>delay</code>), 특정 시간 실행(<code>at</code>), 크론 스케줄(<code>cron</code>) 세 가지 방식을 지원합니다. 에이전트는 사용자 없이도 스스로 깨어나 작업하고 다시 잠들 수 있으며, 이 자율 사이클이 Project Think가 &ldquo;장기 실행 AI 에이전트&quot;로 포지셔닝되는 핵심 근거입니다. 프로덕션 비용 예측을 위해 Cloudflare의 Durable Objects 요금 계산기를 사용하는 것을 권장합니다.</p>
<h3 id="scheduling-alarms-and-cron-triggers">Scheduling, Alarms, and Cron Triggers</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-typescript" data-lang="typescript"><span style="display:flex;"><span><span style="color:#66d9ef">export</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ScheduledAgent</span> <span style="color:#66d9ef">extends</span> <span style="color:#a6e22e">ThinkAgent</span>&lt;<span style="color:#f92672">Env</span>&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 크론으로 매일 오전 9시에 실행
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">scheduled</span>(<span style="color:#a6e22e">controller</span>: <span style="color:#66d9ef">ScheduledController</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;daily-report&#34;</span>, () <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">generateDailyReport</span>());
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 특정 작업을 지연 실행
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">scheduleLaterTask</span>(<span style="color:#a6e22e">delayMs</span>: <span style="color:#66d9ef">number</span>, <span style="color:#a6e22e">payload</span>: <span style="color:#66d9ef">unknown</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 지정 시간 후 알람 설정
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">alarm</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">storage</span>.<span style="color:#a6e22e">setAlarm</span>(Date.<span style="color:#a6e22e">now</span>() <span style="color:#f92672">+</span> <span style="color:#a6e22e">delayMs</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">`task-</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">alarm</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>, <span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// 알람이 울리면 실행
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">processPayload</span>(<span style="color:#a6e22e">payload</span>);
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">async</span> <span style="color:#a6e22e">alarm() {</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 알람 핸들러: Fiber 자동 재개
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">runFiber</span>(<span style="color:#66d9ef">async</span> () <span style="color:#f92672">=&gt;</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">step</span>(<span style="color:#e6db74">&#34;alarm-handler&#34;</span>, () <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">handleScheduledWork</span>());
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>wrangler.toml</code>에 크론 트리거를 추가합니다:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[<span style="color:#a6e22e">triggers</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">crons</span> = [<span style="color:#e6db74">&#34;0 9 * * *&#34;</span>]  <span style="color:#75715e"># 매일 오전 9시 UTC</span>
</span></span></code></pre></div><h3 id="cost-optimization-tips">Cost Optimization Tips</h3>
<ul>
<li><strong>하이버네이션 우선</strong>: 긴 대기 구간은 <code>sleep()</code>이나 알람으로 처리해 CPU 시간을 최소화</li>
<li><strong>SQLite 스토리지 관리</strong>: 불필요한 세션 히스토리는 주기적으로 정리해 스토리지 비용 절감</li>
<li><strong>Facets 수명 관리</strong>: 작업 완료 후 Facets를 명시적으로 종료해 불필요한 오브젝트 유지 방지</li>
<li><strong>step() 캐싱 활용</strong>: 동일 step ID는 재실행 시 캐시에서 반환되므로 재시도 비용 없음</li>
<li><strong>Tier 선택 최적화</strong>: 네트워크가 불필요한 작업은 Tier 1로 실행해 외부 의존성 제거</li>
</ul>
<h2 id="faq">FAQ</h2>
<p>Cloudflare Project Think와 장기 실행 AI 에이전트 구축에 대해 개발자들이 가장 자주 묻는 질문을 정리했습니다. Project Think는 2026년 4월 기준 프리뷰 단계로, 공식 문서(<code>developers.cloudflare.com/agents/api-reference/think/</code>)와 GitHub 저장소의 데모 예제가 가장 신뢰할 수 있는 최신 정보 소스입니다. Workers Paid 플랜 비용($5/월 최소), SQLite 스토리지 요금(2026년 1월 청구 활성화), Fibers와 알람의 차이, Facets RPC 성능 특성, 기존 Cloudflare Agents SDK와의 마이그레이션 경로 등 핵심 사항을 아래에서 다룹니다. 빠르게 변화하는 프리뷰 제품이므로 개발 시작 전 <code>@cloudflare/think</code> npm 패키지의 최신 버전과 변경 로그를 확인하는 것을 권장합니다. Cloudflare의 공식 <code>cloudflare/agents</code> GitHub 저장소에는 30개 이상의 실행 가능한 데모 예제가 있어 실제 패턴을 빠르게 학습할 수 있으며, 각 예제는 독립 실행이 가능한 완전한 Workers 프로젝트로 구성되어 있습니다. Agents Week 2026 기간 중 3,683명 이상의 Cloudflare 내부 사용자가 Workers AI에서 인퍼런스를 실행했으며, 이는 Project Think가 프리뷰임에도 실제 내부 워크로드에서 검증되고 있음을 보여줍니다.</p>
<h3 id="cloudflare-project-think은-정식-출시됐나요">Cloudflare Project Think은 정식 출시됐나요?</h3>
<p>2026년 4월 기준 프리뷰(preview) 상태입니다. <code>@cloudflare/think</code> npm 패키지는 사용 가능하지만, API가 변경될 수 있어 프로덕션 크리티컬 워크로드에 적용할 때는 API 변경 공지를 주시해야 합니다.</p>
<h3 id="project-think를-사용하려면-어떤-cloudflare-플랜이-필요한가요">Project Think를 사용하려면 어떤 Cloudflare 플랜이 필요한가요?</h3>
<p>Workers Paid 플랜($5/월 최소)이 필요합니다. 이 플랜은 Durable Objects 사용량을 포함합니다. SQLite 기반 Durable Objects는 2026년 1월부터 스토리지 요금이 활성화됐습니다.</p>
<h3 id="fibers와-일반-durable-objects-알람의-차이는-무엇인가요">Fibers와 일반 Durable Objects 알람의 차이는 무엇인가요?</h3>
<p>알람은 특정 시간에 핸들러를 호출하는 단순 스케줄러입니다. Fibers는 복잡한 다단계 비동기 흐름 전체를 체크포인트로 저장해, 플랫폼 재시작이나 타임아웃 후에도 정확히 중단된 지점에서 재개합니다. 알람은 Fibers 내에서 사용할 수 있습니다.</p>
<h3 id="facets와-별도-workers-서비스로-분리된-에이전트의-성능-차이는-얼마나-되나요">Facets와 별도 Workers 서비스로 분리된 에이전트의 성능 차이는 얼마나 되나요?</h3>
<p>Facets는 부모와 같은 PoP에 배치되어 RPC 레이턴시가 함수 호출 수준(마이크로초 단위)입니다. 별도 Workers 서비스 간 HTTP 호출은 수 밀리초에서 수십 밀리초가 소요됩니다. 다단계 오케스트레이션에서 이 차이는 누적되어 전체 레이턴시에 크게 영향을 미칩니다.</p>
<h3 id="project-think와-기존-cloudflare-agents-sdk는-어떻게-다른가요">Project Think와 기존 Cloudflare Agents SDK는 어떻게 다른가요?</h3>
<p>기존 Agents SDK는 에이전트 빌딩 블록을 제공하는 프레임워크 레이어입니다. Project Think는 이를 더 발전시켜 Fibers, Facets, Sessions, Dynamic Workers를 네트워크 프리미티브 수준으로 통합합니다. 기존 Agents SDK 코드는 Think로 점진적으로 마이그레이션할 수 있으며, Think는 기존 SDK보다 더 강한 내구성 보장을 제공합니다.</p>
]]></content:encoded></item></channel></rss>