<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://agentflow.10xscale.ai/blog</id>
    <title>AgentFlow Blog — Building Production AI Agents in Python</title>
    <updated>2026-05-04T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://agentflow.10xscale.ai/blog"/>
    <subtitle>Deep dives, patterns, and migration guides for building production AI agents with AgentFlow.</subtitle>
    <icon>https://agentflow.10xscale.ai/img/agentflow-mark.svg</icon>
    <entry>
        <title type="html"><![CDATA[AI Agents vs Workflows: When to Use Each (and How to Tell)]]></title>
        <id>https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows</id>
        <link href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows"/>
        <updated>2026-05-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical guide to choosing between AI agents and deterministic workflows. Decision tree, hybrid patterns, and Python code for each in 2026.]]></summary>
        <content type="html"><![CDATA[<p>"Should this be an agent or a workflow?" gets asked in every architecture review of an AI system. The answer is rarely binary. Most production systems are hybrids. But you should know which mode you are in for any given subsystem, because the operational cost is wildly different.</p>
<p>Here is the practical decision framework.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"AI Agents vs Workflows. When to Use Each (and How to Tell)","description":"A practical guide to choosing between AI agents and deterministic workflows. Decision tree, hybrid patterns, and Python code for each in 2026.","url":"https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows"},"datePublished":"2026-05-04","dateModified":"2026-05-04","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"ai agents vs workflows, agent architecture, workflow design","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-crisp-definitions">The crisp definitions<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#the-crisp-definitions" class="hash-link" aria-label="Direct link to The crisp definitions" title="Direct link to The crisp definitions" translate="no">​</a></h2>
<p><strong>Workflow:</strong> the LLM does not decide control flow. You wrote the steps; the model fills in language-shaped tasks at specific points.</p>
<p><strong>Agent:</strong> the LLM decides control flow. You give it tools and a goal; it picks the next action at each step.</p>
<p>A "graph with conditional edges" is a workflow if the conditions are deterministic Python; it is an agent if the conditions involve the model picking the next node.</p>
<p>This is a continuum, not a binary. Most systems are 80% workflow and 20% agent.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="workflow-code">Workflow code<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#workflow-code" class="hash-link" aria-label="Direct link to Workflow code" title="Direct link to Workflow code" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">summarize_call</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transcript</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">dict</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 1: extract entities (LLM)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    entities </span><span class="token operator">=</span><span class="token plain"> llm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">extract</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transcript</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> schema</span><span class="token operator">=</span><span class="token plain">EntitySchema</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 2: classify intent (LLM)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    intent </span><span class="token operator">=</span><span class="token plain"> llm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">classify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transcript</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> labels</span><span class="token operator">=</span><span class="token plain">INTENTS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 3: write summary (LLM)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    summary </span><span class="token operator">=</span><span class="token plain"> llm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">summarize</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transcript</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> max_words</span><span class="token operator">=</span><span class="token number">120</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 4: store (deterministic)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">write</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">call_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"entities"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> entities</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"intent"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> intent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"summary"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"entities"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> entities</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"intent"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> intent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"summary"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Three LLM calls, in a fixed order. The model never picks the next step.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="agent-code">Agent code<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#agent-code" class="hash-link" aria-label="Direct link to Agent code" title="Direct link to Agent code" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Help the user with their support request. "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Use lookup_order to find their order, refund_order to issue refunds, "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"or escalate_to_human if you cannot resolve it."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># The model decides which tools to call, in what order, and when to stop</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"My order #123 hasn't arrived."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"support-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The model picks: look up the order, check status, decide whether to refund or escalate, etc. <em>That decision</em> is what makes this an agent.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-workflows-win">When workflows win<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#when-workflows-win" class="hash-link" aria-label="Direct link to When workflows win" title="Direct link to When workflows win" translate="no">​</a></h2>
<p>Workflows are the right answer when:</p>
<ul>
<li class=""><strong>The steps are predictable.</strong> Most data pipelines, ETL with LLM enrichment, batch processing.</li>
<li class=""><strong>You need determinism.</strong> Compliance review, regulated outputs, anything where the path matters as much as the result.</li>
<li class=""><strong>Cost matters.</strong> Each LLM call is paid; a fixed pipeline pays only for what you need.</li>
<li class=""><strong>Latency matters.</strong> No "the model is thinking" loops. Steps run sequentially with predictable timings.</li>
<li class=""><strong>You need to test it.</strong> Workflows are easy to unit-test; agent loops are not.</li>
</ul>
<p>A workflow with three LLM calls is a far simpler operational target than an agent that <em>might</em> make three calls, or seven, or none.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-agents-win">When agents win<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#when-agents-win" class="hash-link" aria-label="Direct link to When agents win" title="Direct link to When agents win" translate="no">​</a></h2>
<p>Agents are the right answer when:</p>
<ul>
<li class=""><strong>The path depends on the input.</strong> Customer support: did the user ask for a refund or a status check?</li>
<li class=""><strong>You can't enumerate the steps in advance.</strong> Research tasks, debugging tasks, anything with branching.</li>
<li class=""><strong>The model needs to decide when to stop.</strong> Open-ended exploration with a clear goal.</li>
<li class=""><strong>Tool selection matters.</strong> When the right tool depends on what the user said, the model is the natural router.</li>
</ul>
<p>The killer feature of agents is <em>deciding when to stop</em>. Workflows always run to the end; agents can finish early.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hybrid-the-most-common-production-shape">Hybrid: the most common production shape<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#hybrid-the-most-common-production-shape" class="hash-link" aria-label="Direct link to Hybrid: the most common production shape" title="Direct link to Hybrid: the most common production shape" translate="no">​</a></h2>
<p>Most production systems are hybrids:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">[ Deterministic workflow ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Step 1: Extract entities</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Step 2: Classify intent</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Step 3: ──── Branch on intent ────</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    ├─→ [ Simple workflow: format response ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    └─→ [ Agent: handle complex cases ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                            └─ tool calls, loops, etc.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Step 4: Log result</span><br></span></code></pre></div></div>
<p>The deterministic shell handles the boring parts (extraction, logging, routing). The agent handles the parts where the model needs to decide.</p>
<p>Code shape:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">handle_request</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    intent </span><span class="token operator">=</span><span class="token plain"> llm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">classify</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> labels</span><span class="token operator">=</span><span class="token plain">INTENTS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> intent </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"simple_lookup"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> run_lookup_workflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> intent </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"complex_support"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> support_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> req</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">user_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>This is the right shape for a typical SaaS support system. 80% workflow (cheap, deterministic, fast), 20% agent (handles the long tail).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-decision-tree">A decision tree<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#a-decision-tree" class="hash-link" aria-label="Direct link to A decision tree" title="Direct link to A decision tree" translate="no">​</a></h2>
<p>For any subsystem in your architecture, ask:</p>
<ol>
<li class="">
<p><strong>Can I enumerate the steps in advance?</strong></p>
<ul>
<li class="">Yes → workflow</li>
<li class="">No → agent</li>
</ul>
</li>
<li class="">
<p><strong>Does the path depend on the input?</strong></p>
<ul>
<li class="">Yes → agent (or branching workflow)</li>
<li class="">No → workflow</li>
</ul>
</li>
<li class="">
<p><strong>Does the model need to decide when to stop?</strong></p>
<ul>
<li class="">Yes → agent</li>
<li class="">No → workflow</li>
</ul>
</li>
<li class="">
<p><strong>Does this need to be deterministic for compliance / testing?</strong></p>
<ul>
<li class="">Yes → workflow (even if the obvious shape is an agent)</li>
<li class="">No → either is fine</li>
</ul>
</li>
</ol>
<p>When in doubt, start with a workflow. It is easier to upgrade a workflow to an agent than to downgrade.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="operational-cost-differences">Operational cost differences<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#operational-cost-differences" class="hash-link" aria-label="Direct link to Operational cost differences" title="Direct link to Operational cost differences" translate="no">​</a></h2>
<table><thead><tr><th>Concern</th><th>Workflow</th><th>Agent</th></tr></thead><tbody><tr><td>Token cost per request</td><td>Predictable</td><td>Variable, can spike</td></tr><tr><td>Latency p95</td><td>Predictable</td><td>Long tail</td></tr><tr><td>Failure modes</td><td>Step N failed</td><td>Loop runaway, tool error, recursion limit</td></tr><tr><td>Testability</td><td>Each step in isolation</td><td>End-to-end only</td></tr><tr><td>Observability</td><td>One trace per step</td><td>Full graph trace</td></tr><tr><td>Recovery</td><td>Retry from failed step</td><td>Resume thread from checkpoint</td></tr></tbody></table>
<p>Agents pay an "intelligence tax". The freedom to decide costs you in token spend, latency variance, and operational complexity. Charge for that intelligence only when you need it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="same-primitive-different-uses">Same primitive, different uses<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#same-primitive-different-uses" class="hash-link" aria-label="Direct link to Same primitive, different uses" title="Direct link to Same primitive, different uses" translate="no">​</a></h2>
<p>A graph runtime like AgentFlow or LangGraph supports both. The runtime is the same; the wiring is different:</p>
<ul>
<li class=""><strong>Workflow:</strong> edges are deterministic, conditional functions are pure Python</li>
<li class=""><strong>Agent:</strong> at least one node is an <code>Agent</code> whose tool choice drives an edge</li>
</ul>
<p>You can mix them in one graph. A workflow that calls into a small agent for one branch, then resumes deterministic processing.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"EXTRACT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> extract_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">             </span><span class="token comment" style="color:rgb(98, 114, 164)"># workflow</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"CLASSIFY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> classify_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">           </span><span class="token comment" style="color:rgb(98, 114, 164)"># workflow</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"AGENT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> complex_support_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)"># agent</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> log_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">                     </span><span class="token comment" style="color:rgb(98, 114, 164)"># workflow</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"EXTRACT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"CLASSIFY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"CLASSIFY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">lambda</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"AGENT"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> s</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">intent </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"complex"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"AGENT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"AGENT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"AGENT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"LOG"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>This is the production shape for most non-trivial AI systems.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-mistakes">Common mistakes<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#common-mistakes" class="hash-link" aria-label="Direct link to Common mistakes" title="Direct link to Common mistakes" translate="no">​</a></h2>
<ol>
<li class=""><strong>Agent-everything.</strong> Wrapping a 3-step pipeline in an agent because "agents are cool." You pay 3× the tokens for the same outcome with worse predictability.</li>
<li class=""><strong>Workflow-everything.</strong> A long if-else chain trying to anticipate every case the model could handle in two tool calls. Use the agent.</li>
<li class=""><strong>No determinism boundary.</strong> When the model gets to call any tool any time, your audit log is unreadable. Define agent boundaries explicitly.</li>
<li class=""><strong>Skipping the workflow shell.</strong> A pure agent in production with no deterministic guardrails is a footgun. Wrap it.</li>
<li class=""><strong>Not setting <code>recursion_limit</code>.</strong> Agents loop. Always cap them.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/ai-agents-vs-workflows#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/state-graph">State graph concept</a>. Runtime shared by both shapes</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns">Multi-agent orchestration patterns</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis">ReAct agent with real APIs</a>. Pure agent example</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries">Production AI agents (observability + retries)</a></li>
</ul>
<p>If your system is mostly a workflow with one agent loop, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a>. The same runtime handles both, with the same primitives.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="agents" term="agents"/>
        <category label="workflows" term="workflows"/>
        <category label="architecture" term="architecture"/>
        <category label="decision-making" term="decision-making"/>
        <category label="python" term="python"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[From LangGraph to AgentFlow: A Complete Migration Walkthrough]]></title>
        <id>https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration</id>
        <link href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration"/>
        <updated>2026-04-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A step-by-step LangGraph to AgentFlow migration walkthrough. Graph state, nodes, edges, checkpointers, API serving, and the TypeScript client. With diff-style code.]]></summary>
        <content type="html"><![CDATA[<p>If you have a LangGraph agent in production and want to move to AgentFlow, this is the playbook. The graph mental model is the same, so the port is mostly mechanical. Most teams complete it in an afternoon.</p>
<p>We will walk a real, two-agent example end-to-end: imports, state, nodes, edges, checkpointing, API serving, and the TypeScript client.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"From LangGraph to AgentFlow. A Complete Migration Walkthrough","description":"A step-by-step LangGraph to AgentFlow migration walkthrough. Graph state, nodes, edges, checkpointers, API serving, and the TypeScript client. With diff-style code.","url":"https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration"},"datePublished":"2026-04-27","dateModified":"2026-04-27","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"langgraph migration, agentflow, port langgraph","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-changes-what-stays">What changes, what stays<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#what-changes-what-stays" class="hash-link" aria-label="Direct link to What changes, what stays" title="Direct link to What changes, what stays" translate="no">​</a></h2>
<table><thead><tr><th>Concept</th><th>LangGraph</th><th>AgentFlow</th></tr></thead><tbody><tr><td>Graph builder</td><td><code>StateGraph(MyState)</code></td><td><code>StateGraph(AgentState)</code></td></tr><tr><td>State</td><td><code>TypedDict</code> you define</td><td>Built-in <code>AgentState</code> (extensible)</td></tr><tr><td>Messages</td><td><code>langchain_core.messages.HumanMessage</code>, etc.</td><td><code>agentflow.core.state.Message</code></td></tr><tr><td>Nodes</td><td>Plain functions</td><td><code>Agent</code> / <code>ToolNode</code> / functions</td></tr><tr><td>Conditional edges</td><td><code>add_conditional_edges</code></td><td><code>add_conditional_edges</code> (same name)</td></tr><tr><td>Compile</td><td><code>workflow.compile(checkpointer=...)</code></td><td><code>graph.compile(checkpointer=...)</code></td></tr><tr><td>Memory saver</td><td><code>MemorySaver</code>, <code>PostgresSaver</code></td><td><code>InMemoryCheckpointer</code>, <code>PgCheckpointer</code></td></tr><tr><td>Invoke</td><td><code>app.invoke({"messages": [...]})</code></td><td><code>app.invoke({"messages": [...]}, config={"thread_id": ...})</code></td></tr><tr><td>API serving</td><td>LangGraph Platform / FastAPI</td><td><code>agentflow api</code> (built-in)</td></tr><tr><td>TS client</td><td>None first-party</td><td><code>@10xscale/agentflow-client</code></td></tr></tbody></table>
<p>The shape is identical. The names and types are different.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-example-react-agent--tool">The example: ReAct agent + tool<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#the-example-react-agent--tool" class="hash-link" aria-label="Direct link to The example: ReAct agent + tool" title="Direct link to The example: ReAct agent + tool" translate="no">​</a></h2>
<p>Our starting point. A LangGraph ReAct agent that calls a <code>get_weather</code> tool.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="before-langgraph">Before (LangGraph)<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#before-langgraph" class="hash-link" aria-label="Direct link to Before (LangGraph)" title="Direct link to Before (LangGraph)" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> langchain_core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">messages </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> HumanMessage</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> langchain_core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">tools </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> tool</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> langgraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> langgraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">prebuilt </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> create_react_agent</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> langgraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpoint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">memory </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> MemorySaver</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@tool</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get current weather for a city."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"It is sunny and 22°C in </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">memory </span><span class="token operator">=</span><span class="token plain"> MemorySaver</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> create_react_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"openai:gpt-4o-mini"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tools</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    checkpointer</span><span class="token operator">=</span><span class="token plain">memory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">HumanMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Weather in Tokyo?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"configurable"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"demo-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="after-agentflow">After (AgentFlow)<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#after-agentflow" class="hash-link" aria-label="Direct link to After (AgentFlow)" title="Direct link to After (AgentFlow)" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> InMemoryCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get current weather for a city."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"It is sunny and 22°C in </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tool_node </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># or "openai/gpt-4o-mini"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Helpful assistant."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tool_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    last </span><span class="token operator">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">getattr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tools_calls"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tool"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">memory </span><span class="token operator">=</span><span class="token plain"> InMemoryCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">checkpointer</span><span class="token operator">=</span><span class="token plain">memory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Weather in Tokyo?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"demo-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The notable differences:</p>
<ul>
<li class=""><strong>No <code>@tool</code> decorator.</strong> AgentFlow reads the type hints + docstring directly.</li>
<li class=""><strong>Explicit graph construction.</strong> LangGraph's <code>create_react_agent</code> hides the graph; AgentFlow shows it. Once you've built one, the boilerplate becomes a snippet.</li>
<li class=""><strong><code>Message.text_message(...)</code> instead of <code>HumanMessage(...)</code>.</strong></li>
<li class=""><strong><code>thread_id</code> at top level of config</strong>, not inside <code>configurable</code>.</li>
<li class=""><strong><code>message.text()</code> instead of <code>message.content</code>.</strong></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-by-step-migration-checklist">Step-by-step migration checklist<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#step-by-step-migration-checklist" class="hash-link" aria-label="Direct link to Step-by-step migration checklist" title="Direct link to Step-by-step migration checklist" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-replace-imports">1. Replace imports<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#1-replace-imports" class="hash-link" aria-label="Direct link to 1. Replace imports" title="Direct link to 1. Replace imports" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># - from langchain_core.messages import HumanMessage, AIMessage</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - from langgraph.graph import StateGraph, END</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - from langgraph.prebuilt import create_react_agent</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - from langgraph.checkpoint.memory import MemorySaver</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - from langgraph.checkpoint.postgres import PostgresSaver</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + from agentflow.core.graph import Agent, StateGraph, ToolNode</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + from agentflow.core.state import AgentState, Message</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + from agentflow.storage.checkpointer import InMemoryCheckpointer, PgCheckpointer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + from agentflow.utils import END</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-convert-tools">2. Convert tools<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#2-convert-tools" class="hash-link" aria-label="Direct link to 2. Convert tools" title="Direct link to 2. Convert tools" translate="no">​</a></h3>
<p>LangGraph <code>@tool</code> → plain function. The <code>@tool</code> decorator does mostly type extraction, which AgentFlow does automatically.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># - @tool</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - def get_weather(location: str) -&gt; str:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># -     """Get weather."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># -     return ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + def get_weather(location: str) -&gt; str:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     """Get weather."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     return ...</span><br></span></code></pre></div></div>
<p>Wrap them in <code>ToolNode([fn1, fn2, ...])</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-replace-create_react_agent-with-explicit-graph">3. Replace <code>create_react_agent</code> with explicit graph<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#3-replace-create_react_agent-with-explicit-graph" class="hash-link" aria-label="Direct link to 3-replace-create_react_agent-with-explicit-graph" title="Direct link to 3-replace-create_react_agent-with-explicit-graph" translate="no">​</a></h3>
<p>This is the biggest mechanical change. LangGraph's prebuilt hides the graph; AgentFlow asks you to define it. Use the snippet above as the template. It is the same for any ReAct agent.</p>
<p>If you have many ReAct agents, factor the graph construction into a helper:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">build_react_graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tool_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tool_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> _route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> g</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-convert-state-schema">4. Convert state schema<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#4-convert-state-schema" class="hash-link" aria-label="Direct link to 4. Convert state schema" title="Direct link to 4. Convert state schema" translate="no">​</a></h3>
<p>If you used a custom <code>TypedDict</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># LangGraph</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">TypedDict</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    messages</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Annotated</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token builtin" style="color:rgb(189, 147, 249)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">AnyMessage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> add_messages</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    user_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cart</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token builtin" style="color:rgb(189, 147, 249)">dict</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></span></code></pre></div></div>
<p>AgentFlow's <code>AgentState</code> already has <code>messages</code> and <code>context</code>. Add custom fields by subclassing:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">MyState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    user_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cart</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token builtin" style="color:rgb(189, 147, 249)">dict</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><br></span></code></pre></div></div>
<p>Pass <code>MyState</code> to <code>StateGraph(MyState)</code>. The runtime treats your fields as state slots.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-convert-checkpointer">5. Convert checkpointer<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#5-convert-checkpointer" class="hash-link" aria-label="Direct link to 5. Convert checkpointer" title="Direct link to 5. Convert checkpointer" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># - memory = MemorySaver()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + memory = InMemoryCheckpointer()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - with PostgresSaver.from_conn_string("postgresql://...") as cp:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># -     app = workflow.compile(checkpointer=cp)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + cp = PgCheckpointer(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     db_url="postgresql+asyncpg://user:password@localhost/agentflow",</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     redis_url="redis://localhost:6379/0",</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + )</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + app = graph.compile(checkpointer=cp)</span><br></span></code></pre></div></div>
<p><code>PgCheckpointer</code> requires both Postgres and Redis. Redis is for hot-path access; if you do not have one yet, run <code>redis:7-alpine</code> in Docker. See <a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/checkpointing">production checkpointing</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-update-invoke-calls">6. Update invoke calls<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#6-update-invoke-calls" class="hash-link" aria-label="Direct link to 6. Update invoke calls" title="Direct link to 6. Update invoke calls" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># - app.invoke(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># -     {"messages": [HumanMessage("hi")]},</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># -     config={"configurable": {"thread_id": "u1"}},</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># - )</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + app.invoke(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     {"messages": [Message.text_message("hi")]},</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># +     config={"thread_id": "u1", "recursion_limit": 25},</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + )</span><br></span></code></pre></div></div>
<p><code>recursion_limit</code> lives on the invoke config in AgentFlow. Set it; LangGraph's default is also bounded but AgentFlow asks you to be explicit.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-update-reading-state">7. Update reading state<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#7-update-reading-state" class="hash-link" aria-label="Direct link to 7. Update reading state" title="Direct link to 7. Update reading state" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># - response = result["messages"][-1].content</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># + response = result["messages"][-1].text()</span><br></span></code></pre></div></div>
<p><code>Message.text()</code> returns plain text. For multimodal messages, use <code>.parts</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="8-drop-your-custom-fastapi-server">8. Drop your custom FastAPI server<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#8-drop-your-custom-fastapi-server" class="hash-link" aria-label="Direct link to 8. Drop your custom FastAPI server" title="Direct link to 8. Drop your custom FastAPI server" translate="no">​</a></h3>
<p>If you were running a hand-rolled FastAPI service to expose LangGraph over HTTP:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow api </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--host</span><span class="token plain"> </span><span class="token number">0.0</span><span class="token plain">.0.0 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--port</span><span class="token plain"> </span><span class="token number">8000</span><br></span></code></pre></div></div>
<p><code>agentflow.json</code>:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"agent"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"graph.react:app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>You now have <code>POST /v1/graph/invoke</code>, <code>POST /v1/graph/stream</code>, and <code>GET /v1/graph/threads/{id}</code>. The hand-rolled FastAPI usually deletes 100–300 lines.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="9-replace-your-typescript-fetcher">9. Replace your TypeScript fetcher<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#9-replace-your-typescript-fetcher" class="hash-link" aria-label="Direct link to 9. Replace your TypeScript fetcher" title="Direct link to 9. Replace your TypeScript fetcher" translate="no">​</a></h3>
<p>If you wrote a custom fetch + SSE parser to call LangGraph from a frontend:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// - const response = await fetch("/api/agent", { method: "POST", body: JSON.stringify(...) });</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// - // ... custom SSE parsing ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// + import {AgentFlowClient, Message} from "@10xscale/agentflow-client";</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// + const client = new AgentFlowClient({baseUrl: "/api"});</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// + const result = await client.invoke([Message.text_message(text)], {config: {thread_id}});</span><br></span></code></pre></div></div>
<p>The typed client handles SSE, reconnection, and types.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multi-agent-migrations">Multi-agent migrations<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#multi-agent-migrations" class="hash-link" aria-label="Direct link to Multi-agent migrations" title="Direct link to Multi-agent migrations" translate="no">​</a></h2>
<p>For LangGraph multi-agent workflows (router → specialists, supervisors, handoffs), the migration follows the same pattern:</p>
<ul>
<li class="">LangGraph <code>Command</code> for handoffs → AgentFlow <code>create_handoff_tool</code></li>
<li class="">LangGraph supervisor pattern → AgentFlow router node + handoff tools</li>
</ul>
<p>See the <a class="" href="https://agentflow.10xscale.ai/docs/how-to/python/handoff-between-agents">handoff tutorial</a> for the full pattern. The <a class="" href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns">multi-agent orchestration post</a> covers when each shape is the right call.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-keep">What you keep<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#what-you-keep" class="hash-link" aria-label="Direct link to What you keep" title="Direct link to What you keep" translate="no">​</a></h2>
<p>You do not have to rewrite:</p>
<ul>
<li class=""><strong>Tool implementations.</strong> Plain Python functions move over as-is.</li>
<li class=""><strong>External integrations.</strong> Vector stores, databases, custom retrievers. All unchanged.</li>
<li class=""><strong>System prompts.</strong> Copy them across.</li>
<li class=""><strong>Evals and tests.</strong> Most of them only care about the input/output of the agent, which stays the same.</li>
</ul>
<p>What changes is the orchestration layer in the middle.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="after-the-migration">After the migration<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#after-the-migration" class="hash-link" aria-label="Direct link to After the migration" title="Direct link to After the migration" translate="no">​</a></h2>
<p>Once the port is done, you usually want to:</p>
<ol>
<li class=""><strong>Add streaming</strong>. Use <code>app.stream()</code> / <code>app.astream()</code> and the SSE endpoint</li>
<li class=""><strong>Move to <code>PgCheckpointer</code></strong>. Production durability</li>
<li class=""><strong>Add the TypeScript client</strong>. Kill the hand-rolled fetcher</li>
<li class=""><strong>Set <code>recursion_limit</code></strong>. Explicitly cap loops</li>
<li class=""><strong>Add OpenTelemetry traces</strong>. See <a class="" href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries">production observability</a></li>
</ol>
<p>These are all optional but each saves real time downstream.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-migration-gotchas">Common migration gotchas<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#common-migration-gotchas" class="hash-link" aria-label="Direct link to Common migration gotchas" title="Direct link to Common migration gotchas" translate="no">​</a></h2>
<ol>
<li class=""><strong>Forgetting <code>recursion_limit</code>.</strong> LangGraph's default is 25; AgentFlow asks you to set it. If your agent loops, this is the first place to check.</li>
<li class=""><strong><code>message.content</code> → <code>message.text()</code>.</strong> Easy to miss in tests.</li>
<li class=""><strong><code>configurable</code> config key.</strong> AgentFlow uses top-level <code>config</code>, not nested <code>configurable</code>. Update everywhere.</li>
<li class=""><strong>Custom state schema.</strong> If you used <code>Annotated</code> reducers (e.g., <code>add_messages</code>), AgentFlow handles the messages reducer for you. Custom reducers go on subclassed state fields.</li>
<li class=""><strong>Tool docstrings.</strong> AgentFlow reads them as the tool description for the model. Make sure they are accurate.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-langgraph">AgentFlow vs LangGraph</a>. Head-to-head</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/state-graph">State graph concept</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-memory">Add memory</a>. Checkpointer setup</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/python/handoff-between-agents">Handoff between agents</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns">Multi-agent orchestration patterns</a></li>
</ul>
<p>If you want to compare the runtime first, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a> and reproduce your LangGraph agent in 30 minutes.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="langgraph" term="langgraph"/>
        <category label="migration" term="migration"/>
        <category label="agentflow" term="agentflow"/>
        <category label="python" term="python"/>
        <category label="walkthrough" term="walkthrough"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Deploy an AI Agent to Production: Docker, AWS, and the Boring Bits]]></title>
        <id>https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws</id>
        <link href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws"/>
        <updated>2026-04-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical Docker + AWS deployment guide for a Python AI agent. Image build, ECS Fargate, secrets, autoscaling, and the boring ops you actually need.]]></summary>
        <content type="html"><![CDATA[<p>A working agent on your laptop is not a deployed agent. The gap is mostly boring: a Dockerfile, secrets, a database, autoscaling, observability. Done well, it is one afternoon. Done sloppily, it is a series of 3am pages.</p>
<p>Here is the path from compiled graph to production on AWS. Docker image, ECS Fargate, RDS, secrets, scaling.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Deploy an AI Agent to Production. Docker, AWS, and the Boring Bits","description":"A practical Docker + AWS deployment guide for a Python AI agent. Image build, ECS Fargate, secrets, autoscaling, and the boring ops you actually need.","url":"https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws"},"datePublished":"2026-04-20","dateModified":"2026-04-20","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"deploy ai agent, docker, aws, ecs, production","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-shape-of-a-production-deployment">The shape of a production deployment<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#the-shape-of-a-production-deployment" class="hash-link" aria-label="Direct link to The shape of a production deployment" title="Direct link to The shape of a production deployment" translate="no">​</a></h2>
<p>For a Python agent service on AWS, the minimum viable architecture is:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ALB → ECS Fargate (your agent) → RDS Postgres (checkpointer)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                              → ElastiCache Redis (hot path)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                              → Secrets Manager (API keys)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                              → CloudWatch (logs)</span><br></span></code></pre></div></div>
<p>Each box is one or two days of work. The agent itself is the small part.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-dockerfile">Step 1: Dockerfile<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-1-dockerfile" class="hash-link" aria-label="Direct link to Step 1: Dockerfile" title="Direct link to Step 1: Dockerfile" translate="no">​</a></h2>
<p>A small, reproducible image:</p>
<div class="language-dockerfile codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">FROM python:3.12-slim</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Reduce image size, avoid pyc files baked in by package install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ENV PYTHONDONTWRITEBYTECODE=1 \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    PYTHONUNBUFFERED=1 \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    PIP_NO_CACHE_DIR=1 \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    PIP_DISABLE_PIP_VERSION_CHECK=1</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">WORKDIR /app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Install system deps if you need them (e.g. for asyncpg)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    libpq-dev gcc \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    &amp;&amp; rm -rf /var/lib/apt/lists/*</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Install Python deps first for layer caching</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">COPY pyproject.toml uv.lock ./</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">RUN pip install uv &amp;&amp; uv pip install --system --no-cache-dir -e .</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Copy app code last</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">COPY . .</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># AgentFlow CLI</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">RUN pip install --no-cache-dir 10xscale-agentflow-cli</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">EXPOSE 8000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Use exec form so signals reach the process</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">CMD ["agentflow", "api", "--host", "0.0.0.0", "--port", "8000"]</span><br></span></code></pre></div></div>
<p>If you prefer to skip the Dockerfile, AgentFlow's CLI can scaffold one:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow generate-docker</span><br></span></code></pre></div></div>
<p>See <a class="" href="https://agentflow.10xscale.ai/docs/how-to/api-cli/generate-docker-files">Generate Docker files</a> for the generated content.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-local-docker-compose-for-development">Step 2: Local docker-compose for development<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-2-local-docker-compose-for-development" class="hash-link" aria-label="Direct link to Step 2: Local docker-compose for development" title="Direct link to Step 2: Local docker-compose for development" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"3.9"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">services</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">build</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> .</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"8000:8000"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">DATABASE_URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> postgresql+asyncpg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">//postgres</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">postgres@db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">5432/agentflow</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">REDIS_URL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">//redis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">6379/0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">OPENAI_API_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">OPENAI_API_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">GOOGLE_API_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">GOOGLE_API_KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">depends_on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> redis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> postgres</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">16</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">environment</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">POSTGRES_USER</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> postgres</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">POSTGRES_PASSWORD</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> postgres</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">POSTGRES_DB</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> agentflow</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"5432:5432"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> pgdata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">/var/lib/postgresql/data</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">redis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">image</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">7</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">ports</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"6379:6379"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">volumes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  pgdata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><br></span></code></pre></div></div>
<p>Run <code>docker compose up</code>, send a request to <code>localhost:8000</code>. If this works, ECS will work. Only the configuration changes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-build-and-push-to-ecr">Step 3: Build and push to ECR<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-3-build-and-push-to-ecr" class="hash-link" aria-label="Direct link to Step 3: Build and push to ECR" title="Direct link to Step 3: Build and push to ECR" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">aws ecr create-repository --repository-name agentflow-app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">aws ecr get-login-password </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--region</span><span class="token plain"> us-east-1 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token operator">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> login </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--username</span><span class="token plain"> AWS --password-stdin </span><span class="token operator">&lt;</span><span class="token plain">account</span><span class="token operator">&gt;</span><span class="token plain">.dkr.ecr.us-east-1.amazonaws.com</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> build </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> agentflow-app:latest </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> tag agentflow-app:latest </span><span class="token operator">&lt;</span><span class="token plain">account</span><span class="token operator">&gt;</span><span class="token plain">.dkr.ecr.us-east-1.amazonaws.com/agentflow-app:latest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">docker</span><span class="token plain"> push </span><span class="token operator">&lt;</span><span class="token plain">account</span><span class="token operator">&gt;</span><span class="token plain">.dkr.ecr.us-east-1.amazonaws.com/agentflow-app:latest</span><br></span></code></pre></div></div>
<p>For CI, use the official <code>aws-actions/amazon-ecr-login</code> GitHub Action.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-rds-postgres-for-the-checkpointer">Step 4: RDS Postgres for the checkpointer<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-4-rds-postgres-for-the-checkpointer" class="hash-link" aria-label="Direct link to Step 4: RDS Postgres for the checkpointer" title="Direct link to Step 4: RDS Postgres for the checkpointer" translate="no">​</a></h2>
<p>Create the smallest instance that fits your throughput. For a starting point: <code>db.t4g.medium</code>, single-AZ, 50 GB storage.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">aws rds create-db-instance </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --db-instance-identifier agentflow-prod </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --db-instance-class db.t4g.medium </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--engine</span><span class="token plain"> postgres </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --master-username agentflow </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --master-user-password </span><span class="token string" style="color:rgb(255, 121, 198)">'use-secrets-manager-instead'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --allocated-storage </span><span class="token number">50</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --vpc-security-group-ids sg-xxx </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --db-subnet-group-name your-private-subnet-group</span><br></span></code></pre></div></div>
<p>Connection string format: <code>postgresql+asyncpg://agentflow:&lt;password&gt;@&lt;host&gt;:5432/agentflow</code>. Pass via Secrets Manager (next step), not env vars in the task definition.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-5-elasticache-redis-for-hot-path-state">Step 5: ElastiCache Redis for hot-path state<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-5-elasticache-redis-for-hot-path-state" class="hash-link" aria-label="Direct link to Step 5: ElastiCache Redis for hot-path state" title="Direct link to Step 5: ElastiCache Redis for hot-path state" translate="no">​</a></h2>
<p><code>cache.t4g.small</code> works for most production loads. Single-shard, no clustering needed initially.</p>
<p>Connection string: <code>redis://&lt;host&gt;:6379/0</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-6-secrets-manager">Step 6: Secrets Manager<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-6-secrets-manager" class="hash-link" aria-label="Direct link to Step 6: Secrets Manager" title="Direct link to Step 6: Secrets Manager" translate="no">​</a></h2>
<p>Never put <code>OPENAI_API_KEY</code> in plaintext in your task definition. Create a secret per credential:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">aws secretsmanager create-secret </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--name</span><span class="token plain"> agentflow/prod/openai </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --secret-string </span><span class="token string" style="color:rgb(255, 121, 198)">'{"OPENAI_API_KEY":"sk-..."}'</span><br></span></code></pre></div></div>
<p>Reference it in the ECS task definition's <code>secrets</code> block, not <code>environment</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-7-ecs-fargate-task-definition">Step 7: ECS Fargate task definition<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-7-ecs-fargate-task-definition" class="hash-link" aria-label="Direct link to Step 7: ECS Fargate task definition" title="Direct link to Step 7: ECS Fargate task definition" translate="no">​</a></h2>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"family"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"agentflow-app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"networkMode"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"awsvpc"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"requiresCompatibilities"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"FARGATE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"cpu"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"1024"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"memory"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"2048"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"containerDefinitions"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"agent"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"image"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"&lt;account&gt;.dkr.ecr.us-east-1.amazonaws.com/agentflow-app:latest"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"portMappings"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"containerPort"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">8000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"protocol"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tcp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"environment"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"DATABASE_URL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"value"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"postgresql+asyncpg://agentflow:_/agentflow.cluster-xxx.us-east-1.rds.amazonaws.com:5432/agentflow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"REDIS_URL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"value"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"redis://agentflow.xxx.cache.amazonaws.com:6379/0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"secrets"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OPENAI_API_KEY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token property">"valueFrom"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"arn:aws:secretsmanager:...:secret:agentflow/prod/openai:OPENAI_API_KEY::"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"healthCheck"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"command"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"CMD-SHELL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"curl -f http://localhost:8000/health || exit 1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"interval"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">30</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"retries"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"startPeriod"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">30</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"logConfiguration"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"logDriver"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"awslogs"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token property">"options"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"awslogs-group"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/ecs/agentflow-app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"awslogs-region"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"us-east-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token property">"awslogs-stream-prefix"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"agent"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Notes:</p>
<ul>
<li class="">1 vCPU + 2 GB is plenty for an I/O-bound agent service. Add CPU only if you have CPU-bound tools.</li>
<li class="">Health checks hit <code>/health</code> (AgentFlow exposes this by default).</li>
<li class="">Logs flow to CloudWatch; route from there to your log platform.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-8-alb-and-ssl">Step 8: ALB and SSL<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-8-alb-and-ssl" class="hash-link" aria-label="Direct link to Step 8: ALB and SSL" title="Direct link to Step 8: ALB and SSL" translate="no">​</a></h2>
<p>Put the service behind an Application Load Balancer with HTTPS:</p>
<ul>
<li class="">Target group: HTTP 8000, health check on <code>/health</code></li>
<li class="">Listener: HTTPS 443 with an ACM certificate</li>
<li class="">Idle timeout: <strong>300 seconds</strong>. Important for SSE streams</li>
</ul>
<p>If your idle timeout is too low (default is 60s), long agent streams get cut. Tune it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-9-autoscaling">Step 9: Autoscaling<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-9-autoscaling" class="hash-link" aria-label="Direct link to Step 9: Autoscaling" title="Direct link to Step 9: Autoscaling" translate="no">​</a></h2>
<p>For an agent service, scale on CPU (less likely the bottleneck) or <strong>active connections per task</strong> (more likely). Define a target tracking policy:</p>
<ul>
<li class="">Target: 30 active connections per task</li>
<li class="">Min: 2 tasks (HA across AZs)</li>
<li class="">Max: 20 tasks</li>
</ul>
<p>LLM-bound services are usually I/O-bound. CPU autoscaling underestimates load. Connection-based scaling is closer to truth.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-10-observability">Step 10: Observability<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#step-10-observability" class="hash-link" aria-label="Direct link to Step 10: Observability" title="Direct link to Step 10: Observability" translate="no">​</a></h2>
<p>CloudWatch is the default; most teams ship logs onward to Datadog, Honeycomb, or self-hosted Loki. Either way:</p>
<ul>
<li class="">Subscribe the log group to your platform's ingestion</li>
<li class="">Add the OTEL collector as a sidecar if you want traces</li>
<li class="">Define alarms on:<!-- -->
<ul>
<li class="">Service <code>UnhealthyHostCount</code> &gt; 0 for 5 min</li>
<li class="">p95 latency &gt; 5 s for 5 min</li>
<li class="">Stream-error rate &gt; 5% for 5 min</li>
</ul>
</li>
</ul>
<p>The <a class="" href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries">production observability post</a> covers what to log and trace inside the agent.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cicd-with-github-actions">CI/CD with GitHub Actions<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#cicd-with-github-actions" class="hash-link" aria-label="Direct link to CI/CD with GitHub Actions" title="Direct link to CI/CD with GitHub Actions" translate="no">​</a></h2>
<p>A reasonable pipeline:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> deploy</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">branches</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">jobs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">build-and-deploy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">runs-on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">permissions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">id-token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> write</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">contents</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> read</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> actions/checkout@v4</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">actions/configure</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">credentials@v4</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">role-to-assume</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> arn</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">iam</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">&lt;account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">role/github</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">actions</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">deploy</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">aws-region</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> us</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">east</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token number">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">actions/amazon</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">ecr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">login@v2</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token scalar string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          docker build -t agentflow-app:${{ github.sha }} .</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          docker tag agentflow-app:${{ github.sha }} ${{ env.ECR_REGISTRY }}/agentflow-app:${{ github.sha }}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token scalar string" style="color:rgb(255, 121, 198)">          docker push ${{ env.ECR_REGISTRY }}/agentflow-app:${{ github.sha }}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">actions/amazon</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">ecs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">deploy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">definition@v2</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">service</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">cluster</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">prod</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token key atrule">task-definition</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./.aws/task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">def.json</span><br></span></code></pre></div></div>
<p>Use OIDC for credentials (the <code>id-token: write</code> block). Never long-lived AWS keys in GitHub.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-about-cloud-run--kubernetes">What about Cloud Run / Kubernetes?<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#what-about-cloud-run--kubernetes" class="hash-link" aria-label="Direct link to What about Cloud Run / Kubernetes?" title="Direct link to What about Cloud Run / Kubernetes?" translate="no">​</a></h2>
<p>The same architecture works on:</p>
<ul>
<li class=""><strong>Google Cloud Run</strong>. Replace ECS with Cloud Run, RDS with Cloud SQL, ElastiCache with Memorystore. Slightly simpler ops; same code.</li>
<li class=""><strong>GKE / EKS</strong>. Replace ECS task definition with a Deployment + Service. More flexible, more ops.</li>
<li class=""><strong>Fly.io / Render</strong>. Containers are containers. Mostly the same.</li>
</ul>
<p>Pick whichever your team already operates. The Python agent does not care.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cost-expectations-rough">Cost expectations (rough)<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#cost-expectations-rough" class="hash-link" aria-label="Direct link to Cost expectations (rough)" title="Direct link to Cost expectations (rough)" translate="no">​</a></h2>
<p>A small production agent service on AWS, moderate traffic:</p>
<table><thead><tr><th>Resource</th><th>Monthly</th></tr></thead><tbody><tr><td>ECS Fargate (2× 1 vCPU / 2 GB)</td><td>$40</td></tr><tr><td>RDS Postgres <code>t4g.medium</code></td><td>$60</td></tr><tr><td>ElastiCache Redis <code>t4g.small</code></td><td>$30</td></tr><tr><td>ALB</td><td>$20</td></tr><tr><td>CloudWatch logs / data transfer</td><td>$20</td></tr><tr><td><strong>Infra subtotal</strong></td><td><strong>~$170</strong></td></tr><tr><td>LLM provider tokens</td><td>varies (usually dominates)</td></tr></tbody></table>
<p>Most teams' bills are 10× the infra in token costs. Plan accordingly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-gotchas">Common gotchas<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#common-gotchas" class="hash-link" aria-label="Direct link to Common gotchas" title="Direct link to Common gotchas" translate="no">​</a></h2>
<ol>
<li class=""><strong>ALB idle timeout &lt; SSE stream length.</strong> Streams get cut mid-response. Bump to 300s.</li>
<li class=""><strong>Database connection pool too small.</strong> A <code>PgCheckpointer</code> writes per node; under load, sized it for <code>n_tasks × n_concurrent_streams × 2</code>.</li>
<li class=""><strong>Secrets in plaintext env vars.</strong> Use Secrets Manager and <code>secrets</code> blocks.</li>
<li class=""><strong>No health check.</strong> ECS happily routes traffic to dead pods. <code>/health</code> is one line of code.</li>
<li class=""><strong>Single-AZ RDS.</strong> Cheap until your AZ has an outage. For real production, multi-AZ.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/deploy-ai-agent-docker-aws#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/production-runtime">Production runtime concept</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/deployment">Deployment guide</a>. Full deploy walkthrough</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/api-cli/generate-docker-files">Generate Docker files</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries">Production observability + retries</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/auth-and-authorization">Auth and authorization</a></li>
</ul>
<p>For a working stack to start from, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a>. The same <code>agentflow api</code> server you run locally is what runs in your ECS task.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="deployment" term="deployment"/>
        <category label="docker" term="docker"/>
        <category label="aws" term="aws"/>
        <category label="ecs" term="ecs"/>
        <category label="production" term="production"/>
        <category label="devops" term="devops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Build a ReAct Agent That Calls Real APIs: End-to-End in Python]]></title>
        <id>https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis</id>
        <link href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis"/>
        <updated>2026-04-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical walkthrough of building a ReAct agent in Python that calls real external APIs. Tool design, error handling, retries, and structured outputs.]]></summary>
        <content type="html"><![CDATA[<p>The ReAct pattern (Reason → Act → Observe → loop) is the workhorse of modern agents. It is also where most "hello world" tutorials end and real engineering begins. What does the loop look like when the tools actually call external APIs? When the API rate-limits? When it returns malformed JSON?</p>
<p>Here is the end-to-end pattern, with the failure modes baked in.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Build a ReAct Agent That Calls Real APIs. End-to-End in Python","description":"A practical walkthrough of building a ReAct agent in Python that calls real external APIs. Tool design, error handling, retries, and structured outputs.","url":"https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis"},"datePublished":"2026-04-13","dateModified":"2026-04-13","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"react agent, tool calling, api integration, python","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-react-actually-is">What ReAct actually is<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#what-react-actually-is" class="hash-link" aria-label="Direct link to What ReAct actually is" title="Direct link to What ReAct actually is" translate="no">​</a></h2>
<p>ReAct is a loop:</p>
<ol>
<li class=""><strong>Reason</strong>. The model thinks about what to do</li>
<li class=""><strong>Act</strong>. The model picks a tool and calls it with arguments</li>
<li class=""><strong>Observe</strong>. The tool returns a result; the model reads it</li>
<li class=""><strong>Loop</strong>. Back to Reason, until the model produces a final answer</li>
</ol>
<p>In a graph runtime, this is two nodes (<code>MAIN</code> and <code>TOOL</code>) with a conditional edge between them.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-shape-of-a-real-tool">The shape of a real tool<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#the-shape-of-a-real-tool" class="hash-link" aria-label="Direct link to The shape of a real tool" title="Direct link to The shape of a real tool" translate="no">​</a></h2>
<p>Let's build a tool that hits a real API. The <a href="https://open-meteo.com/" target="_blank" rel="noopener noreferrer" class="">Open-Meteo</a> weather service (no auth required for testing).</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> httpx</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> dataclasses </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> dataclass</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@dataclass</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">WeatherResult</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    temperature_c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">float</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get current weather for a city. Returns a one-line summary."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 1 — geocode</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        geo </span><span class="token operator">=</span><span class="token plain"> httpx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"https://geocoding-api.open-meteo.com/v1/search"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"name"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"count"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            timeout</span><span class="token operator">=</span><span class="token number">5.0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">not</span><span class="token plain"> geo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"results"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Could not find a location named '</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'. Ask the user to clarify."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        latitude </span><span class="token operator">=</span><span class="token plain"> geo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"results"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"latitude"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        longitude </span><span class="token operator">=</span><span class="token plain"> geo</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"results"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"longitude"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)"># Step 2 — current weather</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        weather </span><span class="token operator">=</span><span class="token plain"> httpx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"https://api.open-meteo.com/v1/forecast"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            params</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"latitude"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> latitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"longitude"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> longitude</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"current_weather"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">True</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            timeout</span><span class="token operator">=</span><span class="token number">5.0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        cw </span><span class="token operator">=</span><span class="token plain"> weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"current_weather"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">cw</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'temperature'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">°C, wind </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">cw</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'windspeed'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)"> km/h."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">except</span><span class="token plain"> httpx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">TimeoutException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Weather API timed out for </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">. Tell the user to try again later."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">except</span><span class="token plain"> httpx</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">HTTPError </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Weather API error for </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">e</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">. Suggest a fallback or move on."</span><br></span></code></pre></div></div>
<p>Key choices:</p>
<ul>
<li class=""><strong>Plain Python function with type hints and a docstring.</strong> AgentFlow exposes this to the model automatically.</li>
<li class=""><strong>Returns a string, not a dict.</strong> The model reads strings best; structure goes in the wording, not the type.</li>
<li class=""><strong>Errors become results, not exceptions.</strong> The agent reads the error message and decides how to recover.</li>
<li class=""><strong>Timeouts are explicit.</strong> <code>5.0</code> seconds is a reasonable budget per tool call.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-agent">The agent<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#the-agent" class="hash-link" aria-label="Direct link to The agent" title="Direct link to The agent" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tool_node </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"You are a weather assistant. Use get_weather to answer questions. "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"If the tool returns an error, acknowledge the error and suggest the user try again or pick a different city. "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token string" style="color:rgb(255, 121, 198)">"Do not invent weather data."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tool_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    last </span><span class="token operator">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">getattr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tools_calls"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tool"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The system prompt is doing important work. It tells the model <em>how</em> to handle tool errors. Without that instruction, models often hallucinate weather data when the tool fails.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="running-it">Running it<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#running-it" class="hash-link" aria-label="Direct link to Running it" title="Direct link to Running it" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"What's the weather in Tokyo and Bengaluru?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"weather-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"recursion_limit"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">10</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The agent will call <code>get_weather</code> twice (once per city), then synthesize the answer. With <code>recursion_limit=10</code> we cap the loop in case the model decides to retry forever.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="tool-design-tips">Tool design tips<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#tool-design-tips" class="hash-link" aria-label="Direct link to Tool design tips" title="Direct link to Tool design tips" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keep-the-surface-small">Keep the surface small<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#keep-the-surface-small" class="hash-link" aria-label="Direct link to Keep the surface small" title="Direct link to Keep the surface small" translate="no">​</a></h3>
<p>A tool with 8 optional parameters confuses the model. Two common patterns:</p>
<ul>
<li class=""><strong>One tool, one job.</strong> <code>get_weather(location)</code>, not <code>query_weather(location, date, unit, fields)</code>.</li>
<li class=""><strong>Multiple specific tools.</strong> <code>get_current_weather</code>, <code>get_forecast</code>, <code>get_historical_weather</code>. Each does one thing.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="use-string-typed-parameters-when-you-can">Use string-typed parameters when you can<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#use-string-typed-parameters-when-you-can" class="hash-link" aria-label="Direct link to Use string-typed parameters when you can" title="Direct link to Use string-typed parameters when you can" translate="no">​</a></h3>
<p>Models pass strings reliably. They sometimes mangle complex types. If your underlying API takes a date, accept a date <em>string</em> in the tool:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_forecast</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get weather forecast for a city on a specific date.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token triple-quoted-string string" style="display:inline-block;color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">    Args:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">        location: City name.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">        date: ISO date like 2026-04-15.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">    """</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        d </span><span class="token operator">=</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">fromisoformat</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">except</span><span class="token plain"> ValueError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Invalid date '</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">date</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">'. Use ISO format like 2026-04-15."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><br></span></code></pre></div></div>
<p>Validate inside the tool. Don't trust the model to obey type hints.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="return-useful-scannable-results">Return useful, scannable results<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#return-useful-scannable-results" class="hash-link" aria-label="Direct link to Return useful, scannable results" title="Direct link to Return useful, scannable results" translate="no">​</a></h3>
<p>Models read tool results like a human reads a search result. A useful result has:</p>
<ul>
<li class=""><strong>A clear answer line</strong> at the top</li>
<li class=""><strong>Source / context</strong> so the model can cite it</li>
<li class=""><strong>An error explanation</strong> when something goes wrong, with what to do next</li>
</ul>
<p>Bad: <code>{"data": {"temp": 22, "wind": 3.4}}</code>. The model has to interpret it.</p>
<p>Good: <code>Tokyo: 22°C, wind 3.4 km/h. Source: open-meteo.com.</code> The model just reads it.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bound-the-result-size">Bound the result size<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#bound-the-result-size" class="hash-link" aria-label="Direct link to Bound the result size" title="Direct link to Bound the result size" translate="no">​</a></h3>
<p>A tool that dumps 50 KB of API response into the context will blow your token budget on the next turn. Trim before returning:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">search_internal_docs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Search internal documentation."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    hits </span><span class="token operator">=</span><span class="token plain"> vector_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">search</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> top_k</span><span class="token operator">=</span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    summary </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"\n\n"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">h</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation builtin" style="color:rgb(189, 147, 249)">id</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">] </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">h</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">title</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">h</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">text</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation format-spec">300]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">..."</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> h </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> hits</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> summary </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">or</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"No matching docs found."</span><br></span></code></pre></div></div>
<p>Three results × 300 chars = 1 KB. Plenty for the model, manageable cost.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="multi-tool-structured-output-react">Multi-tool, structured-output ReAct<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#multi-tool-structured-output-react" class="hash-link" aria-label="Direct link to Multi-tool, structured-output ReAct" title="Direct link to Multi-tool, structured-output ReAct" translate="no">​</a></h2>
<p>A common pattern: ReAct agent that needs to return a structured result, not free-form text. Use a final "submit answer" tool:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> typing </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> TypedDict</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">WeatherSummary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">TypedDict</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    temperature_c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">float</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    advice</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">submit_summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> WeatherSummary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Call this when you have a final answer. Stores the structured summary."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Persist or return; AgentFlow surfaces this in state for the caller</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Stored summary for </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">summary</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'location'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tool_node </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> submit_summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The agent loops with <code>get_weather</code>, then calls <code>submit_summary</code> once it has all the data. You read the structured result from <code>state</code> after the run finishes.</p>
<p>For a runnable structured-output example, see <a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/react-agent-validation">react-agent-validation</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="persistence">Persistence<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#persistence" class="hash-link" aria-label="Direct link to Persistence" title="Direct link to Persistence" translate="no">​</a></h2>
<p>The agent above is single-shot. For a real assistant, add a checkpointer:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> PgCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">checkpointer</span><span class="token operator">=</span><span class="token plain">PgCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    db_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"postgresql+asyncpg://user:password@localhost/agentflow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    redis_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"redis://localhost:6379/0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Same thread_id in subsequent calls reuses prior history</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-42"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Now turn 2 of the conversation knows what was said in turn 1. See <a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-memory">add memory</a> for the full pattern.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-react-pitfalls">Common ReAct pitfalls<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#common-react-pitfalls" class="hash-link" aria-label="Direct link to Common ReAct pitfalls" title="Direct link to Common ReAct pitfalls" translate="no">​</a></h2>
<ol>
<li class=""><strong>Forgetting <code>recursion_limit</code>.</strong> Default it to 10–25; the model will sometimes loop on errors.</li>
<li class=""><strong>Letting tools throw.</strong> Catch and return as a string. The agent should <em>read</em> the error.</li>
<li class=""><strong>Tools that block too long.</strong> Set HTTP timeouts (3–10 s). A 30-second tool kills the user experience.</li>
<li class=""><strong>Tools with hidden side effects.</strong> A tool that writes to a database needs an idempotency key. See <a class="" href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries">the production post</a>.</li>
<li class=""><strong>Ambiguous tool names.</strong> <code>lookup</code> vs <code>get_weather</code>. Be specific. Models choose tools by name and description.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/react-agent-tools-real-apis#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-a-tool">Add a tool</a>. Beginner walkthrough</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/tool-decorator">Tool decorator tutorial</a>. Advanced patterns</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/react-agent">ReAct agent example</a>. Runnable code</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse">Streaming agent responses</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns">Multi-agent orchestration patterns</a></li>
</ul>
<p>To get a working ReAct agent in five minutes, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a>. The quickstart walks the same pattern, end to end.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="react-agent" term="react-agent"/>
        <category label="tools" term="tools"/>
        <category label="python" term="python"/>
        <category label="api" term="api"/>
        <category label="tutorial" term="tutorial"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Production AI Agents: Observability, Retries, and Graceful Shutdown]]></title>
        <id>https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries</id>
        <link href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries"/>
        <updated>2026-04-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to ship AI agents that survive production. Observability, retry policies, idempotency, graceful shutdown, and the operational patterns Python teams ship.]]></summary>
        <content type="html"><![CDATA[<p>The "hello world" agent works on day one. The "we have paying customers and a pager" agent works on day 200. The gap is operational: observability, retries, idempotency, graceful shutdown.</p>
<p>These are the patterns we see in production Python agent codebases, and the failure modes they prevent.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Production AI Agents. Observability, Retries, and Graceful Shutdown","description":"How to ship AI agents that survive production. Observability, retry policies, idempotency, graceful shutdown, and the operational patterns Python teams ship.","url":"https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries"},"datePublished":"2026-04-06","dateModified":"2026-04-06","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"production agents, observability, retries, graceful shutdown","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="observability-what-to-log">Observability: what to log<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#observability-what-to-log" class="hash-link" aria-label="Direct link to Observability: what to log" title="Direct link to Observability: what to log" translate="no">​</a></h2>
<p>The minimum you should record per agent run:</p>
<table><thead><tr><th>Field</th><th>Why</th></tr></thead><tbody><tr><td><code>thread_id</code></td><td>Find related events</td></tr><tr><td><code>user_id</code> / <code>tenant_id</code></td><td>Multi-tenant analysis</td></tr><tr><td><code>model</code> and <code>provider</code></td><td>Cost attribution</td></tr><tr><td><code>prompt_tokens</code>, <code>completion_tokens</code>, <code>tool_calls</code></td><td>Cost and performance</td></tr><tr><td><code>node</code> (graph node)</td><td>Debug routing</td></tr><tr><td><code>duration_ms</code> per node</td><td>Find slow nodes</td></tr><tr><td><code>outcome</code> (success / error / interrupt)</td><td>SLOs</td></tr><tr><td><code>error_class</code> and <code>error_message</code></td><td>Triage</td></tr></tbody></table>
<p>Emit one log line per node boundary, plus one summary line per request. Anything more granular goes to traces, not logs.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="correlation">Correlation<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#correlation" class="hash-link" aria-label="Direct link to Correlation" title="Direct link to Correlation" translate="no">​</a></h3>
<p>Use <code>thread_id</code> as your trace correlation ID. Every downstream call (tool HTTP request, vector query, database write) should carry it. When a user reports "the agent went weird at 3pm," you grep <code>thread_id</code> and reconstruct the entire run.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="structured-logging">Structured logging<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#structured-logging" class="hash-link" aria-label="Direct link to Structured logging" title="Direct link to Structured logging" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> structlog</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">logger </span><span class="token operator">=</span><span class="token plain"> structlog</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get_logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">log_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"agent.node"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        thread_id</span><span class="token operator">=</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        node</span><span class="token operator">=</span><span class="token plain">node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        message_count</span><span class="token operator">=</span><span class="token builtin" style="color:rgb(189, 147, 249)">len</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        last_role</span><span class="token operator">=</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>JSON logs go to your platform of choice (Loki, Datadog, OpenSearch). Avoid pretty-printed logs in production. They cost CPU and lose searchability.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="tracing-with-opentelemetry">Tracing with OpenTelemetry<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#tracing-with-opentelemetry" class="hash-link" aria-label="Direct link to Tracing with OpenTelemetry" title="Direct link to Tracing with OpenTelemetry" translate="no">​</a></h3>
<p>For deeper insight (per-tool latency, model timing, span trees):</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> opentelemetry </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> trace</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tracer </span><span class="token operator">=</span><span class="token plain"> trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get_tracer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"agentflow.app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">with</span><span class="token plain"> tracer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">start_as_current_span</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"tool.get_weather"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> span</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        span</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_attribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"location"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        result </span><span class="token operator">=</span><span class="token plain"> weather_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        span</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_attribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"weather.summary"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">summary</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Pipe to Tempo, Jaeger, Honeycomb, or whatever you have. The agent runtime is one boundary; the tools are the other. Trace both.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cost-tracking">Cost tracking<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#cost-tracking" class="hash-link" aria-label="Direct link to Cost tracking" title="Direct link to Cost tracking" translate="no">​</a></h3>
<p>Tokens are money. Add a per-run total:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> chunk </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">astream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">event </span><span class="token operator">==</span><span class="token plain"> StreamEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">MESSAGE </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">usage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        total_prompt_tokens </span><span class="token operator">+=</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">usage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">prompt_tokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        total_completion_tokens </span><span class="token operator">+=</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">usage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">completion_tokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">logger</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">info</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"agent.cost"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    thread_id</span><span class="token operator">=</span><span class="token plain">tid</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    prompt_tokens</span><span class="token operator">=</span><span class="token plain">total_prompt_tokens</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    completion_tokens</span><span class="token operator">=</span><span class="token plain">total_completion_tokens</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token plain">model</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>A daily SQL query against this gives you cost per user, per feature, per model. Invaluable when finance asks why the bill jumped.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="retries-where-to-put-them">Retries: where to put them<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#retries-where-to-put-them" class="hash-link" aria-label="Direct link to Retries: where to put them" title="Direct link to Retries: where to put them" translate="no">​</a></h2>
<p>LLM calls and tool calls fail. There are three failure layers, each with different retry rules:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-1-provider-transient-errors">Layer 1: provider transient errors<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#layer-1-provider-transient-errors" class="hash-link" aria-label="Direct link to Layer 1: provider transient errors" title="Direct link to Layer 1: provider transient errors" translate="no">​</a></h3>
<p>Rate limits (429), gateway timeouts (502/504), connection resets. Always retry with exponential backoff:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> tenacity </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> retry</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> stop_after_attempt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> wait_exponential</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> retry_if_exception_type</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> openai </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> RateLimitError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> APIConnectionError</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@retry</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    stop</span><span class="token operator">=</span><span class="token plain">stop_after_attempt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    wait</span><span class="token operator">=</span><span class="token plain">wait_exponential</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">multiplier</span><span class="token operator">=</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">min</span><span class="token operator">=</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">max</span><span class="token operator">=</span><span class="token number">30</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    retry</span><span class="token operator">=</span><span class="token plain">retry_if_exception_type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">RateLimitError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> APIConnectionError</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">call_llm</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><br></span></code></pre></div></div>
<p>Most provider SDKs (OpenAI, Anthropic, Google) have built-in retry; configure it once.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-2-tool-failures">Layer 2: tool failures<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#layer-2-tool-failures" class="hash-link" aria-label="Direct link to Layer 2: tool failures" title="Direct link to Layer 2: tool failures" translate="no">​</a></h3>
<p>Your tool calls a real API. The API returns 500. What do you do?</p>
<p>The wrong answer: retry inside the tool silently and let the agent think the call succeeded.</p>
<p>The right answer: surface the error to the agent as a tool result, and let the agent decide:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get current weather for a location."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> weather_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">except</span><span class="token plain"> Exception </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"Error fetching weather: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">e</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">. Try a different city or fall back to a general estimate."</span><br></span></code></pre></div></div>
<p>The agent, seeing the error, can retry the tool, ask the user, or move on. This is far more robust than swallowing errors.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="layer-3-graph-level-retries">Layer 3: graph-level retries<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#layer-3-graph-level-retries" class="hash-link" aria-label="Direct link to Layer 3: graph-level retries" title="Direct link to Layer 3: graph-level retries" translate="no">​</a></h3>
<p>For a critical action (a payment, an email send), wrap the node in an idempotency-aware retry:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">charge_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    idempotency_key </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">state</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">config</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'thread_id'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">-</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">state</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">config</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">get</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'attempt'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token string-interpolation interpolation"> </span><span class="token string-interpolation interpolation number">0</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> payment_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">charge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount</span><span class="token operator">=</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> key</span><span class="token operator">=</span><span class="token plain">idempotency_key</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Every external write needs an idempotency key. Without it, retries become double-billing.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="idempotency">Idempotency<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#idempotency" class="hash-link" aria-label="Direct link to Idempotency" title="Direct link to Idempotency" translate="no">​</a></h2>
<p>Two rules:</p>
<ol>
<li class=""><strong>Reads are free to retry.</strong> Search, look-up, fetch. Retry as much as you want.</li>
<li class=""><strong>Writes need an idempotency key.</strong> Charges, emails, ticket creation, file uploads.</li>
</ol>
<p>The key is usually <code>thread_id + node_name + attempt_count</code>. Provide it to the upstream API; if the API does not support keys, use a small dedup table:</p>
<div class="language-sql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">TABLE</span><span class="token plain"> agent_idempotency </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">key</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">VARCHAR</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">KEY</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  result JSONB</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  created_at TIMESTAMPTZ </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">NOW</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p><code>INSERT ... ON CONFLICT DO NOTHING RETURNING result</code>. If the key existed, return the previous result without re-doing the action.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="graceful-shutdown">Graceful shutdown<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#graceful-shutdown" class="hash-link" aria-label="Direct link to Graceful shutdown" title="Direct link to Graceful shutdown" translate="no">​</a></h2>
<p>When your container gets a SIGTERM (deploy, autoscale-down, spot reclaim), you have ~30 seconds to clean up. For an agent server, that means:</p>
<ol>
<li class=""><strong>Stop accepting new requests.</strong> Most ASGI servers do this automatically.</li>
<li class=""><strong>Let in-flight requests finish.</strong> Or at least checkpoint their state.</li>
<li class=""><strong>Close the database pool.</strong></li>
<li class=""><strong>Flush logs and traces.</strong></li>
</ol>
<p>AgentFlow's CLI handles 1, 3, and 4. For 2. Letting in-flight runs finish. The checkpointer is your friend: even if the request is killed, the graph state is durable, and a new replica can resume the thread.</p>
<p>The pattern:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># In your FastAPI / agent entrypoint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> signal</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">shutdown </span><span class="token operator">=</span><span class="token plain"> asyncio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">_on_term</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">*</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    shutdown</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SIGTERM</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> _on_term</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">signal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SIGINT</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> _on_term</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># In long-running loops, periodically check shutdown.is_set()</span><br></span></code></pre></div></div>
<p>For a runnable example, see the <a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/graceful-shutdown">graceful shutdown tutorial</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="slos-that-actually-mean-something">SLOs that actually mean something<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#slos-that-actually-mean-something" class="hash-link" aria-label="Direct link to SLOs that actually mean something" title="Direct link to SLOs that actually mean something" translate="no">​</a></h2>
<p>For an agent service, the useful SLOs are:</p>
<ul>
<li class=""><strong>TTFB (time-to-first-byte) p95 &lt; 1.5 s</strong>. First token latency the user feels</li>
<li class=""><strong>Stream-success rate ≥ 99.5%</strong>. Streams that complete without error</li>
<li class=""><strong>Tool-error rate &lt; 2%</strong>. Tool failures bubbling up to user</li>
<li class=""><strong>Cost per request p95 &lt; $X</strong>. Pick a number for your model mix</li>
</ul>
<p>Latency to <em>completion</em> is less useful for streaming agents. Users care about first token, not total time.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="failure-modes-you-will-hit">Failure modes you will hit<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#failure-modes-you-will-hit" class="hash-link" aria-label="Direct link to Failure modes you will hit" title="Direct link to Failure modes you will hit" translate="no">​</a></h2>
<ol>
<li class=""><strong>Recursion runaway.</strong> Always set <code>recursion_limit</code> (10–25 for most workflows).</li>
<li class=""><strong>Token blowout.</strong> A long thread + verbose tool output can blow past the model's context. Trim aggressively.</li>
<li class=""><strong>Provider outage.</strong> Have a fallback model; provider abstractions make this a config change.</li>
<li class=""><strong>Vector store unavailable.</strong> If long-term memory is down, degrade gracefully. Note in the logs and continue without it.</li>
<li class=""><strong>Database lock contention.</strong> <code>PgCheckpointer</code> writes per node; under load, you need a connection pool sized appropriately.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-quick-checklist-before-you-go-live">A quick checklist before you go live<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#a-quick-checklist-before-you-go-live" class="hash-link" aria-label="Direct link to A quick checklist before you go live" title="Direct link to A quick checklist before you go live" translate="no">​</a></h2>
<ul class="contains-task-list containsTaskList_mC6p">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Structured logs with <code>thread_id</code> correlation</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->OpenTelemetry traces for tool calls and LLM calls</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Cost (token) tracking per run</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Provider-level retries configured</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Tool errors surfaced as results, not exceptions</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Idempotency keys on every external write</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <code>recursion_limit</code> set on every invoke</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Fallback model for provider outages</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Graceful shutdown with checkpointer-backed resume</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->SLOs defined and dashboards in place</li>
</ul>
<p>This is the boring stuff that keeps the pager quiet.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/production-ai-agents-observability-retries#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/production-runtime">Production runtime concept</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/auth-and-authorization">Auth and authorization</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/checkpointing">Production checkpointing</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/deployment">Deployment guide</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/graceful-shutdown">Graceful shutdown example</a></li>
</ul>
<p>If you are starting from a prototype and shipping to prod, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a>. The runtime gives you most of this checklist for free.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="production" term="production"/>
        <category label="observability" term="observability"/>
        <category label="retries" term="retries"/>
        <category label="python" term="python"/>
        <category label="ai-agents" term="ai-agents"/>
        <category label="ops" term="ops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Streaming Agent Responses with FastAPI and SSE: A Practical Guide]]></title>
        <id>https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse</id>
        <link href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse"/>
        <updated>2026-03-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to stream AI agent responses to a frontend over Server-Sent Events from a Python FastAPI backend. Handles tool calls, errors, and reconnection.]]></summary>
        <content type="html"><![CDATA[<p>A blocking 30-second response is not a product. The first token in 200ms is. Server-Sent Events (SSE) is still the simplest way to stream agent output from a Python backend to a browser, and it composes well with auth, reconnection, and tool calls.</p>
<p>Here is the production-shaped pattern.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Streaming Agent Responses with FastAPI and SSE. A Practical Guide","description":"How to stream AI agent responses to a frontend over Server-Sent Events from a Python FastAPI backend. Handles tool calls, errors, and reconnection.","url":"https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse"},"datePublished":"2026-03-30","dateModified":"2026-03-30","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"streaming, fastapi, sse, python ai agent","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-sse-not-websockets">Why SSE, not WebSockets<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#why-sse-not-websockets" class="hash-link" aria-label="Direct link to Why SSE, not WebSockets" title="Direct link to Why SSE, not WebSockets" translate="no">​</a></h2>
<p>For agent responses, SSE wins on the things that matter:</p>
<ul>
<li class=""><strong>HTTP/2 friendly</strong>. Works through every proxy and CDN</li>
<li class=""><strong>Automatic reconnect</strong>. Browser does it for you</li>
<li class=""><strong>One-way</strong>. Exactly the data shape you need</li>
<li class=""><strong>Auth is just a header</strong>. No special handshake</li>
</ul>
<p>WebSockets win for full-duplex, low-latency interaction (collaborative editing, multiplayer). For chat / agent streaming, SSE is simpler and more reliable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-an-event-stream-actually-looks-like">What an event stream actually looks like<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#what-an-event-stream-actually-looks-like" class="hash-link" aria-label="Direct link to What an event stream actually looks like" title="Direct link to What an event stream actually looks like" translate="no">​</a></h2>
<p>Each event is a line beginning with <code>data: </code> followed by a JSON payload. AgentFlow's stream emits events with a discriminator field:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: message_chunk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"role": "assistant", "content": "Looking up "}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: message_chunk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"role": "assistant", "content": "the weather"}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: tool_start</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"name": "get_weather", "args": {"location": "Tokyo"}}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: tool_end</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"name": "get_weather", "output": "Sunny, 22°C"}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: message_chunk</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"role": "assistant", "content": "Tokyo is sunny..."}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">event: done</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">data: {"thread_id": "user-1", "tokens": 124}</span><br></span></code></pre></div></div>
<p>Your frontend parses each event and updates the UI accordingly: append text on <code>message_chunk</code>, show a "calling tool..." indicator on <code>tool_start</code>, hide it on <code>tool_end</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="server-side-agentflows-built-in-api">Server side: AgentFlow's built-in API<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#server-side-agentflows-built-in-api" class="hash-link" aria-label="Direct link to Server side: AgentFlow's built-in API" title="Direct link to Server side: AgentFlow's built-in API" translate="no">​</a></h2>
<p>The fastest path: use <code>agentflow api</code>, which already serves SSE-correctly.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow api </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--host</span><span class="token plain"> </span><span class="token number">0.0</span><span class="token plain">.0.0 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--port</span><span class="token plain"> </span><span class="token number">8000</span><br></span></code></pre></div></div>
<p><code>POST /v1/graph/stream</code> is the streaming endpoint. No FastAPI to wire yourself.</p>
<p>If you need custom routing, auth, or pre-processing, mount AgentFlow inside your existing FastAPI app instead.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="server-side-custom-fastapi-integration">Server side: custom FastAPI integration<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#server-side-custom-fastapi-integration" class="hash-link" aria-label="Direct link to Server side: custom FastAPI integration" title="Direct link to Server side: custom FastAPI integration" translate="no">​</a></h2>
<p>Embedding AgentFlow's stream in a FastAPI route:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> fastapi </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> FastAPI</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> fastapi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">responses </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> StreamingResponse</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> pydantic </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> BaseModel</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> ResponseGranularity</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stream_chunks </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> StreamEvent</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> my_app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> app </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> agent_app  </span><span class="token comment" style="color:rgb(98, 114, 164)"># your compiled graph</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">api </span><span class="token operator">=</span><span class="token plain"> FastAPI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">class</span><span class="token plain"> </span><span class="token class-name">Body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">BaseModel</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    thread_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">@api</span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token decorator annotation punctuation" style="color:rgb(248, 248, 242)">post</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/agent/stream"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">gen</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> chunk </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> agent_app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">astream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> body</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">thread_id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"recursion_limit"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">25</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                response_granularity</span><span class="token operator">=</span><span class="token plain">ResponseGranularity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">LOW</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">event </span><span class="token operator">==</span><span class="token plain"> StreamEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">MESSAGE </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    payload </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">yield</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"event: message_chunk\ndata: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">json</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">dumps</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation">payload</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n\n"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">elif</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">event </span><span class="token operator">==</span><span class="token plain"> StreamEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">TOOL_START</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">yield</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"event: tool_start\ndata: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">json</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">dumps</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation">chunk</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">payload</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n\n"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">elif</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">event </span><span class="token operator">==</span><span class="token plain"> StreamEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">TOOL_END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">yield</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"event: tool_end\ndata: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">json</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">dumps</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation">chunk</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">payload</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n\n"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">yield</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"event: done\ndata: {}\n\n"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">except</span><span class="token plain"> Exception </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># noqa: BLE001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">yield</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"event: error\ndata: </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">json</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">dumps</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation string" style="color:rgb(255, 121, 198)">'message'</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token string-interpolation interpolation"> </span><span class="token string-interpolation interpolation builtin" style="color:rgb(189, 147, 249)">str</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation interpolation">e</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">\n\n"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> StreamingResponse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">gen</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> media_type</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"text/event-stream"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> headers</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Cache-Control"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"no-cache"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"X-Accel-Buffering"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"no"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># disable nginx buffering</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Notes:</p>
<ul>
<li class=""><strong><code>X-Accel-Buffering: no</code></strong> prevents nginx from holding events in a buffer</li>
<li class=""><strong>Trailing <code>\n\n</code></strong> ends an SSE event. Required by the spec</li>
<li class=""><strong><code>recursion_limit</code></strong> caps runaway loops at the API boundary</li>
<li class=""><strong>Catch and emit <code>error</code> events</strong> rather than crashing mid-stream</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="frontend-vanilla-browser">Frontend: vanilla browser<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#frontend-vanilla-browser" class="hash-link" aria-label="Direct link to Frontend: vanilla browser" title="Direct link to Frontend: vanilla browser" translate="no">​</a></h2>
<p>Modern browsers ship <code>EventSource</code>, but it does not support custom headers (auth) for non-GET requests. For POST + auth, use <code>fetch</code> with a manual SSE parser or <a href="https://www.npmjs.com/package/@microsoft/fetch-event-source" target="_blank" rel="noopener noreferrer" class=""><code>@microsoft/fetch-event-source</code></a>.</p>
<p>If you do not need auth, a vanilla <code>EventSource</code> is fine:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> es </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name maybe-class-name">EventSource</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"/agent/stream?thread_id=u1&amp;text=hello"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">es</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addEventListener</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"message_chunk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token known-class-name class-name">JSON</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">parse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">appendToUI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">content</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">es</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">addEventListener</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"done"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> es</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">close</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="frontend-typescript-with-auth">Frontend: TypeScript with auth<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#frontend-typescript-with-auth" class="hash-link" aria-label="Direct link to Frontend: TypeScript with auth" title="Direct link to Frontend: TypeScript with auth" translate="no">​</a></h2>
<p>Use AgentFlow's typed client. It handles SSE parsing, reconnection, and Auth headers:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports maybe-class-name">AgentFlowClient</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">Message</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@10xscale/agentflow-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name maybe-class-name">AgentFlowClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  baseUrl</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"/api"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// or full URL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  headers</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token maybe-class-name">Authorization</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Bearer </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">token</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> chunk </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Plan my trip to Tokyo."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">config</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">thread_id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"message_chunk"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">appendToUI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">content</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tool_start"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">showToolIndicator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">type</span><span class="token plain"> </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tool_end"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">hideToolIndicator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>The type definitions match the server's event shape. No untyped JSON in your UI.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reconnection-and-resume">Reconnection and resume<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#reconnection-and-resume" class="hash-link" aria-label="Direct link to Reconnection and resume" title="Direct link to Reconnection and resume" translate="no">​</a></h2>
<p><code>EventSource</code> reconnects automatically with the last-event-id header. For agent streams, this is harder: you do not want to replay the whole conversation, just the events the client missed.</p>
<p>The robust pattern:</p>
<ol>
<li class="">Client requests <code>?thread_id=X</code></li>
<li class="">Server starts streaming from the <em>current</em> graph state (the checkpointer holds it)</li>
<li class="">On disconnect, the server keeps running (do not bind the agent to the SSE response)</li>
<li class="">Client reconnects with the same <code>thread_id</code> and reads only new events</li>
</ol>
<p>Implementing step 3 cleanly requires a publisher / pub-sub between the agent and the SSE handler. For the "good enough" version: persist progress to the checkpointer and have the client poll-then-reconnect.</p>
<p>For the production version, see <a class="" href="https://agentflow.10xscale.ai/docs/concepts/streaming">Streaming concept</a> and <a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/stream-sync">stream-sync tutorial</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="backpressure">Backpressure<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#backpressure" class="hash-link" aria-label="Direct link to Backpressure" title="Direct link to Backpressure" translate="no">​</a></h2>
<p>If the client is slow (mobile, bad network), and the agent is fast, the buffer fills. Two choices:</p>
<ul>
<li class=""><strong>Drop intermediate token chunks</strong> when the client is behind (acceptable for chat)</li>
<li class=""><strong>Batch tokens</strong> into 50–100ms windows (smooths jitter, costs ~1 frame of latency)</li>
</ul>
<p>AgentFlow's <code>ResponseGranularity</code> setting controls this.<code>LOW</code> for individual tokens, higher for batched chunks.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="auth-and-rate-limits">Auth and rate limits<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#auth-and-rate-limits" class="hash-link" aria-label="Direct link to Auth and rate limits" title="Direct link to Auth and rate limits" translate="no">​</a></h2>
<p>A few rules of thumb:</p>
<ol>
<li class=""><strong>Authenticate the request, not the SSE connection.</strong> Pass a JWT in the body of the initial POST; the SSE response is implicitly authenticated.</li>
<li class=""><strong>Rate limit by user</strong>, not by IP. Agent users sit behind shared NATs.</li>
<li class=""><strong>Cap <code>recursion_limit</code></strong> server-side. Do not trust the client to send a sane value.</li>
<li class=""><strong>Add a per-stream timeout</strong> (60–180 s). Long stalls usually mean the model is stuck; better to fail than hang.</li>
</ol>
<p>See <a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/auth-and-authorization">Auth and authorization</a> for AgentFlow's auth options.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-gotchas">Common gotchas<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#common-gotchas" class="hash-link" aria-label="Direct link to Common gotchas" title="Direct link to Common gotchas" translate="no">​</a></h2>
<ul>
<li class=""><strong>CORS preflight blocks SSE</strong> if the browser sends <code>Access-Control-Request-Headers</code> with custom headers. Use <code>client.stream</code> or <code>fetch-event-source</code>, not raw <code>EventSource</code>, when auth is involved.</li>
<li class=""><strong>Server-side proxy buffering.</strong> Nginx, Cloudflare, and AWS ALBs all need explicit "no buffering" hints.</li>
<li class=""><strong>Long-running connections + autoscaling.</strong> SSE connections are sticky; account for that in your scaling policy (use connection draining, not hard kills).</li>
<li class=""><strong>Mobile networks drop frequently.</strong> Reconnection logic is not optional.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/streaming-agent-responses-fastapi-sse#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/streaming">Streaming concept</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/stream-sync">Stream-sync tutorial</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/deployment">Production deployment</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/stop-stream">Stop a stream</a>. Handling client cancellation</li>
</ul>
<p>When you are ready, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a>. The default <code>agentflow api</code> command serves correctly-formatted SSE out of the box.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="streaming" term="streaming"/>
        <category label="fastapi" term="fastapi"/>
        <category label="sse" term="sse"/>
        <category label="python" term="python"/>
        <category label="api" term="api"/>
        <category label="frontend" term="frontend"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI Agent Memory in Python: Short-Term, Long-Term, and Checkpointing]]></title>
        <id>https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python</id>
        <link href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python"/>
        <updated>2026-03-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[How to give a Python AI agent durable memory. Short-term threads, long-term semantic recall, and checkpointing for resumable runs. With AgentFlow code.]]></summary>
        <content type="html"><![CDATA[<p>"Memory" is doing a lot of work in agent literature. It can mean: chat history within a session, long-term semantic recall across sessions, persistent state for resumable runs, or all three. They are different problems with different solutions.</p>
<p>Here is the practical taxonomy and how to wire each one in Python.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"AI Agent Memory in Python. Short-Term, Long-Term, and Checkpointing","description":"How to give a Python AI agent durable memory. Short-term threads, long-term semantic recall, and checkpointing for resumable runs. With AgentFlow code.","url":"https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python"},"datePublished":"2026-03-23","dateModified":"2026-03-23","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"ai agent memory, checkpointing, vector memory, python agents","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="three-kinds-of-memory-three-tools">Three kinds of memory, three tools<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#three-kinds-of-memory-three-tools" class="hash-link" aria-label="Direct link to Three kinds of memory, three tools" title="Direct link to Three kinds of memory, three tools" translate="no">​</a></h2>
<table><thead><tr><th>Kind</th><th>Lifespan</th><th>Mechanism</th></tr></thead><tbody><tr><td><strong>Short-term</strong> (chat history)</td><td>Within one thread</td><td>Checkpointer + <code>thread_id</code></td></tr><tr><td><strong>Long-term</strong> (semantic recall)</td><td>Across users / time</td><td>Vector store accessed as a tool</td></tr><tr><td><strong>Resumable state</strong> (interrupts, replays)</td><td>Until cleanup</td><td>Checkpointer snapshot per node</td></tr></tbody></table>
<p>Most teams need all three. Most "memory" libraries solve one and leave you to assemble the rest.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="short-term-memory-threads-and-checkpointers">Short-term memory: threads and checkpointers<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#short-term-memory-threads-and-checkpointers" class="hash-link" aria-label="Direct link to Short-term memory: threads and checkpointers" title="Direct link to Short-term memory: threads and checkpointers" translate="no">​</a></h2>
<p>A thread is a single conversation. AgentFlow snapshots the entire graph state after every node, keyed by <code>thread_id</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> InMemoryCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Helpful assistant."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">checkpointer</span><span class="token operator">=</span><span class="token plain">InMemoryCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Turn 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"My name is Alex."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-42"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Turn 2 — same thread_id pulls the prior history</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"What's my name?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-42"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Key properties:</p>
<ul>
<li class=""><strong>No code changes</strong> when you swap the storage backend</li>
<li class=""><strong>Same <code>thread_id</code></strong> = same conversation context</li>
<li class=""><strong>Automatic</strong>. You do not assemble the prompt yourself</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="production-storage">Production storage<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#production-storage" class="hash-link" aria-label="Direct link to Production storage" title="Direct link to Production storage" translate="no">​</a></h3>
<p><code>InMemoryCheckpointer</code> is for development. Switch to Postgres + Redis with one import:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> PgCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">checkpointer </span><span class="token operator">=</span><span class="token plain"> PgCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    db_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"postgresql+asyncpg://user:password@localhost/agentflow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    redis_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"redis://localhost:6379/0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">checkpointer</span><span class="token operator">=</span><span class="token plain">checkpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>Postgres holds the durable history; Redis is used for fast hot-path access. See <a class="" href="https://agentflow.10xscale.ai/docs/concepts/checkpointing-and-threads">checkpointing concept</a> and the <a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/checkpointing">production checkpointing guide</a> for tuning.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="trimming-long-threads">Trimming long threads<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#trimming-long-threads" class="hash-link" aria-label="Direct link to Trimming long threads" title="Direct link to Trimming long threads" translate="no">​</a></h3>
<p>Threads grow. At ~100 turns, you start paying for tokens you do not need. Two common patterns:</p>
<ol>
<li class=""><strong>Sliding window</strong>. Keep last N turns, drop the rest</li>
<li class=""><strong>Summary head</strong>. Every 20 turns, replace the oldest 15 with a summary message</li>
</ol>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Helpful assistant."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    trim_context</span><span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># AgentFlow's built-in trimming</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>For custom strategies, see <a class="" href="https://agentflow.10xscale.ai/docs/concepts/state-and-messages">State and messages</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="long-term-memory-semantic-recall">Long-term memory: semantic recall<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#long-term-memory-semantic-recall" class="hash-link" aria-label="Direct link to Long-term memory: semantic recall" title="Direct link to Long-term memory: semantic recall" translate="no">​</a></h2>
<p>Threads cover "what did this user say earlier?" They do not cover "what did <em>any</em> user say about pricing in the last 90 days?" or "what did this user prefer 6 months ago?"</p>
<p>For that, expose a vector store as a tool:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">remember</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Search long-term memory for relevant past interactions."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># qdrant / pgvector / pinecone / your choice</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    hits </span><span class="token operator">=</span><span class="token plain"> vector_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">search</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> top_k</span><span class="token operator">=</span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"\n"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"[</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">h</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation builtin" style="color:rgb(189, 147, 249)">id</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">] </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">h</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string-interpolation interpolation">text</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> h </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> hits</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">write_to_memory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tags</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Store a notable fact for future recall."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    vector_client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">upsert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">text</span><span class="token operator">=</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> metadata</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"tags"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> tags</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Saved."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tool_node </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">remember</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> write_to_memory</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Use `remember` to recall past info and `write_to_memory` "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"to save important new facts. Cite memory IDs."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>The agent decides when to recall and when to write. This is materially different from naively dumping the entire vector index into context. It scales and stays auditable.</p>
<p>For a runnable example with Qdrant, see <a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/qdrant-memory">the qdrant-memory tutorial</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-to-write-vs-when-to-query">When to write vs when to query<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#when-to-write-vs-when-to-query" class="hash-link" aria-label="Direct link to When to write vs when to query" title="Direct link to When to write vs when to query" translate="no">​</a></h3>
<p>A useful default:</p>
<ul>
<li class=""><strong>Always query</strong> at the start of a conversation if the user is identified</li>
<li class=""><strong>Write</strong> when the agent encounters a stable fact (preference, identity, decision). Not raw chat</li>
<li class=""><strong>Tag aggressively</strong> so retrieval can filter by user, tenant, or topic</li>
</ul>
<p>This keeps the long-term store as a curated knowledge base, not a chat dump.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="resumable-runs-checkpointing-for-interrupts-and-replays">Resumable runs: checkpointing for interrupts and replays<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#resumable-runs-checkpointing-for-interrupts-and-replays" class="hash-link" aria-label="Direct link to Resumable runs: checkpointing for interrupts and replays" title="Direct link to Resumable runs: checkpointing for interrupts and replays" translate="no">​</a></h2>
<p>The same checkpointer that powers thread history also powers two other features:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="interrupt-and-resume">Interrupt and resume<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#interrupt-and-resume" class="hash-link" aria-label="Direct link to Interrupt and resume" title="Direct link to Interrupt and resume" translate="no">​</a></h3>
<p>Pause the graph mid-flow, get human approval, then resume:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Refund order #123 for $400."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"approval-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Graph paused at APPROVE node; surface state to a human</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Later — same thread_id resumes from the checkpoint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"approval"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">True</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"approval-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="time-travel--replays">Time travel / replays<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#time-travel--replays" class="hash-link" aria-label="Direct link to Time travel / replays" title="Direct link to Time travel / replays" translate="no">​</a></h3>
<p>Because every node-boundary state is snapshotted, you can replay a thread from any prior state. Useful for debugging "why did the agent choose tool X here?" without rerunning the whole conversation.</p>
<p>See the <a class="" href="https://agentflow.10xscale.ai/docs/concepts/checkpointing-and-threads">interrupts-and-resume tutorial</a> for the details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="putting-it-together-a-memory-architecture">Putting it together: a memory architecture<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#putting-it-together-a-memory-architecture" class="hash-link" aria-label="Direct link to Putting it together: a memory architecture" title="Direct link to Putting it together: a memory architecture" translate="no">​</a></h2>
<p>A production agent typically wires:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">┌──────────────────────────────────────────┐</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  Agent (LLM)                              │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  ├── short-term: PgCheckpointer (thread)  │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  ├── long-term: vector tool (Qdrant)      │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">│  └── resumable: same PgCheckpointer       │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">└──────────────────────────────────────────┘</span><br></span></code></pre></div></div>
<p>Each layer has a different SLA:</p>
<table><thead><tr><th>Layer</th><th>Latency budget</th><th>Storage</th></tr></thead><tbody><tr><td>Short-term</td><td>&lt; 50 ms</td><td>Redis (cached) + Postgres</td></tr><tr><td>Long-term</td><td>&lt; 200 ms</td><td>Vector DB (Qdrant / pgvector)</td></tr><tr><td>Resumable</td><td>&lt; 1 s</td><td>Postgres</td></tr></tbody></table>
<p>These are budgets, not guarantees. The checkpointer is on the hot path; the vector store is opt-in per query. Treat them differently when you scale.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-mistakes">Common mistakes<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#common-mistakes" class="hash-link" aria-label="Direct link to Common mistakes" title="Direct link to Common mistakes" translate="no">​</a></h2>
<ol>
<li class=""><strong>Storing everything in the vector store.</strong> It becomes noise. Curate.</li>
<li class=""><strong>Skipping <code>thread_id</code> in dev.</strong> Then surprised it doesn't remember in prod. Always pass <code>thread_id</code> from day one.</li>
<li class=""><strong>One vector index per user.</strong> Hard to maintain. Use one index with <code>user_id</code> metadata and filter at query time.</li>
<li class=""><strong>No expiry policy.</strong> Memory is a feature; stale memory is a bug. Add TTL on long-term entries.</li>
<li class=""><strong>Treating chat history as long-term memory.</strong> They are not the same. The full chat goes in the checkpointer; <em>facts</em> extracted from chat go in the vector store.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/ai-agent-memory-checkpointing-python#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/checkpointing-and-threads">Checkpointing and threads</a>. Concept guide</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/memory-and-store">Memory and store</a>. Full memory architecture</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-memory">Add memory tutorial</a>. Beginner walkthrough</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/qdrant-memory">Qdrant memory example</a>. Long-term recall</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/checkpointing">Production checkpointing</a>. Postgres + Redis tuning</li>
</ul>
<p>When you are ready, <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a> and you will have working short-term memory in under five minutes.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="memory" term="memory"/>
        <category label="checkpointing" term="checkpointing"/>
        <category label="python" term="python"/>
        <category label="ai-agents" term="ai-agents"/>
        <category label="persistence" term="persistence"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[LangGraph Alternatives: 5 Frameworks to Ship AI Agents Faster]]></title>
        <id>https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks</id>
        <link href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks"/>
        <updated>2026-03-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Five LangGraph alternatives in 2026. AgentFlow, CrewAI, AutoGen, LlamaIndex Agents, and Google ADK. Compare runtimes, persistence, APIs, and when to pick each.]]></summary>
        <content type="html"><![CDATA[<p>LangGraph put graph-based agent orchestration on the map. It is also a fairly opinionated piece of the LangChain ecosystem, and many teams hit limits. Operational, architectural, or licensing. That send them looking for alternatives.</p>
<p>This is a survey of the five strongest LangGraph alternatives in 2026, what each one is good at, and how to decide.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"LangGraph Alternatives — 5 Frameworks to Ship AI Agents Faster","description":"Five LangGraph alternatives in 2026. AgentFlow, CrewAI, AutoGen, LlamaIndex Agents, and Google ADK. Compare runtimes, persistence, APIs, and when to pick each.","url":"https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks"},"datePublished":"2026-03-16","dateModified":"2026-03-16","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"langgraph alternative, agent framework comparison, python agent framework","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-people-look-for-alternatives">Why people look for alternatives<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#why-people-look-for-alternatives" class="hash-link" aria-label="Direct link to Why people look for alternatives" title="Direct link to Why people look for alternatives" translate="no">​</a></h2>
<p>The most common reasons we hear:</p>
<ol>
<li class=""><strong>LangChain dependency tax.</strong> LangGraph builds on LangChain core. If you do not need LangChain, you carry the dependencies anyway.</li>
<li class=""><strong>No built-in production server.</strong> LangGraph is the runtime. Serving an agent over REST/SSE is BYO FastAPI or paid LangGraph Platform.</li>
<li class=""><strong>No first-party TypeScript client.</strong> Most products have a JS frontend; you wrap fetch and parse SSE by hand.</li>
<li class=""><strong>Vendor gravity.</strong> LangSmith and LangGraph Platform are good products and pull you toward a paid stack.</li>
</ol>
<p>If those tradeoffs work for you, stay with LangGraph. It is mature and well-supported. Otherwise, here are the five strongest alternatives.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-agentflow-the-closest-drop-in-alternative">1. AgentFlow: the closest drop-in alternative<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#1-agentflow-the-closest-drop-in-alternative" class="hash-link" aria-label="Direct link to 1. AgentFlow: the closest drop-in alternative" title="Direct link to 1. AgentFlow: the closest drop-in alternative" translate="no">​</a></h2>
<p>AgentFlow is an MIT-licensed graph-based runtime with the same mental model as LangGraph (typed <code>StateGraph</code>, conditional edges, checkpointers) plus a built-in REST + SSE server (<code>agentflow api</code>) and a typed TypeScript client (<code>@10xscale/agentflow-client</code>).</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Helpful assistant."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># ... edges ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Strengths</strong></p>
<ul>
<li class="">Graph mental model identical to LangGraph (one of the most mechanical migrations in the field)</li>
<li class="">Production server + TypeScript client included</li>
<li class="">No required SaaS account, MIT license</li>
<li class="">Multi-provider out of the box (OpenAI, Anthropic, Google, Vertex AI)</li>
</ul>
<p><strong>Weaknesses</strong></p>
<ul>
<li class="">Smaller community than LangGraph today</li>
<li class="">No equivalent of LangSmith for tracing yet (use OpenTelemetry + your existing observability)</li>
</ul>
<p><strong>Pick it when:</strong> you want a graph runtime plus the production stack in one project. → <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-langgraph">AgentFlow vs LangGraph</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-crewai-fastest-path-to-a-role-based-crew">2. CrewAI: fastest path to a role-based crew<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#2-crewai-fastest-path-to-a-role-based-crew" class="hash-link" aria-label="Direct link to 2. CrewAI: fastest path to a role-based crew" title="Direct link to 2. CrewAI: fastest path to a role-based crew" translate="no">​</a></h2>
<p>CrewAI optimizes for declarative role + task DSL. Five lines for "researcher → writer → editor."</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> crewai </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Task</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Crew</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Process</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">researcher </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">role</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Researcher"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> goal</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> backstory</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">writer </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">role</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"Writer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> goal</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> backstory</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">crew </span><span class="token operator">=</span><span class="token plain"> Crew</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">agents</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">researcher</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> writer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tasks</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> process</span><span class="token operator">=</span><span class="token plain">Process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">sequential</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">crew</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">kickoff</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Strengths</strong></p>
<ul>
<li class="">Shortest distance from idea to working crew</li>
<li class="">Hierarchical processes for runtime-dispatched delegation</li>
<li class="">Clear conceptual model for non-engineers</li>
</ul>
<p><strong>Weaknesses</strong></p>
<ul>
<li class="">Less explicit control flow than a graph</li>
<li class="">Production patterns (persistence, API serving) require more glue than LangGraph or AgentFlow</li>
<li class="">CrewAI Enterprise is the recommended production hosting</li>
</ul>
<p><strong>Pick it when:</strong> the workflow really is "roles + tasks" and you want fast prototyping. → <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-crewai">AgentFlow vs CrewAI</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-microsoft-autogen-research-grade-multi-agent-conversations">3. Microsoft AutoGen: research-grade multi-agent conversations<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#3-microsoft-autogen-research-grade-multi-agent-conversations" class="hash-link" aria-label="Direct link to 3. Microsoft AutoGen: research-grade multi-agent conversations" title="Direct link to 3. Microsoft AutoGen: research-grade multi-agent conversations" translate="no">​</a></h2>
<p>AutoGen 0.4 split into core + agentchat + extensions, with strong primitives for multi-agent chat, group chats, and selectors.</p>
<p><strong>Strengths</strong></p>
<ul>
<li class="">Excellent for emergent multi-agent dynamics</li>
<li class="">Actor-style architecture in <code>autogen-core</code></li>
<li class="">AutoGen Studio is a great UI for designing flows visually</li>
</ul>
<p><strong>Weaknesses</strong></p>
<ul>
<li class="">LLM-driven selectors make routing harder to debug under load</li>
<li class="">Production server is BYO</li>
<li class="">API surface still evolving across 0.4.x</li>
</ul>
<p><strong>Pick it when:</strong> you are exploring multi-agent dynamics, working in Microsoft / Azure, or want the visual designer. → <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-autogen">AgentFlow vs AutoGen</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-llamaindex-agents-rag-first-agent-layer">4. LlamaIndex Agents: RAG-first agent layer<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#4-llamaindex-agents-rag-first-agent-layer" class="hash-link" aria-label="Direct link to 4. LlamaIndex Agents: RAG-first agent layer" title="Direct link to 4. LlamaIndex Agents: RAG-first agent layer" translate="no">​</a></h2>
<p>LlamaIndex's <code>FunctionAgent</code>, <code>ReActAgent</code>, and <code>Workflow</code> build on top of best-in-class retrieval and indexing primitives. If your product is "chat with my documents," it is the natural starting point.</p>
<p><strong>Strengths</strong></p>
<ul>
<li class="">Best retrieval + parsing + indexing stack in Python</li>
<li class="">Tight integration between agents and query engines</li>
<li class="">LlamaCloud for managed parsing/indexing</li>
</ul>
<p><strong>Weaknesses</strong></p>
<ul>
<li class="">Agent layer is thinner than the retrieval layer</li>
<li class="">Less explicit multi-agent orchestration</li>
<li class="">No bundled production server</li>
</ul>
<p><strong>Pick it when:</strong> retrieval is the core feature, not just one tool. (Common pattern: LlamaIndex for retrieval, AgentFlow for the runtime.) → <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-llamaindex-agents">AgentFlow vs LlamaIndex Agents</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-google-adk-vertex-ai-native">5. Google ADK: Vertex AI native<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#5-google-adk-vertex-ai-native" class="hash-link" aria-label="Direct link to 5. Google ADK: Vertex AI native" title="Direct link to 5. Google ADK: Vertex AI native" translate="no">​</a></h2>
<p>Google's Agent Development Kit (ADK) is the official Google framework with first-party Gemini and Vertex AI support, plus Vertex AI Agent Engine for hosted execution.</p>
<p><strong>Strengths</strong></p>
<ul>
<li class="">Best-in-class Gemini integration</li>
<li class="">Vertex AI Agent Engine for managed deployment</li>
<li class="">Apache-2.0 license, no required commercial tier</li>
</ul>
<p><strong>Weaknesses</strong></p>
<ul>
<li class="">Provider-neutral by intent, but truly best on Vertex AI</li>
<li class="">No first-party TypeScript client</li>
<li class="">Smaller community outside the Google ecosystem</li>
</ul>
<p><strong>Pick it when:</strong> you are committed to Vertex AI across data, models, and ops. → <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-google-adk">AgentFlow vs Google ADK</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-decision-tree">A decision tree<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#a-decision-tree" class="hash-link" aria-label="Direct link to A decision tree" title="Direct link to A decision tree" translate="no">​</a></h2>
<table><thead><tr><th>Your situation</th><th>Try first</th></tr></thead><tbody><tr><td>Graph mental model + production stack in one project</td><td><strong>AgentFlow</strong></td></tr><tr><td>Already deep in LangChain ecosystem</td><td><strong>LangGraph</strong> (stay)</td></tr><tr><td>Roles + tasks, fast prototype</td><td><strong>CrewAI</strong></td></tr><tr><td>Research / Microsoft stack</td><td><strong>AutoGen</strong></td></tr><tr><td>RAG is the product</td><td><strong>LlamaIndex Agents</strong></td></tr><tr><td>All-in on Vertex AI</td><td><strong>Google ADK</strong></td></tr></tbody></table>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="when-langgraph-is-still-the-right-pick">When LangGraph is still the right pick<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#when-langgraph-is-still-the-right-pick" class="hash-link" aria-label="Direct link to When LangGraph is still the right pick" title="Direct link to When LangGraph is still the right pick" translate="no">​</a></h2>
<p>We will not pretend LangGraph is wrong for everyone. It is the right answer when:</p>
<ul>
<li class="">Your codebase already depends on LangChain runnables and retrievers</li>
<li class="">You use LangSmith for tracing and debugging</li>
<li class="">LangGraph Platform's hosted infrastructure works for your team</li>
<li class="">You want the largest community and the most third-party content</li>
</ul>
<p>The "alternatives" framing is about fit, not quality. All six frameworks here ship production agents in 2026.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-evaluate-without-committing">How to evaluate without committing<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#how-to-evaluate-without-committing" class="hash-link" aria-label="Direct link to How to evaluate without committing" title="Direct link to How to evaluate without committing" translate="no">​</a></h2>
<p>Pick a real, small use case (2 agents, 1 tool, persistent threads) and implement it in your top two candidates. Measure:</p>
<ul>
<li class="">Cold-start time</li>
<li class="">p95 latency under your real load</li>
<li class="">Code size of the agent + the deployment surface</li>
<li class="">How long it takes a new engineer to read the flow</li>
</ul>
<p>The differences become obvious in a week. That signal is worth more than any roundup post, including this one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/langgraph-alternatives-5-frameworks#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started with AgentFlow</a></li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/compare/best-python-agent-framework-2026">Best Python agent frameworks in 2026</a>. Full roundup</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-langgraph">AgentFlow vs LangGraph</a>. Head-to-head</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns">Multi-agent orchestration patterns</a></li>
</ul>
<p>If you are curious about migration mechanics, the <a class="" href="https://agentflow.10xscale.ai/blog/langgraph-to-agentflow-migration">LangGraph → AgentFlow walkthrough</a> covers a full port in one sitting.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="langgraph" term="langgraph"/>
        <category label="alternatives" term="alternatives"/>
        <category label="comparison" term="comparison"/>
        <category label="python" term="python"/>
        <category label="agent-framework" term="agent-framework"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Multi-Agent Orchestration in Python: 7 Patterns That Actually Work]]></title>
        <id>https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns</id>
        <link href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns"/>
        <updated>2026-03-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Seven multi-agent orchestration patterns in Python. Sequential, parallel, router, handoff, supervisor, hierarchical, and human-in-the-loop. With AgentFlow code.]]></summary>
        <content type="html"><![CDATA[<p>Most "multi-agent" demos collapse into a <code>for</code> loop calling two LLMs. That works for a blog post and not much else. Real multi-agent systems need explicit control flow, shared state, and a way to debug when one specialist agent goes off the rails.</p>
<p>Here are seven orchestration patterns we see ship in production Python codebases, and when each one is the right tool.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Multi-Agent Orchestration in Python — 7 Patterns That Actually Work","description":"Seven multi-agent orchestration patterns in Python. Sequential, parallel, router, handoff, supervisor, hierarchical, and human-in-the-loop. With AgentFlow code.","url":"https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns"},"datePublished":"2026-03-09","dateModified":"2026-03-09","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"multi-agent orchestration, python multi-agent, agent patterns, supervisor agent","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-quick-mental-model">A quick mental model<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#a-quick-mental-model" class="hash-link" aria-label="Direct link to A quick mental model" title="Direct link to A quick mental model" translate="no">​</a></h2>
<p>A graph-based runtime models multi-agent flows as <strong>nodes</strong> (agents or tools) connected by <strong>edges</strong> (control flow). State is shared across the graph, and each pattern below is just a different way of wiring the edges.</p>
<p>We use <a class="" href="https://agentflow.10xscale.ai/docs/get-started">AgentFlow</a>'s <code>StateGraph</code> for the examples; the patterns translate to LangGraph, AutoGen, or CrewAI with minor syntax changes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-1-sequential-pipeline">Pattern 1: Sequential pipeline<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-1-sequential-pipeline" class="hash-link" aria-label="Direct link to Pattern 1: Sequential pipeline" title="Direct link to Pattern 1: Sequential pipeline" translate="no">​</a></h2>
<p>The simplest case: agent A → agent B → agent C, in order.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">researcher </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Find three sources for the topic."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">writer </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Use the sources to write a 200-word brief."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">editor </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Tighten and copy-edit the brief."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"RESEARCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> researcher</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"WRITE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> writer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"EDIT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> editor</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"RESEARCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"RESEARCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"WRITE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"WRITE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"EDIT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"EDIT"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> the order is fixed and each step depends on the previous output. Content pipelines, ETL with LLM enrichment, document synthesis.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-2-parallel-fan-out--fan-in">Pattern 2: Parallel fan-out + fan-in<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-2-parallel-fan-out--fan-in" class="hash-link" aria-label="Direct link to Pattern 2: Parallel fan-out + fan-in" title="Direct link to Pattern 2: Parallel fan-out + fan-in" translate="no">​</a></h2>
<p>Run multiple specialists in parallel, then combine.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"FETCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> source_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_A"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> summarizer_a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># different angle</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_B"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> summarizer_b</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MERGE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> merger_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"FETCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"FETCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_A"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"FETCH"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_B"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_A"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MERGE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SUMMARIZE_B"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MERGE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MERGE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> independent perspectives or independent work units (multi-source research, ensemble reasoning). The fan-in node sees both outputs in shared state.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-3-router-deterministic-dispatch">Pattern 3: Router (deterministic dispatch)<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-3-router-deterministic-dispatch" class="hash-link" aria-label="Direct link to Pattern 3: Router (deterministic dispatch)" title="Direct link to Pattern 3: Router (deterministic dispatch)" translate="no">​</a></h2>
<p>A non-LLM router decides which specialist runs next based on a Python function. Cheap, fast, debuggable.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">route_by_intent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    last </span><span class="token operator">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"refund"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">lower</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"REFUNDS"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"delivery"</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">lower</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SHIPPING"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"GENERAL"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"REFUNDS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> refunds_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"SHIPPING"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> shipping_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"GENERAL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> general_agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ROUTE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># placeholder; route is conditional</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">"ROUTE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> route_by_intent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"REFUNDS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"REFUNDS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SHIPPING"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SHIPPING"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"GENERAL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"GENERAL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> the routing decision is deterministic. Saves an LLM call, reduces latency, makes routing trivially testable.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-4-llm-router-semantic-dispatch">Pattern 4: LLM router (semantic dispatch)<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-4-llm-router-semantic-dispatch" class="hash-link" aria-label="Direct link to Pattern 4: LLM router (semantic dispatch)" title="Direct link to Pattern 4: LLM router (semantic dispatch)" translate="no">​</a></h2>
<p>When the routing logic itself needs natural-language understanding, the router becomes a small LLM that picks a downstream node by name.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">prebuilt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">tools </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> create_handoff_tool</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">router_tools </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"refunds"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Send to refunds specialist"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"shipping"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Send to shipping specialist"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"general"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Handle as general inquiry"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">router </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Choose the right specialist for the user's question."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"ROUTER_TOOLS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> intent is ambiguous (multilingual, domain-specific phrasing). Use a small fast model to keep cost down. The router does not need to be the same model that handles the response.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-5-handoff-specialists-pass-control">Pattern 5: Handoff (specialists pass control)<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-5-handoff-specialists-pass-control" class="hash-link" aria-label="Direct link to Pattern 5: Handoff (specialists pass control)" title="Direct link to Pattern 5: Handoff (specialists pass control)" translate="no">​</a></h2>
<p>Specialists can hand off to each other directly, not just back to a central router. This gives you free-form conversations between agents while keeping every transition explicit.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">researcher_tools </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"writer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hand findings to writer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"done"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"End the workflow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">writer_tools </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"researcher"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Need more research"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    create_handoff_tool</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"done"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Finalize the draft"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> the workflow is collaborative and the path is data-dependent. Critic ↔ author loops, debate, hierarchical task decomposition. See the <a class="" href="https://agentflow.10xscale.ai/docs/how-to/python/handoff-between-agents">handoff how-to</a> for the full pattern.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-6-supervisor-manager--workers">Pattern 6: Supervisor (manager + workers)<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-6-supervisor-manager--workers" class="hash-link" aria-label="Direct link to Pattern 6: Supervisor (manager + workers)" title="Direct link to Pattern 6: Supervisor (manager + workers)" translate="no">​</a></h2>
<p>A supervisor agent decides who works on what, monitors progress, and stops when the goal is met.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">supervisor </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"You manage a team of specialists. Decide who handles each task. "</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"When all subtasks are complete, return DONE."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"SUPERVISOR_TOOLS"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> tasks decompose into subtasks of variable count (research → analyse → report; coding → testing → docs). The supervisor pattern is what most teams reach for after sequential pipelines stop scaling.</p>
<p>Set <code>recursion_limit</code> in your invoke config to cap runaway loops.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="pattern-7-human-in-the-loop-interrupt">Pattern 7: Human-in-the-loop interrupt<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#pattern-7-human-in-the-loop-interrupt" class="hash-link" aria-label="Direct link to Pattern 7: Human-in-the-loop interrupt" title="Direct link to Pattern 7: Human-in-the-loop interrupt" translate="no">​</a></h2>
<p>The graph pauses at a node, surfaces state to a human, and resumes when the human approves or edits.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Pause before high-risk actions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"APPROVE"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> human_review_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># writes a "needs_approval" marker</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Refund order #123 for $400."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"human-loop-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># State is checkpointed at APPROVE; resume after human input</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"approval"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean">True</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"human-loop-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>Use when:</strong> decisions exceed the agent's authority. Payments, customer-facing emails, destructive operations. Pair with a checkpointer so the pause is durable across restarts.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-pick">How to pick<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#how-to-pick" class="hash-link" aria-label="Direct link to How to pick" title="Direct link to How to pick" translate="no">​</a></h2>
<table><thead><tr><th>Workflow shape</th><th>Pattern</th></tr></thead><tbody><tr><td>Fixed steps in order</td><td>Sequential</td></tr><tr><td>Independent work in parallel</td><td>Fan-out + fan-in</td></tr><tr><td>Cheap, deterministic dispatch</td><td>Router (Python)</td></tr><tr><td>Semantic dispatch</td><td>LLM router</td></tr><tr><td>Collaborative agent-to-agent</td><td>Handoff</td></tr><tr><td>Variable-count subtasks</td><td>Supervisor</td></tr><tr><td>Risky or revenue actions</td><td>Human-in-the-loop</td></tr></tbody></table>
<p>You can mix patterns in one graph. A supervisor for top-level dispatch, sequential pipelines per subtask, human-in-the-loop on the final step. The graph syntax is the same.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="production-gotchas">Production gotchas<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#production-gotchas" class="hash-link" aria-label="Direct link to Production gotchas" title="Direct link to Production gotchas" translate="no">​</a></h2>
<ul>
<li class=""><strong>Always set <code>recursion_limit</code>.</strong> Default to 10–25. Routers and supervisors love to loop.</li>
<li class=""><strong>Log the graph state at every node boundary.</strong> With <code>AgentState</code> shared, this is one log line per node, not one per LLM call.</li>
<li class=""><strong>Persist threads from day one.</strong> A multi-agent flow without checkpointing is a research script, not a product.</li>
<li class=""><strong>Use small models for routers.</strong> A <code>gemini-2.5-flash</code> router calling a <code>claude-3-5-sonnet</code> specialist is the right cost shape.</li>
<li class=""><strong>Avoid free-form chat between agents.</strong> Handoffs as explicit tool calls are easier to debug than free-form messages.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="further-reading">Further reading<a href="https://agentflow.10xscale.ai/blog/multi-agent-orchestration-python-7-patterns#further-reading" class="hash-link" aria-label="Direct link to Further reading" title="Direct link to Further reading" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/concepts/state-graph">State graph concept</a>. How nodes, edges, and routing work</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/how-to/python/handoff-between-agents">Handoff between agents</a>. Full handoff pattern</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/tutorials/from-examples/multiagent">Multi-agent tutorial</a>. Runnable example</li>
<li class=""><a class="" href="https://agentflow.10xscale.ai/docs/compare">Compare AgentFlow vs LangGraph / CrewAI / AutoGen</a>. Same patterns in other frameworks</li>
</ul>
<p>Once you have the right pattern, the rest is implementation. <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a> and ship the first version this week.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="python" term="python"/>
        <category label="multi-agent" term="multi-agent"/>
        <category label="orchestration" term="orchestration"/>
        <category label="patterns" term="patterns"/>
        <category label="architecture" term="architecture"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to Build an AI Agent in Python: A 2026 Guide]]></title>
        <id>https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python</id>
        <link href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python"/>
        <updated>2026-03-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A practical 2026 guide to building an AI agent in Python. Graphs, tools, memory, streaming, and production deployment. With runnable code in AgentFlow.]]></summary>
        <content type="html"><![CDATA[<p>If you have a Python codebase and an LLM provider, you can ship a working AI agent today. The hard part is no longer "can the model use a tool?". It is "how do I keep this thing reliable in production, with memory, streaming, and a UI."</p>
<p>This guide walks the full path: from a single-tool prototype to a deployed Python AI agent with persistent threads and a typed frontend client. Every snippet runs.</p>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"How to Build an AI Agent in Python. A 2026 Guide","description":"A practical 2026 guide to building an AI agent in Python. Graphs, tools, memory, streaming, and production deployment. With runnable code in AgentFlow.","url":"https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python","mainEntityOfPage":{"@type":"WebPage","@id":"https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python"},"datePublished":"2026-03-02","dateModified":"2026-03-02","author":{"@type":"Organization","name":"AgentFlow Team","url":"https://agentflow.10xscale.ai"},"publisher":{"@type":"Organization","name":"AgentFlow","url":"https://agentflow.10xscale.ai","logo":{"@type":"ImageObject","url":"https://agentflow.10xscale.ai/img/agentflow-mark.svg"}},"image":"https://agentflow.10xscale.ai/img/agentflow-social-card.png","keywords":"python ai agent, build ai agent python, agent framework, tutorial","inLanguage":"en"}</script>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-ai-agent-actually-means-in-2026">What "AI agent" actually means in 2026<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#what-ai-agent-actually-means-in-2026" class="hash-link" aria-label="Direct link to What &quot;AI agent&quot; actually means in 2026" title="Direct link to What &quot;AI agent&quot; actually means in 2026" translate="no">​</a></h2>
<p>The term has stretched. For this guide, an <strong>AI agent</strong> is a Python program that:</p>
<ol>
<li class="">Takes a goal or query from a user</li>
<li class="">Decides which <strong>tools</strong> (functions) to call</li>
<li class="">Calls them, possibly in a loop, and uses the results</li>
<li class="">Returns an answer, or asks for clarification, or hands off to a human</li>
</ol>
<p>Concretely: a function that wraps an LLM, has access to tools, and runs in a controlled loop. Everything else (memory, streaming, multi-agent) is layered on top.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-1-pick-a-runtime-not-just-an-llm-library">Step 1: Pick a runtime, not just an LLM library<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-1-pick-a-runtime-not-just-an-llm-library" class="hash-link" aria-label="Direct link to Step 1: Pick a runtime, not just an LLM library" title="Direct link to Step 1: Pick a runtime, not just an LLM library" translate="no">​</a></h2>
<p>You can write an agent loop with raw provider SDKs. For a one-off script, that is fine. For anything you plan to run more than twice, you want a runtime that gives you:</p>
<ul>
<li class=""><strong>Graph-based control flow</strong>. Explicit state and routing, not a <code>while</code> loop</li>
<li class=""><strong>Persistent state</strong>. A conversation that survives a process restart</li>
<li class=""><strong>Streaming primitives</strong>. Token-by-token responses to a frontend</li>
<li class=""><strong>An API surface</strong>.<code>POST /invoke</code> and <code>POST /stream</code> you can call from anywhere</li>
</ul>
<p>We use <a class="" href="https://agentflow.10xscale.ai/docs/get-started">AgentFlow</a> for the rest of this guide because it ships all of the above in one Python package. The patterns transfer to LangGraph, CrewAI, AutoGen, and others. See the <a class="" href="https://agentflow.10xscale.ai/docs/compare">framework comparisons</a> for the head-to-head.</p>
<p>Install:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pip </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> 10xscale-agentflow 10xscale-agentflow-cli</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-2-define-a-tool">Step 2: Define a tool<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-2-define-a-tool" class="hash-link" aria-label="Direct link to Step 2: Define a tool" title="Direct link to Step 2: Define a tool" translate="no">​</a></h2>
<p>Tools are plain Python functions. AgentFlow reads the type hints and docstring to expose them to the model.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">location</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:rgb(255, 121, 198)">"""Get current weather for a city."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Replace with a real API call</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"It is sunny and 22°C in </span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">location</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">."</span><br></span></code></pre></div></div>
<p>If your function calls an external API, that is the only place network I/O should live. Keep tools pure: in → out, easy to test.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-3-build-the-smallest-working-agent">Step 3: Build the smallest working agent<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-3-build-the-smallest-working-agent" class="hash-link" aria-label="Direct link to Step 3: Build the smallest working agent" title="Direct link to Step 3: Build the smallest working agent" translate="no">​</a></h2>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">graph </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> ToolNode</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">tool_node </span><span class="token operator">=</span><span class="token plain"> ToolNode</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">get_weather</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agent </span><span class="token operator">=</span><span class="token plain"> Agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    model</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"google/gemini-2.5-flash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    system_prompt</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"role"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"system"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"content"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"You are a helpful assistant. Use tools when you need facts."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tool_node</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph </span><span class="token operator">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> agent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> tool_node</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    last </span><span class="token operator">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">context </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">getattr</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tools_calls"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"assistant"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> last </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> last</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">role </span><span class="token operator">==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"tool"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> END</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> route</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> END</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"TOOL"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MAIN"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">result </span><span class="token operator">=</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"What is the weather in Tokyo?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"demo-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>This is a <strong>ReAct agent</strong>. Reason (decide which tool) → Act (call the tool) → Observe (read the result) → loop until the model is done. The <code>route</code> function is the key: it inspects the last message and decides whether to keep looping or finish.</p>
<p>For the full conceptual model, see <a class="" href="https://agentflow.10xscale.ai/docs/concepts/agents-and-tools">Agents and tools</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-4-add-memory-so-the-agent-remembers">Step 4: Add memory so the agent remembers<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-4-add-memory-so-the-agent-remembers" class="hash-link" aria-label="Direct link to Step 4: Add memory so the agent remembers" title="Direct link to Step 4: Add memory so the agent remembers" translate="no">​</a></h2>
<p>A real assistant needs to remember earlier turns. AgentFlow handles this with a <strong>checkpointer</strong> keyed by <code>thread_id</code>:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> InMemoryCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">checkpointer </span><span class="token operator">=</span><span class="token plain"> InMemoryCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app </span><span class="token operator">=</span><span class="token plain"> graph</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">compile</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">checkpointer</span><span class="token operator">=</span><span class="token plain">checkpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Turn 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"My name is Alex and I'm in Bengaluru."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-42"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Turn 2 — same thread_id reuses the entire conversation</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"What's the weather in my city?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"user-42"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><code>InMemoryCheckpointer</code> is good for development. For production, swap to <code>PgCheckpointer</code> (Postgres + Redis) without changing any agent code:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">checkpointer </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> PgCheckpointer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">checkpointer </span><span class="token operator">=</span><span class="token plain"> PgCheckpointer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    db_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"postgresql+asyncpg://user:password@localhost/agentflow"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    redis_url</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"redis://localhost:6379/0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>See <a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-memory">Add memory</a> for the full pattern.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-5-stream-tokens-to-a-frontend">Step 5: Stream tokens to a frontend<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-5-stream-tokens-to-a-frontend" class="hash-link" aria-label="Direct link to Step 5: Stream tokens to a frontend" title="Direct link to Step 5: Stream tokens to a frontend" translate="no">​</a></h2>
<p>Users do not wait for a 30-second blocking response. Stream:</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">utils </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> ResponseGranularity</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> agentflow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">core</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">state</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stream_chunks </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> StreamEvent</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> chunk </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">in</span><span class="token plain"> app</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"messages"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Tell me a story about a Python agent."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    config</span><span class="token operator">=</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string" style="color:rgb(255, 121, 198)">"thread_id"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"story-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    response_granularity</span><span class="token operator">=</span><span class="token plain">ResponseGranularity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">LOW</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">event </span><span class="token operator">==</span><span class="token plain"> StreamEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">MESSAGE </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">and</span><span class="token plain"> chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">is</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">not</span><span class="token plain"> </span><span class="token boolean">None</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">print</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">chunk</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> end</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">""</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> flush</span><span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>For the async variant and how to forward chunks over an HTTP SSE connection, see <a class="" href="https://agentflow.10xscale.ai/docs/concepts/streaming">Streaming</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-6-expose-the-agent-as-an-api">Step 6: Expose the agent as an API<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-6-expose-the-agent-as-an-api" class="hash-link" aria-label="Direct link to Step 6: Expose the agent as an API" title="Direct link to Step 6: Expose the agent as an API" translate="no">​</a></h2>
<p>When you are ready to put this behind a real frontend or call it from another service:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow init</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">agentflow api </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--host</span><span class="token plain"> </span><span class="token number">0.0</span><span class="token plain">.0.0 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--port</span><span class="token plain"> </span><span class="token number">8000</span><br></span></code></pre></div></div>
<p><code>agentflow.json</code> points the CLI at your compiled graph:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token property">"agent"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"graph.react:app"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>You now have:</p>
<ul>
<li class=""><code>POST /v1/graph/invoke</code>. Request/response</li>
<li class=""><code>POST /v1/graph/stream</code>. Server-sent events</li>
<li class=""><code>GET /v1/graph/threads/{id}</code>. Fetch persisted state</li>
</ul>
<p>Production patterns like auth, environment variables, and Docker are covered in <a class="" href="https://agentflow.10xscale.ai/docs/beginner/run-with-api">Run with API</a> and <a class="" href="https://agentflow.10xscale.ai/docs/how-to/production/deployment">Deployment</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="step-7-call-it-from-typescript">Step 7: Call it from TypeScript<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#step-7-call-it-from-typescript" class="hash-link" aria-label="Direct link to Step 7: Call it from TypeScript" title="Direct link to Step 7: Call it from TypeScript" translate="no">​</a></h2>
<p>For a Next.js, React, or Node frontend:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports maybe-class-name">AgentFlowClient</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">Message</span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@10xscale/agentflow-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name maybe-class-name">AgentFlowClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">baseUrl</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"http://127.0.0.1:8000"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">invoke</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token maybe-class-name">Message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">text_message</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"What's the weather in Tokyo?"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">config</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">thread_id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ui-1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token console class-name">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">messages</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">at</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">?.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre></div></div>
<p>The TypeScript client is typed end-to-end. The same <code>Message</code> and <code>thread_id</code> you used in Python are the contract.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-you-ship-vs-what-you-skip">What you ship vs what you skip<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#what-you-ship-vs-what-you-skip" class="hash-link" aria-label="Direct link to What you ship vs what you skip" title="Direct link to What you ship vs what you skip" translate="no">​</a></h2>
<p>A complete production agent has:</p>
<ul>
<li class="">✅ A single tool (we built this)</li>
<li class="">✅ Persistent threads (checkpointer)</li>
<li class="">✅ Streaming (<code>app.stream</code>)</li>
<li class="">✅ A REST API (<code>agentflow api</code>)</li>
<li class="">✅ A typed client (<code>@10xscale/agentflow-client</code>)</li>
</ul>
<p>What you can skip on day one:</p>
<ul>
<li class="">Multi-agent handoffs. Add when one agent is not enough</li>
<li class="">Custom state fields.<code>AgentState</code> covers most cases</li>
<li class="">Vector retrieval. Only when the model's context is not enough</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="common-mistakes-that-bite-in-week-2">Common mistakes that bite in week 2<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#common-mistakes-that-bite-in-week-2" class="hash-link" aria-label="Direct link to Common mistakes that bite in week 2" title="Direct link to Common mistakes that bite in week 2" translate="no">​</a></h2>
<ol>
<li class=""><strong>Using <code>InMemoryCheckpointer</code> in production.</strong> It loses everything on restart. Move to <code>PgCheckpointer</code> before you have real users.</li>
<li class=""><strong>Treating the LLM call as deterministic.</strong> It is not. Always set <code>recursion_limit</code> in your invoke config and handle the case where the agent gives up.</li>
<li class=""><strong>Skipping streaming.</strong> Adding it later means changing your API and frontend. Build streaming into the initial design.</li>
<li class=""><strong>Hard-coding the model.</strong> Use <code>provider/model</code> strings (e.g., <code>"google/gemini-2.5-flash"</code>) so you can swap providers without rewriting the agent. See <a class="" href="https://agentflow.10xscale.ai/docs/providers">providers</a>.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="where-to-go-next">Where to go next<a href="https://agentflow.10xscale.ai/blog/how-to-build-an-ai-agent-in-python#where-to-go-next" class="hash-link" aria-label="Direct link to Where to go next" title="Direct link to Where to go next" translate="no">​</a></h2>
<ul>
<li class="">Beginner path: <a class="" href="https://agentflow.10xscale.ai/docs/beginner/mental-model">Mental model</a> → <a class="" href="https://agentflow.10xscale.ai/docs/beginner/your-first-agent">Your first agent</a> → <a class="" href="https://agentflow.10xscale.ai/docs/beginner/add-a-tool">Add a tool</a></li>
<li class="">Concepts: <a class="" href="https://agentflow.10xscale.ai/docs/concepts/state-graph">State graphs</a>, <a class="" href="https://agentflow.10xscale.ai/docs/concepts/memory-and-store">Memory and store</a></li>
<li class="">Comparison: <a class="" href="https://agentflow.10xscale.ai/docs/compare/agentflow-vs-langgraph">AgentFlow vs LangGraph</a> and <a class="" href="https://agentflow.10xscale.ai/docs/compare">other frameworks</a></li>
</ul>
<p>Or jump straight to <a class="" href="https://agentflow.10xscale.ai/docs/get-started">Get started</a> and have a working agent in five minutes.</p>]]></content>
        <author>
            <name>AgentFlow Team</name>
            <uri>https://github.com/10xHub/Agentflow</uri>
        </author>
        <category label="python" term="python"/>
        <category label="ai-agents" term="ai-agents"/>
        <category label="tutorial" term="tutorial"/>
        <category label="getting-started" term="getting-started"/>
    </entry>
</feed>