<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Richard Dillon</title>
    <description>The latest articles on DEV Community by Richard Dillon (@richard_dillon_b9c238186e).</description>
    <link>https://dev.to/richard_dillon_b9c238186e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3849330%2F15d5a6d5-ef2a-430b-9760-3ac77ede5242.png</url>
      <title>DEV Community: Richard Dillon</title>
      <link>https://dev.to/richard_dillon_b9c238186e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/richard_dillon_b9c238186e"/>
    <language>en</language>
    <item>
      <title>The Evolution of Tool Calling — From Single Function to Multi-Tool Orchestration</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 27 Jul 2026 12:03:53 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/the-evolution-of-tool-calling-from-single-function-to-multi-tool-orchestration-4i0j</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/the-evolution-of-tool-calling-from-single-function-to-multi-tool-orchestration-4i0j</guid>
      <description>&lt;h1&gt;
  
  
  The Evolution of Tool Calling — From Single Function to Multi-Tool Orchestration
&lt;/h1&gt;

&lt;p&gt;Three years ago, "tool calling" meant asking Claude to invoke a single function and parse the JSON response. Today, production agents coordinate dozens of tools across branching execution paths, managing dependencies, handling partial failures, and optimizing for both latency and token budget. This evolution from "call this API" to "orchestrate these 15 tools with typed dependencies" represents one of the most significant architectural shifts in how we build agentic systems. If you're still wiring up tools the way you did in 2024, you're leaving performance on the table and accepting failure modes that modern patterns have solved.&lt;/p&gt;

&lt;p&gt;The recent survey &lt;a href="https://arxiv.org/html/2603.22862v2" rel="noopener noreferrer"&gt;"The Evolution of Tool Use in LLM Agents"&lt;/a&gt; crystallizes what practitioners have been discovering through trial and error: tool calling has matured through distinct generations, each solving problems the previous generation couldn't address. Understanding these generations isn't academic—it's the difference between agents that work in demos and agents that survive production traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Generations of Tool Calling
&lt;/h2&gt;

&lt;p&gt;The history of tool calling in LLM agents follows a clear progression, each generation emerging from the limitations of its predecessor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 1 (2023-2024)&lt;/strong&gt; established the baseline: single-tool invocation with JSON schema descriptions. OpenAI function calling and Anthropic tool use gave us the primitives we still build on today. The pattern was simple—describe your tools in JSON Schema, send the schema with your prompt, parse the function call from the response, execute it, and feed the result back. One tool per turn, synchronous execution, manual result parsing. This worked beautifully for simple use cases: a customer service bot that could check order status, a coding assistant that could run a single command.&lt;/p&gt;

&lt;p&gt;The limitation became apparent immediately: no coordination between tools, no dependency awareness. If your agent needed to fetch customer data &lt;em&gt;and then&lt;/em&gt; check their order status, that was two round trips minimum. Worse, there was no mechanism for the model to express that these operations had a dependency relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 2 (2024-2025)&lt;/strong&gt; introduced parallel function calling and basic orchestration. Models could now request multiple tool invocations in a single response, and patterns like the &lt;a href="https://learn.microsoft.com/en-us/dotnet/ai/conceptual/calling-tools" rel="noopener noreferrer"&gt;&lt;code&gt;FunctionInvokingChatClient&lt;/code&gt;&lt;/a&gt; emerged for automatic parallel dispatch. The token cost reduction was immediate—batched requests meant fewer round trips, and fewer round trips meant faster responses and lower costs.&lt;/p&gt;

&lt;p&gt;But Generation 2 had its own blind spot: no handling of tool interdependencies or mutable state. When a model requested parallel execution of &lt;code&gt;update_user_profile&lt;/code&gt; and &lt;code&gt;send_notification_to_user&lt;/code&gt;, nothing in the system understood that these operations might conflict or that one logically should precede the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation 3 (2026)&lt;/strong&gt; treats tools as nodes in execution graphs with typed dependencies. This is where &lt;a href="https://www.langchain.com/blog/langchain-langgraph-1dot0" rel="noopener noreferrer"&gt;modern frameworks&lt;/a&gt; have been focusing their energy. Tools declare not just their inputs and outputs but their side effects and dependencies. Execution planners build DAGs from these declarations. Speculative tool execution—running tools before you're certain their results will be needed—becomes possible when you can reason about the graph structure. The &lt;a href="https://arxiv.org/html/2603.22862v2" rel="noopener noreferrer"&gt;ToolGen approach&lt;/a&gt; takes this further, representing tools as tokens during training while maintaining their semantic richness at inference time.&lt;/p&gt;

&lt;p&gt;The shift between generations isn't merely about capability—it's about where complexity lives. In Generation 1, the complexity was in your application code, manually orchestrating tool calls. In Generation 3, the complexity is in your tool declarations and the framework's execution planner, letting your agent code focus on business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tool Selection Problem at Scale
&lt;/h2&gt;

&lt;p&gt;When you have 15 tools, naive approaches work fine. Register them all, let the model pick. But when 15 tools becomes 150—a realistic number for enterprise applications integrating multiple internal APIs—the math breaks down catastrophically.&lt;/p&gt;

&lt;p&gt;Consider the token budget: 150 tool descriptions at roughly 200 tokens each consumes 30,000 context tokens before you've even included the user's query. That's most of your context window gone to tool schemas. Research synthesized in the &lt;a href="https://arxiv.org/html/2603.22862v2" rel="noopener noreferrer"&gt;tool use survey&lt;/a&gt; confirms what practitioners discovered empirically: accuracy degrades significantly beyond 20-30 registered tools per request. The model simply can't hold that many tool schemas in working memory while also reasoning about which to use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hierarchical tool retrieval&lt;/strong&gt; addresses this through multiple patterns. The AnyTool approach uses self-reflective hierarchical selection for large-scale API pools—essentially, a tool-selection agent that narrows down candidates before the main agent sees them. The Tulip Agent pattern uses embedding-based tool retrieval, computing similarity between the user query and tool descriptions to select a relevant subset before LLM invocation. Re-Invoke rewrites the user's intent into a form optimized for zero-shot tool retrieval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dynamic tool registration&lt;/strong&gt; offers a complementary strategy. Rather than registering all tools upfront, you register only tools relevant to the current conversation state. A "tool routing" agent—often a lightweight, fast model—selects tool subsets before the main agent executes. In practice, this looks like tool categories with lazy loading: register the category descriptions, and only when the agent selects a category do you load the full schemas for tools within it.&lt;/p&gt;

&lt;p&gt;The research is clear on one point that practitioners sometimes miss: tool description quality matters more than quantity. The &lt;a href="https://github.com/Applied-Machine-Learning-Lab/Awesome-Function-Callings" rel="noopener noreferrer"&gt;EASYTOOL research&lt;/a&gt; on optimizing tool instruction format found that concise, action-oriented descriptions dramatically outperform verbose documentation. "Updates the user's email address in the database" beats a three-paragraph explanation of the email validation rules and database schema. The model needs to understand &lt;em&gt;what the tool does&lt;/em&gt;, not &lt;em&gt;how it does it&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel Execution Safety and State Management
&lt;/h2&gt;

&lt;p&gt;Parallel tool execution offers compelling latency improvements, but it introduces failure modes that don't exist in sequential execution. The mutable state problem is the most dangerous: when Tool A and Tool B both modify the same resource, you have race conditions in agent land.&lt;/p&gt;

&lt;p&gt;Consider a concrete scenario: the model requests parallel execution of &lt;code&gt;update_user_profile(user_id=123, email="new@example.com")&lt;/code&gt; and &lt;code&gt;send_notification_to_user(user_id=123, template="welcome")&lt;/code&gt;. In sequential execution, the notification uses the new email address. In parallel execution, it's a race—the notification might go to the old address, or it might fail entirely if the profile update invalidates some intermediate state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency graph extraction&lt;/strong&gt; offers a systematic solution. Static analysis of tool schemas can identify read/write conflicts: if Tool A writes to resource X and Tool B reads from resource X, there's an implicit dependency. The &lt;a href="https://arxiv.org/html/2603.22862v2" rel="noopener noreferrer"&gt;LLM Compiler approach&lt;/a&gt; treats tool calls as operations in a compiler intermediate representation, with explicit data dependencies that determine execution order. You derive the execution order from the dependency DAG, parallelizing only the tools that are genuinely independent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production safeguards&lt;/strong&gt; layer additional protection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency requirements&lt;/strong&gt;: Tools eligible for parallel execution must be idempotent—calling them twice with the same inputs produces the same result. This eliminates a class of race conditions entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction semantics&lt;/strong&gt;: Checkpoint state before a parallel batch, roll back on any failure. This is easier said than done in distributed systems, but even approximate transactions help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit marking&lt;/strong&gt;: Tools that modify shared state get an &lt;code&gt;@exclusive&lt;/code&gt; marker; the executor serializes all exclusive tools while parallelizing the rest.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Execution Mode&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;th&gt;Failure Handling&lt;/th&gt;
&lt;th&gt;Implementation Complexity&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sequential&lt;/td&gt;
&lt;td&gt;High (sum of all tool latencies)&lt;/td&gt;
&lt;td&gt;Simple—stop on error&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Debugging, simple workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel (naive)&lt;/td&gt;
&lt;td&gt;Low (max tool latency)&lt;/td&gt;
&lt;td&gt;Complex—partial success states&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Independent, read-only tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency-aware&lt;/td&gt;
&lt;td&gt;Medium (critical path latency)&lt;/td&gt;
&lt;td&gt;Managed—DAG-aware rollback&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Production systems with mixed tools&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The dependency-aware approach threads the needle: you get the latency benefits of parallelism where it's safe while maintaining correctness guarantees for tools with real dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification and Error Recovery in Tool Chains
&lt;/h2&gt;

&lt;p&gt;Tool results are not automatically trustworthy. An API might return malformed JSON, a database query might return stale data, an external service might fail silently and return an empty result instead of an error. Verification isn't paranoia—it's engineering rigor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chain-of-Abstraction&lt;/strong&gt; decoding offers an elegant pattern from recent research: the model generates an abstract reasoning chain with placeholders, then populates those placeholders with actual tool outputs. The key insight is that you can verify the reasoning path &lt;em&gt;before&lt;/em&gt; invoking tools. If the abstract plan is "Get user's order history [TOOL_RESULT_1], find the most recent order [DERIVED], check its status [TOOL_RESULT_2]," you can validate that this plan makes sense before spending tokens on tool calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool result validation&lt;/strong&gt; operates at multiple levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema validation&lt;/strong&gt;: Does the tool output match its declared return type? A tool claiming to return a list of orders should not return a string error message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic validation&lt;/strong&gt;: Does this result make sense given the query? A search for orders in the last week returning orders from 2019 suggests a bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence scoring&lt;/strong&gt;: Tools can return confidence alongside their results, letting downstream reasoning weight information appropriately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://github.com/masamasa59/ai-agent-papers/blob/main/capability-papers/tool-use.md" rel="noopener noreferrer"&gt;research on robustness of agentic function calling&lt;/a&gt; identifies common failure modes: tools timing out, returning partial results, or succeeding but with results that don't match the semantic intent. Mitigations include timeout budgets per tool, partial result schemas, and explicit "this tool might return incomplete data" flags in tool descriptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error recovery&lt;/strong&gt; must go beyond simple retry. Production patterns include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool-specific fallback chains&lt;/strong&gt;: If the GitHub API fails, try local git operations. If the primary database is slow, fall back to a read replica.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial result handling&lt;/strong&gt;: When 3 of 5 parallel tools succeed, the agent should be able to reason with incomplete information rather than failing entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalation policies&lt;/strong&gt;: Some failures should surface to users (external service down), while others should auto-recover (transient network error). The escalation policy is tool-specific.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hands-On: Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;Let's build a dependency-aware multi-tool executor in LangGraph. Our scenario: a research agent that needs to fetch company financials, search recent news, analyze sentiment of that news, and generate a summary. The dependency structure is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financials (A) and News Search (B) are independent&lt;/li&gt;
&lt;li&gt;Sentiment Analysis (C) depends on News Search (B)
&lt;/li&gt;
&lt;li&gt;Summary (D) depends on both Financials (A) and Sentiment (C)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.prebuilt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ToolNode&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;defaultdict&lt;/span&gt;

&lt;span class="c1"&gt;# Define our tool result types with explicit schemas
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FinancialData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;revenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;profit_margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;quarter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewsArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;published_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SentimentResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;overall_sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;  &lt;span class="c1"&gt;# "positive", "negative", "neutral"
&lt;/span&gt;    &lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;article_sentiments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Tool definitions with explicit dependency hints in docstrings
# The dependency analyzer will parse these annotations
&lt;/span&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;FinancialData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Fetch quarterly financial data for a company.

    Dependencies: none
    Side effects: none (read-only)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Simulated API call - in production, this hits your financial data API
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;FinancialData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;revenue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;150_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;profit_margin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;quarter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Q2-2026&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_recent_news&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NewsArticle&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search for recent news articles about a company.

    Dependencies: none
    Side effects: none (read-only)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Simulated search - in production, this calls a news API
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;NewsArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; announces new product line&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TechCrunch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;published_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-25&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The company revealed plans for expansion...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;NewsArticle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Q2 earnings beat expectations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bloomberg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;published_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-24&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Strong performance in cloud division...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SentimentResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyze sentiment of news articles.

    Dependencies: requires news articles (output of search_recent_news)
    Side effects: none (read-only)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# In production, this runs sentiment analysis model
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;SentimentResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;overall_sentiment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;article_sentiments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_research_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate a research summary combining financial data and news sentiment.

    Dependencies: requires financials and sentiment analysis results
    Side effects: none (read-only)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Research Summary: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Financial Highlights:
    - Revenue: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;revenue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    - Profit Margin: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profit_margin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    - Quarter: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quarter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    News Sentiment: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;overall_sentiment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    (Confidence: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)

    Overall Assessment: Based on strong financials and positive news sentiment,
    the outlook appears favorable.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# Dependency analyzer that builds execution DAG from tool schemas
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToolDependencyAnalyzer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyzes tool dependencies and builds execution graph.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_parse_dependencies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_parse_dependencies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Extract dependencies from tool docstrings.

        In production, you&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;d use more sophisticated parsing or explicit
        decorators. This demonstrates the pattern.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;deps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Hardcoded for clarity - in production, parse from docstrings/annotations
&lt;/span&gt;        &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_recent_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate_research_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# Tools with no dependencies are implicitly independent
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_execution_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requested_tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return tools grouped by execution level.

        Tools in the same group can execute in parallel.
        Groups must execute sequentially.
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requested_tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;execution_levels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Find tools whose dependencies are all completed
&lt;/span&gt;            &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dep&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Circular dependency detected in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;execution_levels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;execution_levels&lt;/span&gt;

&lt;span class="c1"&gt;# State definition for our research agent
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;company_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;news_articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;current_level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;execution_plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Parallel tool executor with dependency awareness
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DependencyAwareToolExecutor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Executes tools respecting dependency order with parallel dispatch.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;analyzer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ToolDependencyAnalyzer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;tool_names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute a single level of tools in parallel.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Map tool names to their required arguments from state
&lt;/span&gt;                &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_tool_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute all tools in this level concurrently
&lt;/span&gt;        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;run_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_names&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_tool_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Map state to tool arguments. Production code would be more dynamic.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_recent_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;news_articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate_research_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;# Build the LangGraph workflow
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_research_graph&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Construct the LangGraph StateGraph for research workflow.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;search_recent_news&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;generate_research_summary&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DependencyAwareToolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;analyzer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ToolDependencyAnalyzer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plan_execution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate execution plan based on dependencies.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;all_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_recent_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate_research_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;analyzer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_execution_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all_tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execution_plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_current_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute tools at current dependency level.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;tools_to_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execution_plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools_to_run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Update state with results
&lt;/span&gt;        &lt;span class="n"&gt;new_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]))&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tool_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Map results to state fields
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_company_financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_recent_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;news_articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
                &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze_news_sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tool_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate_research_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;new_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_state&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;should_continue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Check if more execution levels remain.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execution_plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Build the graph
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan_execution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;execute_current_level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;should_continue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_research&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_research_graph&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;company_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;financials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;news_articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_level&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execution_plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="c1"&gt;# Run it
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;run_research&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Acme Corp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ACME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Errors: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;errors&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation demonstrates several key patterns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explicit dependency declaration&lt;/strong&gt; in tool docstrings (production systems would use decorators or schema annotations)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topological sorting&lt;/strong&gt; to determine execution levels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel dispatch within levels&lt;/strong&gt; using &lt;code&gt;asyncio.gather&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial failure handling&lt;/strong&gt; that continues execution when some tools fail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State mapping&lt;/strong&gt; between tool outputs and agent state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The execution order for our research scenario is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 0: &lt;code&gt;fetch_company_financials&lt;/code&gt;, &lt;code&gt;search_recent_news&lt;/code&gt; (parallel)&lt;/li&gt;
&lt;li&gt;Level 1: &lt;code&gt;analyze_news_sentiment&lt;/code&gt; (waits for news)&lt;/li&gt;
&lt;li&gt;Level 2: &lt;code&gt;generate_research_summary&lt;/code&gt; (waits for financials and sentiment)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;The evolution from single-tool calling to multi-tool orchestration has concrete implications for how you architect agentic systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token budget planning becomes an architectural concern.&lt;/strong&gt; Just as you budget context window space for RAG retrieval results, you must now budget for tool descriptions. A production system might allocate: 4K tokens for system prompt, 8K for conversation history, 6K for RAG context, and 4K for tool schemas—leaving 10K for actual reasoning. With large toolsets, consider tool description compression, summarization, or the hierarchical retrieval patterns discussed earlier. Monitor token costs per tool invocation in &lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;LangSmith traces&lt;/a&gt; to identify tools with bloated descriptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool API design must optimize for agent consumption.&lt;/strong&gt; This is distinct from designing APIs for human developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Idempotent operations wherever possible&lt;/strong&gt;: Agents retry. A lot. Tools that can be safely re-invoked simplify error handling dramatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear input/output schemas&lt;/strong&gt;: Pydantic models, not loose dicts. The model needs to understand what it's getting back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit side effect documentation&lt;/strong&gt;: If a tool sends an email, that must be crystal clear in the description. Agents can't infer side effects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Framework selection depends on your orchestration needs.&lt;/strong&gt; The &lt;a href="https://www.langchain.com/resources/ai-agent-frameworks" rel="noopener noreferrer"&gt;landscape has matured&lt;/a&gt; considerably:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Tool Orchestration Model&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.langchain.com/oss/python/langgraph/overview" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full control via custom nodes&lt;/td&gt;
&lt;td&gt;Complex, custom workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;Microsoft AutoGen&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Built-in parallel calling, &lt;a href="https://www.microsoft.com/en-us/research/video/autogen-v0-4-reimagining-the-foundation-of-agentic-ai-for-scale-and-more-microsoft-research-forum" rel="noopener noreferrer"&gt;scale-focused architecture&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Multi-agent systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/crewaiinc/crewai" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Task-level parallelism&lt;/td&gt;
&lt;td&gt;Role-based agent teams&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Migration checklist for existing tool implementations:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Audit every tool for idempotency and side effects. Document findings.&lt;/li&gt;
&lt;li&gt;Add explicit type annotations (Pydantic models) to all tool signatures.&lt;/li&gt;
&lt;li&gt;Implement a result validation layer between tools and agent reasoning.&lt;/li&gt;
&lt;li&gt;Classify tools as independent vs. stateful for parallel execution eligibility.&lt;/li&gt;
&lt;li&gt;Set up tool-specific error handlers before enabling parallel execution.&lt;/li&gt;
&lt;li&gt;Add dependency declarations to tools that consume other tools' outputs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;research on agentic system architecture&lt;/a&gt; suggests these patterns will become table stakes. Systems built with sequential-only tool calling will hit performance ceilings that dependency-aware orchestration avoids entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Build This Week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build a "tool catalog" service for your existing agent.&lt;/strong&gt; Take your current tool implementations and build a metadata layer that includes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependency declarations (what other tools' outputs does this tool need?)&lt;/li&gt;
&lt;li&gt;Side effect classifications (read-only, creates resource, updates resource, deletes resource)&lt;/li&gt;
&lt;li&gt;Idempotency flags (safe to retry? safe to parallelize?)&lt;/li&gt;
&lt;li&gt;Estimated latency and token cost per invocation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then implement a simple execution planner that reads this metadata and generates dependency-aware execution orders. Start with just visualization—show yourself the DAG your current tool calls would produce. You'll likely discover implicit dependencies you hadn't thought about and opportunities for parallelization you've been missing.&lt;/p&gt;

&lt;p&gt;The goal isn't to replace your current execution model immediately. The goal is to understand your tool graph well enough to make informed decisions about when parallel execution is safe and when it isn't. That understanding will inform every tool you write going forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2603.22862v2" rel="noopener noreferrer"&gt;The Evolution of Tool Use in LLM Agents: From Single-Tool Call to Multi-Tool Orchestration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/ai/conceptual/calling-tools" rel="noopener noreferrer"&gt;AI tool calling - .NET | Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/langchain-langgraph-1dot0" rel="noopener noreferrer"&gt;LangChain and LangGraph Agent Frameworks Reach v1.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.langchain.com/oss/python/langgraph/overview" rel="noopener noreferrer"&gt;LangGraph overview - Docs by LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;The Agent Development Lifecycle: Build, Test, Deploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/resources/ai-agent-frameworks" rel="noopener noreferrer"&gt;The best AI agent frameworks in 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;GitHub - microsoft/autogen: A programming framework for agentic AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.microsoft.com/en-us/research/video/autogen-v0-4-reimagining-the-foundation-of-agentic-ai-for-scale-and-more-microsoft-research-forum" rel="noopener noreferrer"&gt;AutoGen v0.4: Reimagining the foundation of agentic AI for scale and more - Microsoft Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/crewaiinc/crewai" rel="noopener noreferrer"&gt;crewAIInc/crewAI: Framework for orchestrating role-playing agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/masamasa59/ai-agent-papers/blob/main/capability-papers/tool-use.md" rel="noopener noreferrer"&gt;ai-agent-papers/capability-papers/tool-use.md - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Applied-Machine-Learning-Lab/Awesome-Function-Callings" rel="noopener noreferrer"&gt;GitHub - Applied-Machine-Learning-Lab/Awesome-Function-Callings&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;The Evolution of Agentic AI Software Architecture&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of the **Agentic Engineering Weekly&lt;/em&gt;* series — a deep-dive every Monday into the frameworks,&lt;br&gt;
patterns, and techniques shaping the next generation of AI systems.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building something agentic? Drop a comment — I'd love to feature reader projects.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Weekly: GPT-5.6 Raises the Security Bar, Capital One Arms Defenders, and Agents Get Theoretical Grounding</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 27 Jul 2026 12:02:38 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-gpt-56-raises-the-security-bar-capital-one-arms-defenders-and-agents-get-theoretical-3p34</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-gpt-56-raises-the-security-bar-capital-one-arms-defenders-and-agents-get-theoretical-3p34</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly: GPT-5.6 Raises the Security Bar, Capital One Arms Defenders, and Agents Get Theoretical Grounding
&lt;/h1&gt;

&lt;p&gt;The past week delivered a striking convergence of themes that rarely align so neatly: frontier AI capabilities arriving with unprecedented safety infrastructure, major financial institutions giving away their defensive AI tooling, and academic researchers finally building the theoretical foundations that agentic AI has desperately needed. Whether you're building agents, defending against them, or just trying to keep your stack current, this week offered substantive developments across the board.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI GPT-5.6 Launches with Enhanced Security and Layered Safeguards
&lt;/h2&gt;

&lt;p&gt;OpenAI &lt;a href="https://openai.com/index/gpt-5-6" rel="noopener noreferrer"&gt;released GPT-5.6&lt;/a&gt;, positioning it as "frontier intelligence that scales with your ambition" — marketing speak aside, the technical reality is significant. The model is now the &lt;a href="https://openai.com/index/gpt-5-6" rel="noopener noreferrer"&gt;preferred model in Microsoft 365 Copilot&lt;/a&gt; as of July 9, 2026, meaning enterprise adoption will scale rapidly whether individual developers choose it or not.&lt;/p&gt;

&lt;p&gt;What distinguishes this release is the security posture surrounding it. OpenAI introduced a new rapid-remediation process alongside what they describe as their &lt;a href="https://openai.com/index/gpt-5-6" rel="noopener noreferrer"&gt;strongest monitoring effort to date&lt;/a&gt;. This pairs with existing security and biology bug bounty programs that have been running since earlier model generations. The company explicitly &lt;a href="https://openai.com/index/gpt-5-6" rel="noopener noreferrer"&gt;acknowledges that no perfect security exists&lt;/a&gt;, committing instead to continuous monitoring and collaboration with the defensive security community.&lt;/p&gt;

&lt;p&gt;This framing represents a maturation in how frontier labs discuss risk — less "we've solved safety" and more "we've built responsive infrastructure." For practitioners integrating GPT-5.6 into production systems, the rapid-remediation commitment matters: when vulnerabilities emerge (and they will), the response timeline becomes a critical factor in your own risk calculus. The Microsoft 365 integration also means your enterprise clients are likely already using this model, whether your applications are ready for its behavioral characteristics or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  US Government Negotiating Voluntary AI Model Standards with Industry
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.reuters.com/business/retail-consumer/us-talks-with-ai-companies-voluntary-model-standards-ft-reports-2026-07-02" rel="noopener noreferrer"&gt;Financial Times reported&lt;/a&gt; that advanced talks are underway between the US government and major AI companies to establish a voluntary framework for releasing new AI models. An announcement could come as soon as next week, according to &lt;a href="https://www.reuters.com/business/retail-consumer/us-talks-with-ai-companies-voluntary-model-standards-ft-reports-2026-07-02" rel="noopener noreferrer"&gt;Reuters coverage&lt;/a&gt; of the report.&lt;/p&gt;

&lt;p&gt;The framework would establish voluntary standards rather than mandatory compliance requirements — a significant distinction that will shape how the industry responds. This represents a deliberate shift toward industry self-regulation, with the government providing guardrails rather than prescriptive rules. For AI companies, voluntary standards offer flexibility; for critics, they raise questions about enforcement mechanisms when commercial pressures conflict with safety commitments.&lt;/p&gt;

&lt;p&gt;The timing coincides with &lt;a href="https://openai.com/index/election-safeguards-2026" rel="noopener noreferrer"&gt;election safeguards work&lt;/a&gt; that OpenAI and others have been developing for the 2026 cycle, suggesting the framework may address content generation and misinformation alongside model capability thresholds. If you're building AI products, watch this space closely — "voluntary" standards have a way of becoming procurement requirements and eventually de facto mandates, even without formal regulation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capital One Open-Sources VulnHunter Agentic Security Scanner
&lt;/h2&gt;

&lt;p&gt;In one of the most ambitious public defensive AI releases from a major financial institution, &lt;a href="https://venturebeat.com/technology/capital-one-releases-vulnhunter-an-open-source-ai-tool-that-finds-software-flaws-before-hackers-do" rel="noopener noreferrer"&gt;Capital One released VulnHunter&lt;/a&gt; under the Apache 2.0 license on GitHub. The tool uses what Capital One calls &lt;a href="https://venturebeat.com/technology/capital-one-releases-vulnhunter-an-open-source-ai-tool-that-finds-software-flaws-before-hackers-do" rel="noopener noreferrer"&gt;"attacker-first forward analysis"&lt;/a&gt;, starting from entry points like APIs, network messages, and file uploads, then reasoning forward through application logic to find real exploit paths.&lt;/p&gt;

&lt;p&gt;This approach directly addresses a persistent pain point: the false positive rates that plague conventional backward-scanning static analysis tools. Traditional scanners work backward from potentially dangerous operations, flagging every path that could theoretically reach them. VulnHunter inverts this, asking "what can an attacker actually control, and where can they drive execution?" The result should be findings that map more closely to exploitable vulnerabilities rather than theoretical concerns.&lt;/p&gt;

&lt;p&gt;For security teams drowning in scanner output, the Apache 2.0 licensing means you can integrate this into existing pipelines immediately. The fact that a &lt;a href="https://venturebeat.com/technology/capital-one-releases-vulnhunter-an-open-source-ai-tool-that-finds-software-flaws-before-hackers-do" rel="noopener noreferrer"&gt;major financial institution&lt;/a&gt; is giving away tooling it presumably uses internally suggests either confidence that the approach is now commoditized or a strategic bet that community contributions will improve the tool faster than keeping it proprietary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The theoretical foundations underpinning agentic AI received significant attention this week. A comprehensive paper on &lt;a href="https://arxiv.org/html/2606.12835v1" rel="noopener noreferrer"&gt;"The Internet of Agentic AI"&lt;/a&gt; provides a unified treatment linking classical multi-agent systems research with modern LLM-based frameworks. The analysis covers &lt;a href="https://arxiv.org/html/2606.12835v1" rel="noopener noreferrer"&gt;AutoGPT, BabyAGI, LangChain, LangGraph, CrewAI, AutoGen, Semantic Kernel, and OpenAI Agents SDK&lt;/a&gt; — essentially the entire landscape of tools practitioners are actually using.&lt;/p&gt;

&lt;p&gt;Researchers are tackling practical scaling questions head-on. New work on &lt;a href="https://arxiv.org/list/cs.AI/recent" rel="noopener noreferrer"&gt;confidence-aware routing&lt;/a&gt; proposes dynamic agent role selection across heterogeneous LLMs, letting systems match tasks to model capabilities at runtime rather than design time. The &lt;a href="https://arxiv.org/list/cs.AI/recent" rel="noopener noreferrer"&gt;MonoScale framework&lt;/a&gt; addresses a critical concern for production systems: guaranteeing non-decreasing performance when scaling multi-agent pools, preventing the degradation that often occurs when naively adding agents.&lt;/p&gt;

&lt;p&gt;Perhaps most practically relevant are papers exploring &lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;when single-agent skill libraries can replace multi-agent systems&lt;/a&gt; and identifying the phase transition limits where complexity demands true multi-agent coordination. For teams debating architecture decisions, this research provides empirical grounding for choices that have often been made on intuition. Meanwhile, &lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;negotiation and argumentation frameworks&lt;/a&gt; are gaining attention for decision-making in open multi-agent systems — work tracked in curated lists like &lt;a href="https://github.com/Zijian-Ni/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;awesome-ai-agents-2026&lt;/a&gt; that compile the latest research.&lt;/p&gt;

&lt;h2&gt;
  
  
  LocalAI v4.7.1 Ships Multi-Modal Engine for Any Hardware
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/mudler/localai" rel="noopener noreferrer"&gt;LocalAI released v4.7.1&lt;/a&gt; on July 14, 2026, continuing its mission as an open-source AI engine that runs LLMs, vision, voice, image, and video models without requiring a GPU. The project has accumulated &lt;a href="https://github.com/mudler/localai" rel="noopener noreferrer"&gt;47.6k GitHub stars across 132 releases&lt;/a&gt;, reflecting sustained community interest in hardware-agnostic inference.&lt;/p&gt;

&lt;p&gt;The latest release adds support for MCP (Model Context Protocol), &lt;a href="https://github.com/mudler/localai" rel="noopener noreferrer"&gt;decentralized and distributed inference&lt;/a&gt;, and expanded agent capabilities. For teams targeting on-premise or edge deployment scenarios, this addresses the persistent tension between capability and hardware constraints. Running multi-modal models on CPU-only hardware remains slower than GPU inference, but for compliance-sensitive environments or bandwidth-limited edge cases, the tradeoff often makes sense.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/mudler/localai" rel="noopener noreferrer"&gt;agent capabilities addition&lt;/a&gt; is particularly notable given the broader agentic AI momentum this week. LocalAI positioned as an inference engine that can power agent workflows on arbitrary hardware opens deployment options that cloud-dependent frameworks cannot match.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Codex CLI Gets Desktop Integration and Mobile Preview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;OpenAI's Codex CLI&lt;/a&gt;, now boasting over 82,000 GitHub stars, expanded its integration surface significantly. The tool is now integrated into the ChatGPT desktop app for both macOS and Windows, blurring the line between conversational AI and development tooling.&lt;/p&gt;

&lt;p&gt;July releases added a &lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;beta multi-agent feature powered by GPT-5.6&lt;/a&gt;, enabling coordinated code generation and modification workflows. A May preview introduced &lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;Codex on Mobile&lt;/a&gt;, allowing developers to remote-control macOS Codex instances from iOS and Android devices — useful for monitoring long-running generation tasks or making quick fixes away from a workstation.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;Chrome extension&lt;/a&gt; now enables in-browser DevTools workflows, and for developers who want physical controls, &lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;Codex Micro hardware&lt;/a&gt; — a $230 keypad announced July 15 — provides dedicated buttons for common Codex operations. The multi-modal integration strategy here is clear: meet developers wherever they work, from mobile to browser to dedicated hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Humble Robotics Brings Autonomous Vehicles to Freight Industry
&lt;/h2&gt;

&lt;p&gt;After several hype cycles focused on consumer autonomous vehicles, startups are finding traction in constrained industrial environments. &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;Humble Robotics&lt;/a&gt; represents renewed interest in applying AV technology specifically to freight logistics, focusing on commercial trucking and distribution warehouse operations.&lt;/p&gt;

&lt;p&gt;The freight application sidesteps many challenges that complicated consumer AV deployment: routes are more predictable, operating conditions can be controlled more tightly, and the economic case for autonomy is clearer when driver labor costs dominate logistics margins. Warehouse operations in particular offer the combination of high repetition, controlled environments, and significant labor costs that make automation ROI straightforward to calculate.&lt;/p&gt;

&lt;p&gt;This follows a &lt;a href="https://www.reuters.com/technology" rel="noopener noreferrer"&gt;broader trend&lt;/a&gt; of AV technology finding practical applications in industrial settings — mining, ports, agriculture — where the operational constraints match current system capabilities better than open-road consumer driving.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Watch
&lt;/h2&gt;

&lt;p&gt;The voluntary AI standards framework could materialize within days, potentially reshaping how frontier models reach deployment. Watch for whether VulnHunter's attacker-first approach spawns similar releases from other major enterprises — if this becomes the new baseline for AI-assisted security scanning, backward-scanning tools will need to adapt or become supplementary. The agentic AI research hitting arxiv this month is unusually focused on practical scaling and architecture questions; expect production frameworks to incorporate these findings by Q4.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/gpt-5-6" rel="noopener noreferrer"&gt;GPT-5.6: Frontier intelligence that scales with your ambition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/election-safeguards-2026" rel="noopener noreferrer"&gt;Election information and safeguards in 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/business/retail-consumer/us-talks-with-ai-companies-voluntary-model-standards-ft-reports-2026-07-02" rel="noopener noreferrer"&gt;US in talks with AI companies for voluntary model standards, FT reports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://venturebeat.com/technology/capital-one-releases-vulnhunter-an-open-source-ai-tool-that-finds-software-flaws-before-hackers-do" rel="noopener noreferrer"&gt;Capital One releases VulnHunter, an open-source AI tool that finds software flaws before hackers do | VentureBeat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2606.12835v1" rel="noopener noreferrer"&gt;The Internet of Agentic AI: Communication, Coordination ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;Agentic Artificial Intelligence (AI): Architectures ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;Agentifying Agentic AI 1 - 1 1In: WMAC 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/list/cs.AI/recent" rel="noopener noreferrer"&gt;Artificial Intelligence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Zijian-Ni/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;GitHub - Zijian-Ni/awesome-ai-agents-2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mudler/localai" rel="noopener noreferrer"&gt;LocalAI is the open-source AI engine. Run any model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jamesmurdza/awesome-ai-devtools" rel="noopener noreferrer"&gt;Awesome AI-Powered Developer Tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;TechCrunch | Startup and Technology News&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://www.reuters.com/technology" rel="noopener noreferrer"&gt;Tech News | Today's Latest Technology News&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>Agentic Reasoning Patterns — From ReAct to Hierarchical Planning in Production Systems</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 13 Jul 2026 12:03:51 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/agentic-reasoning-patterns-from-react-to-hierarchical-planning-in-production-systems-3l3d</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/agentic-reasoning-patterns-from-react-to-hierarchical-planning-in-production-systems-3l3d</guid>
      <description>&lt;h1&gt;
  
  
  Agentic Reasoning Patterns — From ReAct to Hierarchical Planning in Production Systems
&lt;/h1&gt;

&lt;p&gt;The days of cobbling together agent systems with ad-hoc prompts and prayer are ending. Just as the Gang of Four's design patterns transformed object-oriented programming from chaotic experimentation into disciplined engineering, a parallel revolution is sweeping through agentic AI development. The January 2026 paper "Architecting Agentic Communities using Design Patterns" &lt;a href="https://arxiv.org/html/2601.03624v3" rel="noopener noreferrer"&gt;cataloged 45+ distinct patterns&lt;/a&gt; across reasoning, memory, and coordination—giving us, for the first time, a shared vocabulary for discussing what actually makes agents work. If you're still building agents by intuition alone, you're leaving significant reliability and performance on the table.&lt;/p&gt;

&lt;p&gt;The research consensus emerging from 2026 is clear: production-grade agents don't rely on single reasoning approaches. They compose multiple patterns—ReAct cycles nested within hierarchical plans, memory augmentation feeding into both—creating systems that are more than the sum of their parts. The &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;Agentic Frameworks for Reasoning Tasks&lt;/a&gt; study demonstrated that single patterns plateau around 67% task completion on complex reasoning benchmarks, while thoughtful composition pushes past 82%. Understanding these patterns isn't academic—it's the difference between agents that demo well and agents that ship.&lt;/p&gt;

&lt;p&gt;This article dives deep into the three foundational reasoning patterns—ReAct, Memory-Augmented, and Hierarchical Planning—and shows you exactly how to compose them in LangGraph. We'll move past the conceptual and into the mechanical: state schemas, routing logic, failure modes, and a complete runnable implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Pattern #1: ReAct — Reasoning-Action Cycles in Practice
&lt;/h2&gt;

&lt;p&gt;The ReAct pattern—Reasoning plus Acting—represents perhaps the most fundamental shift in how we build agents. At its core, ReAct implements interleaved thought-action-observation loops: the agent explicitly reasons about its current state, selects an action (typically a tool call), observes the result, and then reasons again. This cycle continues until the agent determines the task is complete or reaches a termination condition.&lt;/p&gt;

&lt;p&gt;What distinguishes ReAct as an "Agentic AI" pattern rather than a simple "LLM Agent" pattern is the &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;autonomous determination of which actions to take&lt;/a&gt; based on observations. The agent isn't following a predefined workflow—it's dynamically deciding what to do next based on what it's learned. This autonomy is precisely what makes ReAct powerful and precisely what makes it dangerous in production.&lt;/p&gt;

&lt;p&gt;The implementation anatomy breaks down into three distinct components. First, &lt;strong&gt;thought traces as explicit state&lt;/strong&gt;: rather than letting reasoning happen implicitly in the model's hidden representations, ReAct externalizes it. The agent generates a "Thought:" prefix that captures its current understanding and intent. Second, &lt;strong&gt;action selection as tool binding&lt;/strong&gt;: the thought leads to an explicit "Action:" that maps to a tool invocation with specific parameters. Third, &lt;strong&gt;observation parsing as state updates&lt;/strong&gt;: the tool's output becomes an "Observation:" that feeds back into the next reasoning cycle.&lt;/p&gt;

&lt;p&gt;Common failure modes are well-documented but still catch teams by surprise. &lt;strong&gt;Reasoning drift&lt;/strong&gt; occurs when thought traces become increasingly repetitive or circular, often indicating the agent has lost track of its objective. &lt;strong&gt;Action stuttering&lt;/strong&gt; manifests as the same tool being called repeatedly with identical or near-identical parameters—the agent is stuck in a local minimum. &lt;strong&gt;Observation blindness&lt;/strong&gt; happens when the agent generates new thoughts that completely ignore the tool results it just received, often because the context window is saturated or the observation was poorly formatted.&lt;/p&gt;

&lt;p&gt;Production hardening requires explicit countermeasures. &lt;strong&gt;Thought budgets&lt;/strong&gt; cap the number of reasoning cycles (typically 5-7 for most tasks, rarely exceeding 10). &lt;strong&gt;Action deduplication&lt;/strong&gt; tracks recent tool calls and flags or blocks repeated identical invocations. &lt;strong&gt;Observation summarization&lt;/strong&gt; compresses long traces to preserve context window space for fresh reasoning. The &lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;LangGraph framework&lt;/a&gt; provides native support for these patterns through its state management and conditional routing capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Pattern #2: Memory-Augmented Agents — Beyond Conversation History
&lt;/h2&gt;

&lt;p&gt;Memory-Augmented agents learn from interactions to improve future performance—a capability that transforms agents from stateless executors into systems that genuinely get better over time. This pattern operates distinctly from simple conversation history; it involves deliberate storage, retrieval, and application of learned information across sessions and tasks.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;2026 research on agentic frameworks&lt;/a&gt; identifies three critical memory integration points. &lt;strong&gt;Pre-planning retrieval&lt;/strong&gt; queries memory before the agent begins work, surfacing relevant past experiences, user preferences, or domain knowledge that should inform the approach. &lt;strong&gt;Mid-execution reference&lt;/strong&gt; allows the agent to consult memory during reasoning cycles—"Have I seen this error before? What worked last time?" &lt;strong&gt;Post-task consolidation&lt;/strong&gt; extracts lessons learned and stores them for future use, completing the learning loop.&lt;/p&gt;

&lt;p&gt;The Memory as Action paradigm represents a crucial architectural decision. Rather than treating memory operations as implicit system behavior, &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;modern agent frameworks&lt;/a&gt; increasingly expose memory operations—store, retrieve, update, forget—as first-class agent actions. This means the agent explicitly decides when to save information, what queries to run against its memory, and even when to deprecate outdated knowledge. The agent becomes responsible for its own learning, not just its immediate task execution.&lt;/p&gt;

&lt;p&gt;Trade-off analysis reveals the hidden costs of memory augmentation. &lt;strong&gt;Memory hit rate&lt;/strong&gt; measures how often retrieved memories are actually relevant—low hit rates mean you're burning context window tokens on noise. &lt;strong&gt;Retrieval latency&lt;/strong&gt; adds directly to response time; embedding lookups and vector searches aren't free. &lt;strong&gt;Context window consumption&lt;/strong&gt; is the silent killer—rich memory retrieval can consume 30-40% of your available context before the agent even begins reasoning about the current task.&lt;/p&gt;

&lt;p&gt;When does memory hurt? Cases where accumulated memory introduces noise or outdated context are more common than most teams realize. An agent that "remembers" a deprecated API will confidently use it. An agent that learned workarounds for a bug that's since been fixed will apply unnecessary complexity. Memory requires curation, and &lt;a href="https://arxiv.org/html/2601.06064v1" rel="noopener noreferrer"&gt;autonomous agents&lt;/a&gt; that can't distinguish fresh knowledge from stale knowledge will degrade over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Pattern #3: Hierarchical Planning — Decomposing Complex Goals
&lt;/h2&gt;

&lt;p&gt;Hierarchical Planning addresses a fundamental limitation of flat reasoning: some tasks are simply too complex to solve in a single ReAct loop. The pattern involves decomposing complex goals into subgoals, delegating execution to specialized processes, and synthesizing results back up the hierarchy.&lt;/p&gt;

&lt;p&gt;The critical distinction from simple task decomposition lies in &lt;strong&gt;dynamic replanning&lt;/strong&gt;. A static DAG executor follows predetermined paths regardless of intermediate outcomes. Hierarchical Planning, by contrast, monitors subgoal completion and adjusts the broader plan based on what's learned. If subgoal B reveals that subgoal C is unnecessary, a hierarchical planner adapts. If subgoal A fails in an unexpected way, the planner can reformulate subsequent steps or escalate.&lt;/p&gt;

&lt;p&gt;Planning depth trade-offs are well-studied in the &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;2026 agentic frameworks research&lt;/a&gt;. Shallow plans (2-3 levels) execute quickly but may miss important subtleties in complex tasks. Deep plans (5+ levels) capture more nuance but introduce substantial overhead—each planning level requires LLM calls, and errors compound across levels. The research finding is clear: most production systems cap at 4 levels because &lt;strong&gt;planning overhead becomes dominant cost beyond 7 levels&lt;/strong&gt;. The time spent planning exceeds the time saved by better execution.&lt;/p&gt;

&lt;p&gt;Integration with ReAct creates powerful hybrid systems. Rather than choosing between planning and reactive execution, &lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;successful implementations&lt;/a&gt; use ReAct cycles within each planning level while maintaining hierarchical structure. The planner decomposes the goal into subgoals; each subgoal is executed via ReAct loops; observations from execution feed back into the planner for potential replanning. This combination—"hybrid reasoning strategies" in the research terminology—consistently outperforms pure approaches.&lt;/p&gt;

&lt;p&gt;Failure recovery in hierarchical systems requires careful design. &lt;strong&gt;Subgoal failure propagation&lt;/strong&gt; determines how a failed subgoal affects the broader plan—does it block the parent goal, trigger replanning, or get marked as optional? &lt;strong&gt;Replanning triggers&lt;/strong&gt; define when the system should abandon its current plan and start fresh versus attempting local repairs. &lt;strong&gt;Graceful degradation&lt;/strong&gt; ensures that partial success is captured even when full completion isn't possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;Let's build a three-pattern agent in LangGraph that composes ReAct, Memory-Augmented, and Hierarchical Planning. This research assistant plans multi-step investigations, reasons through each step with tool access, and learns from past queries to improve future performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph.message&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;add_messages&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_anthropic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatAnthropic&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.messages&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SystemMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="c1"&gt;# State schema separating planning state, reasoning traces, and memory references
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Hierarchical planning state
&lt;/span&gt;    &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# List of subgoals with status
&lt;/span&gt;    &lt;span class="n"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;planning_depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="c1"&gt;# ReAct reasoning state
&lt;/span&gt;    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;add_messages&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;thought_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;max_thoughts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;  &lt;span class="c1"&gt;# Thought budget for ReAct loops
&lt;/span&gt;    &lt;span class="n"&gt;recent_actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# For action deduplication
&lt;/span&gt;
    &lt;span class="c1"&gt;# Memory-augmented state
&lt;/span&gt;    &lt;span class="n"&gt;memory_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;  &lt;span class="c1"&gt;# Retrieved memories for current task
&lt;/span&gt;    &lt;span class="n"&gt;memories_to_store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Pending memory writes
&lt;/span&gt;
    &lt;span class="c1"&gt;# Meta state for pattern routing
&lt;/span&gt;    &lt;span class="n"&gt;task_complexity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;pattern_trace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Which patterns contributed to decisions
&lt;/span&gt;
&lt;span class="c1"&gt;# Initialize the LLM - using Claude for strong reasoning
&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatAnthropic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define research tools for the ReAct pattern
&lt;/span&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_papers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search academic papers on a topic. Returns summaries of relevant papers.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Simulated - in production, connect to Semantic Scholar, arXiv, etc.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Found 3 papers on &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: [Paper summaries would appear here]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_documentation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search technical documentation for APIs and frameworks.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Documentation results for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: [Docs would appear here]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code_snippet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyze a code snippet for patterns, issues, or improvements.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analysis of code: [Analysis would appear here]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;search_papers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_documentation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;analyze_code&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;llm_with_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Memory operations as first-class actions
&lt;/span&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Store information for future retrieval. 
    memory_type: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fact&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;procedure&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;preference&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, or &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lesson&lt;/span&gt;&lt;span class="sh"&gt;'"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Stored memory &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; of type &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;memory_type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieve relevant memories based on semantic query.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Simulated - in production, vector store retrieval
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retrieved memories relevant to &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: [Memories would appear here]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;memory_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;store_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_memory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;llm_with_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;memory_tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Pattern-specific node: Hierarchical Planning
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;plan_decompose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Decompose the goal into subgoals with hierarchical structure.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Track pattern usage for observability
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hierarchical_planning:decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;planning_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are a research planning agent. Decompose this goal into 
    2-4 concrete subgoals. Each subgoal should be independently executable.

    Goal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;goal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Previously retrieved context from memory:
    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Return a JSON array of subgoals, each with:
    - &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: what to accomplish
    - &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;
    - &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated_complexity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;
    - &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dependencies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: list of subgoal indices this depends on
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nc"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;planning_prompt&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

    &lt;span class="c1"&gt;# Parse the plan (with error handling in production)
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Fallback: single subgoal matching the original goal
&lt;/span&gt;        &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;goal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated_complexity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dependencies&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planning_depth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planning_depth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Pattern-specific node: ReAct reasoning cycle
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reason_act_observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute one ReAct cycle: think, act, observe.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;react:cycle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check thought budget
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_thoughts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thought budget exhausted. Summarizing findings...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]}&lt;/span&gt;

    &lt;span class="n"&gt;current_subgoal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

    &lt;span class="n"&gt;react_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are executing a ReAct reasoning loop.

    Current subgoal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_subgoal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Memory context: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Recent actions taken (avoid repetition): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    Think step by step:
    1. What do I know so far from observations?
    2. What information am I still missing?
    3. What action should I take next?

    If the subgoal is complete, respond with &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SUBGOAL_COMPLETE: [summary]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;
    Otherwise, call the appropriate tool.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;react_prompt&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm_with_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Track the action for deduplication
&lt;/span&gt;    &lt;span class="n"&gt;action_signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning_only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Check for action stuttering (same action 3+ times)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:].&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action_signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;react:stutter_detected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Detected repeated actions. Reconsidering approach...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;action_signature&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Pattern-specific node: Memory query (pre-planning retrieval)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;memory_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Query memory for relevant context before planning or execution.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory:pre_retrieval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Construct semantic query from current goal/subgoal
&lt;/span&gt;    &lt;span class="n"&gt;query_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;goal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;query_target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Simulated memory retrieval - in production, use vector store
&lt;/span&gt;    &lt;span class="n"&gt;retrieved_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Relevant past experiences for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query_target&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: [Retrieved memories]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;retrieved_context&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Pattern-specific node: Memory store (post-task consolidation)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;memory_store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Consolidate learnings from completed subgoal into memory.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory:consolidation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

    &lt;span class="n"&gt;current_subgoal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

    &lt;span class="n"&gt;consolidation_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Review the execution of this subgoal and extract 
    key learnings worth remembering for future tasks.

    Subgoal: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_subgoal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
    Execution trace: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

    What lessons, facts, or procedures should be stored for future reference?
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nc"&gt;SystemMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;consolidation_prompt&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

    &lt;span class="n"&gt;new_memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subgoal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;current_subgoal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;learnings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-13&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# In production, use actual timestamp
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memories_to_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memories_to_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Routing logic: determine which pattern to invoke based on state
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route_by_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Conditional routing based on task complexity and current progress.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# If no plan exists, start with memory retrieval then planning
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if current subgoal is complete
&lt;/span&gt;    &lt;span class="n"&gt;current_subgoal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;last_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;last_message&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SUBGOAL_COMPLETE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Mark subgoal complete and consolidate memory
&lt;/span&gt;        &lt;span class="n"&gt;current_subgoal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Move to next subgoal or finish
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Consolidate before moving on
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;end&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if we need to replan (too many failed attempts)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_thoughts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;routing:replan_considered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Could trigger replanning here for complex failures
&lt;/span&gt;
    &lt;span class="c1"&gt;# Default: continue ReAct cycle for current subgoal
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;advance_subgoal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Advance to the next subgoal after memory consolidation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Reset thought budget for new subgoal
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;  &lt;span class="c1"&gt;# Clear action history
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;  &lt;span class="c1"&gt;# Will be refreshed by memory_query
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Build the composed graph
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_research_agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Construct the three-pattern agent graph.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add pattern-specific nodes
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory_query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan_decompose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason_act_observe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory_store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advance_subgoal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;advance_subgoal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Entry point: always start with memory retrieval
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Memory query leads to planning if no plan exists
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Planning leads to ReAct execution
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ReAct cycles with conditional exit
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;route_by_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason_act_observe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan_decompose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;end&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Memory store leads to advancing subgoal
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advance_subgoal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# After advancing, query memory for new context
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advance_subgoal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Usage example with observability
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_research_agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;goal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compare ReAct and Chain-of-Thought prompting for code generation tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;plan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_subgoal_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;planning_depth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_thoughts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Thought budget per subgoal
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recent_actions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory_context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memories_to_store&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;task_complexity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Execute with streaming for observability
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;node_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;node_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pattern trace: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pattern_trace&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thought count: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;thought_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;max_thoughts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above demonstrates several key architectural decisions. The &lt;code&gt;AgentState&lt;/code&gt; TypedDict cleanly separates concerns—planning state, reasoning traces, and memory references each have their own fields, making the graph easier to debug and extend. The &lt;code&gt;pattern_trace&lt;/code&gt; field provides observability into which patterns contributed to each decision, essential for &lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;debugging in LangSmith&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Notice how the routing function &lt;code&gt;route_by_state&lt;/code&gt; implements the pattern composition logic. It checks for plan existence, subgoal completion, and thought budget exhaustion to determine which pattern to invoke next. This is the "sequential composition" approach—plan first, then execute via ReAct, with memory operations at key integration points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern Composition: The 2026 Research Consensus
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;Agentic Frameworks for Reasoning Tasks&lt;/a&gt; study crystallized what practitioners had been discovering empirically: single patterns plateau, and composition unlocks the next performance tier. Their benchmarks showed ReAct alone achieving 67% task completion on complex reasoning tasks, rising to 82% when combined with memory patterns and hierarchical planning.&lt;/p&gt;

&lt;p&gt;Three composition strategies dominate the research literature. &lt;strong&gt;Sequential composition&lt;/strong&gt; (plan → execute) is what we implemented above—hierarchical planning produces a structure that ReAct cycles then fill in. &lt;strong&gt;Nested composition&lt;/strong&gt; embeds one pattern within another's nodes—for example, using ReAct cycles within each planning decision to gather information before committing to subgoals. &lt;strong&gt;Parallel composition&lt;/strong&gt; runs multiple reasoning strategies simultaneously and uses voting or critic agents to select the best output.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Critic-Actor meta-pattern&lt;/strong&gt; deserves special attention. This approach uses one agent pattern to evaluate another's outputs—a planning agent that critiques a ReAct agent's proposed actions before allowing them, or a memory-augmented critic that checks whether proposed plans align with past successful approaches. The &lt;a href="https://arxiv.org/html/2603.22359v1" rel="noopener noreferrer"&gt;STEM Agent architecture&lt;/a&gt; demonstrates this with its self-adapting evaluation loops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reflexion integration&lt;/strong&gt; takes composition further by implementing self-improvement loops that modify pattern parameters based on task outcomes. If ReAct cycles consistently hit thought budgets on certain task types, a Reflexion layer can learn to increase the budget or trigger earlier replanning. This meta-learning over pattern configurations represents the frontier of agent development.&lt;/p&gt;

&lt;p&gt;Anti-patterns discovered through &lt;a href="https://arxiv.org/html/2601.07136v1" rel="noopener noreferrer"&gt;large-scale studies&lt;/a&gt; include &lt;strong&gt;memory-before-planning&lt;/strong&gt;, which retrieves context before understanding what context is actually needed, resulting in irrelevant or distracting information. &lt;strong&gt;Over-hierarchical&lt;/strong&gt; designs spend more time planning than executing, particularly problematic when planning overhead exceeds 40% of total execution time. &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;LangGraph's StateGraph&lt;/a&gt; natively supports pattern composition through its subgraph and conditional routing features, while alternatives often require custom orchestration layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;Pattern selection should follow a clear heuristic based on task autonomy requirements. &lt;strong&gt;Low autonomy tasks&lt;/strong&gt;—structured data extraction, validation, simple retrieval—benefit from Structured Output and Validation patterns, not full ReAct loops. The overhead isn't worth it. &lt;strong&gt;High autonomy tasks&lt;/strong&gt;—open-ended research, complex debugging, multi-step investigations—justify the ReAct + Memory + Planning composition. The &lt;a href="https://www.langchain.com/resources/ai-agent-frameworks" rel="noopener noreferrer"&gt;best AI agent frameworks&lt;/a&gt; in 2026 support both modes without forcing you into one approach.&lt;/p&gt;

&lt;p&gt;The migration path for existing systems follows a proven trajectory. Start with ReAct alone, validating that your tools and observation parsing work correctly. Add memory when you see repeated tasks that could benefit from learned context—but measure memory hit rate before committing. Add hierarchical planning when task complexity exceeds what single-level reasoning can handle, typically indicated by thought budget exhaustion becoming common.&lt;/p&gt;

&lt;p&gt;Observability requirements differ by pattern. ReAct needs thought trace visibility and action frequency monitoring. Memory needs retrieval quality metrics and staleness tracking. Hierarchical planning needs subgoal completion rates and replanning frequency. &lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;LangSmith&lt;/a&gt; already supports custom annotations; pattern-specific trace categories are reportedly coming Q3 2026.&lt;/p&gt;

&lt;p&gt;Cost implications are non-trivial. Hierarchical planning multiplies LLM calls—a 4-level plan with 3 subgoals per level means 40+ planning calls before execution even begins. Memory retrieval adds 100-500ms latency per lookup depending on your vector store. Budget your patterns based on task value: high-stakes tasks justify composition overhead; routine tasks should use minimal patterns.&lt;/p&gt;

&lt;p&gt;Testing strategy must address pattern interactions. Unit test individual patterns with mocked dependencies—verify ReAct handles observation blindness, verify memory retrieval degrades gracefully with empty stores, verify planning caps at maximum depth. Integration test compositions to catch emergent failures—patterns that work individually can interfere when combined. The research community has developed &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;MemBench and SkillBench&lt;/a&gt; for regression testing; adopt similar benchmark-driven testing for your specific domain.&lt;/p&gt;

&lt;p&gt;When should you avoid patterns entirely? Simple retrieval tasks don't need reasoning loops. Deterministic workflows with known branching don't need planning. Latency-critical paths (sub-second requirements) often can't afford pattern overhead. Not every agent needs to be agentic—sometimes a well-tuned prompt and a single LLM call is the right answer. The &lt;a href="https://arxiv.org/html/2601.06064v1" rel="noopener noreferrer"&gt;socio-technical analysis&lt;/a&gt; of agentic systems emphasizes that pattern complexity should match problem complexity, not exceed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Build This Week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project: Build a Pattern-Instrumented Research Assistant&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Take the code from the walkthrough and extend it with full pattern observability. Your goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instrument pattern transitions&lt;/strong&gt;: Log every time the router switches between patterns, including the state that triggered the switch. Output should show the pattern sequence for any query: &lt;code&gt;memory_query → plan_decompose → reason_act_observe × 4 → memory_store → advance_subgoal → memory_query → reason_act_observe × 2 → end&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implement pattern metrics&lt;/strong&gt;: Track thought budget utilization per subgoal, memory hit rate (how often retrieved memories appear in subsequent reasoning), and planning overhead ratio (planning time / total time).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a failure injection mode&lt;/strong&gt;: Randomly fail tool calls or return unhelpful observations. Observe how your pattern composition handles degraded inputs. Does it replan? Hit thought budgets? Fall into action stuttering?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connect to real tools&lt;/strong&gt;: Replace the simulated tools with actual API calls—arXiv API for paper search, your codebase for documentation search. See how real-world latency and result variability affect pattern behavior.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal isn't a production-ready assistant—it's building intuition for how these patterns interact under realistic conditions. The teams shipping reliable agents in 2026 are the ones who've internalized these failure modes through hands-on experimentation, not just reading about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/langgraph" rel="noopener noreferrer"&gt;LangGraph: Agent Orchestration Framework for Reliable AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;langchain-ai/langgraph: Build resilient agents - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;Agentic Frameworks for Reasoning Tasks: An Empirical Study - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.03624v3" rel="noopener noreferrer"&gt;Architecting Agentic Communities using Design Patterns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.06064v1" rel="noopener noreferrer"&gt;Socio-technical aspects of Agentic AI - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2603.22359v1" rel="noopener noreferrer"&gt;STEM Agent: A Self-Adapting, Tool-Enabled, Extensible Architecture for Multi-Protocol AI Agent Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.07136v1" rel="noopener noreferrer"&gt;A Large-Scale Study on the Development and Issues of Multi-Agent AI Systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://www.langchain.com/resources/ai-agent-frameworks" rel="noopener noreferrer"&gt;The best AI agent frameworks in 2026 - LangChain&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of the **Agentic Engineering Weekly&lt;/em&gt;* series — a deep-dive every Monday into the frameworks,&lt;br&gt;
patterns, and techniques shaping the next generation of AI systems.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building something agentic? Drop a comment — I'd love to feature reader projects.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Weekly Briefing: OpenAI's Flagship Model Finally Ships as Industry Pivots from Scale to Strategy</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 13 Jul 2026 12:02:44 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-briefing-openais-flagship-model-finally-ships-as-industry-pivots-from-scale-to-strategy-29mn</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-briefing-openais-flagship-model-finally-ships-as-industry-pivots-from-scale-to-strategy-29mn</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly Briefing: OpenAI's Flagship Model Finally Ships as Industry Pivots from Scale to Strategy
&lt;/h1&gt;

&lt;p&gt;The AI landscape this week crystallizes a fundamental tension: while OpenAI prepares to launch its most capable model yet, the broader industry narrative has shifted decisively away from "bigger is better" toward pragmatic deployment. Add in geopolitical maneuvering over model access, a sobering benchmark showing most frontier LLMs can't actually trade profitably, and you have a week that captures 2026's defining themes—capability meets reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI's Most Capable GPT Model Set to Launch After Delayed Rollout
&lt;/h2&gt;

&lt;p&gt;After months of delays that tested investor patience, OpenAI &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;confirmed the imminent release of its most capable GPT model&lt;/a&gt;, marking what the company frames as a significant leap in reasoning and multimodal capabilities. The extended development timeline had fueled speculation about technical challenges, but sources familiar with the matter suggest the delays were driven by safety testing rather than fundamental architecture problems.&lt;/p&gt;

&lt;p&gt;The timing isn't coincidental. Bank of America &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;extended a first $520 million loan&lt;/a&gt; to OpenAI ahead of an anticipated IPO, signaling financial markets remain bullish on the company despite competitive headwinds. This capital infusion provides runway for the costly inference infrastructure required to serve a model of this scale.&lt;/p&gt;

&lt;p&gt;Perhaps more telling is the competitive context: &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Reuters reports&lt;/a&gt; the release timing reflects strategic positioning against DeepSeek and other Chinese labs that have demonstrated comparable performance at fraction of the compute cost. The pressure from Chinese AI labs has intensified throughout 2026, forcing OpenAI to accelerate its roadmap while maintaining its safety-focused brand positioning. Whether the new model justifies the development investment—or simply matches what competitors achieved months ago—remains to be seen once benchmarks emerge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beijing Considers Curbing Overseas Access to China's Top AI Models
&lt;/h2&gt;

&lt;p&gt;In a development that could reshape the global AI research landscape, &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Chinese government officials are reportedly exploring restrictions&lt;/a&gt; on foreign access to the country's leading domestic AI models. The policy discussions, driven by national security concerns, signal a potential escalation in the US-China technology competition that has already fractured semiconductor supply chains.&lt;/p&gt;

&lt;p&gt;The implications extend beyond geopolitics. Researchers and companies worldwide have increasingly relied on Chinese open-source models and API-accessible systems, particularly after DeepSeek demonstrated that competitive performance doesn't require OpenAI-scale resources. Restricting access would force a recalibration of research workflows and enterprise deployments that had bet on Chinese model availability.&lt;/p&gt;

&lt;p&gt;Sources indicate the discussions remain preliminary, with no final policy decisions announced. However, the mere consideration of such restrictions reflects Beijing's growing view of advanced AI capabilities as strategic assets rather than commercial products. For Western enterprises that integrated Chinese models into production systems—attracted by cost advantages and increasingly competitive benchmark performance—the uncertainty alone may prompt diversification strategies. The asymmetry is notable: while US export controls target hardware and training infrastructure, China's potential countermeasures would target the models themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The academic foundations of agentic AI received a pointed critique this week. A new &lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;arXiv paper titled "Agentifying Agentic AI"&lt;/a&gt; argues that the autonomous agents community (AAMAS) has spent decades developing tools—BDI architectures, FIPA-ACL communication protocols, mechanism design frameworks—that could solve problems the current LLM-based agent wave repeatedly stumbles over. The authors specifically criticize the reliance on unstructured natural language dialogue between agents, calling instead for formal communication protocols and institutional modeling that provide guarantees about agent behavior.&lt;/p&gt;

&lt;p&gt;On the tooling front, &lt;a href="https://github.com/VoltAgent/awesome-ai-agent-papers" rel="noopener noreferrer"&gt;VoltAgent's curated 2026 paper collection&lt;/a&gt; has grown substantially, now tracking 53 multi-agent papers, 95 agent tooling papers, and 82 AI agent security papers published since January alone. The security category's rapid growth reflects enterprise deployment concerns that the research community is scrambling to address.&lt;/p&gt;

&lt;p&gt;Two new evaluation frameworks emerged targeting different aspects of agent reliability. The LUMINA framework introduces methods for measuring individual capability criticality in multi-turn agentic tasks—essentially determining which component failures cascade into task failures. Separately, a new &lt;a href="https://arxiv.org/list/cs.AI/recent" rel="noopener noreferrer"&gt;diagnostic framework presents a 12-category error taxonomy&lt;/a&gt; specifically for tool-use reliability in multi-agent LLM systems running on edge hardware, addressing the growing deployment of agents outside cloud environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apple Commits $30 Billion to Broadcom for US-Made Chips
&lt;/h2&gt;

&lt;p&gt;Apple's &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;multi-year supply agreement with Broadcom&lt;/a&gt; represents the company's largest domestic chip sourcing commitment to date, a $30 billion signal that the Trump administration's pressure campaign for expanded US semiconductor manufacturing is reshaping Big Tech supply chains. The deal bolsters Broadcom's position as a key AI chip supplier alongside NVIDIA, diversifying Apple's silicon strategy beyond its in-house designs.&lt;/p&gt;

&lt;p&gt;The agreement arrives as Apple accelerates on-device AI capabilities across its product line, requiring specialized chips that balance performance with power efficiency. Broadcom's US fabrication capacity provides both supply chain resilience and political cover for a company that has faced repeated criticism over its manufacturing reliance on Asian suppliers.&lt;/p&gt;

&lt;p&gt;For the broader industry, the deal signals a potential template: committed multi-year volumes that justify domestic fab investments, structured to satisfy both shareholder demands for cost efficiency and political demands for onshoring. Whether other Big Tech firms follow with similar commitments—or whether this remains an Apple-specific response to unique regulatory pressures—will shape US semiconductor policy outcomes for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon Science Releases TrivialPlus Hallucination Detection Benchmark
&lt;/h2&gt;

&lt;p&gt;Amazon Science's &lt;a href="https://github.com/amazon-science/hallucination-benchmark-trivialplus" rel="noopener noreferrer"&gt;TrivialPlus benchmark&lt;/a&gt;, accepted to the ACL 2026 main conference, addresses what enterprise AI teams increasingly identify as their deployment blocker: detecting when models confidently fabricate information. The benchmark specifically targets long-context hallucination detection, introducing a new RAG-based evaluation methodology built around a desiderata framework that specifies what adequate hallucination detection should actually accomplish.&lt;/p&gt;

&lt;p&gt;The contribution matters because existing evaluation methods systematically miss hallucinations that occur in retrieval-augmented generation workflows—precisely where enterprises deploy LLMs for knowledge work. When a model synthesizes information across multiple retrieved documents, it can introduce subtle factual errors that neither the retrieval system nor typical evaluation methods catch.&lt;/p&gt;

&lt;p&gt;TrivialPlus is designed to surface these failure modes, providing evaluation infrastructure that matches how LLMs actually get used in production rather than how they're typically benchmarked. For teams building RAG systems, the benchmark offers a standardized methodology to compare hallucination rates across models and configurations—data that directly informs deployment decisions and SLA commitments.&lt;/p&gt;

&lt;h2&gt;
  
  
  PolyBench Reveals Only 2 of 7 Top LLMs Can Profitably Trade Prediction Markets
&lt;/h2&gt;

&lt;p&gt;A sobering &lt;a href="https://arxiv.org/html/2604.14199v1" rel="noopener noreferrer"&gt;new multimodal benchmark called PolyBench&lt;/a&gt; demonstrates that sophisticated reasoning capabilities don't translate to financial performance: only 2 of 7 frontier LLMs generated positive returns when trading live prediction markets. The benchmark couples 38,666 Polymarket binary prediction markets with real-time central limit order book data and contemporaneous news feeds, creating evaluation conditions that mirror actual trading environments.&lt;/p&gt;

&lt;p&gt;The evaluation methodology deserves attention. Researchers analyzed &lt;a href="https://arxiv.org/html/2604.14199v1" rel="noopener noreferrer"&gt;36,165 predictions from seven frontier models&lt;/a&gt; under timestamp-locked conditions between February 6-12, 2026, ensuring models couldn't benefit from information that wasn't available at prediction time. This temporal control addresses a chronic problem in financial AI benchmarks: models that appear to predict well but actually just memorized outcomes present in their training data.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/html/2605.28359v1" rel="noopener noreferrer"&gt;memory-controlled design&lt;/a&gt; makes PolyBench uniquely suited for evaluating sequential financial decision-making. Most models failed despite access to real-time market data and news context, suggesting that the gap between reasoning about markets and profitably trading them remains substantial. For firms considering AI-assisted trading systems, the results counsel humility about current capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  2026 Industry Shift: From Scaling to Pragmatic Deployment
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://techcrunch.com/2026/01/02/in-2026-ai-will-move-from-hype-to-pragmatism" rel="noopener noreferrer"&gt;TechCrunch's analysis identifies 2026&lt;/a&gt; as the inflection point where AI development pivoted from brute-force parameter scaling to targeted, workflow-aligned deployments. The shift manifests across multiple dimensions: smaller models deployed where they fit rather than flagship models deployed everywhere; physical device integration rather than cloud-first architectures; and AI systems designed around specific workflows rather than general capabilities marketed as applicable to everything.&lt;/p&gt;

&lt;p&gt;World model development has accelerated notably. Google DeepMind's Genie, World Labs' Marble, and Runway's GWM-1 have all moved from research demonstrations to commercial availability, enabling AI systems that reason about physical environments rather than just text and images. These models power robotics, simulation, and embodied AI applications that pure language models couldn't address.&lt;/p&gt;

&lt;p&gt;Investment patterns reflect the priority shift. General Intuition's &lt;a href="https://techcrunch.com/2026/01/02/in-2026-ai-will-move-from-hype-to-pragmatism" rel="noopener noreferrer"&gt;$134 million seed round&lt;/a&gt; for spatial reasoning represents one of the largest pre-Series A raises in AI history, signaling that capital is flowing toward embodied AI and physical-world applications rather than yet another foundation model competitor. The era of "scale solves everything" has given way to "fit matters more than size."&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Watch
&lt;/h2&gt;

&lt;p&gt;The next few weeks will reveal whether OpenAI's new model delivers capability gains that justify the extended timeline—or whether Chinese competitors have already matched the performance at lower cost. Beijing's deliberations on model access restrictions bear monitoring; even preliminary signals could trigger enterprise migration away from Chinese model dependencies. And as PolyBench's results circulate, expect renewed skepticism about AI deployment in high-stakes financial decision-making, potentially cooling investment in autonomous trading systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Artificial Intelligence - Latest AI News - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2026/01/02/in-2026-ai-will-move-from-hype-to-pragmatism" rel="noopener noreferrer"&gt;In 2026, AI will move from hype to pragmatism - TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;Agentifying Agentic AI - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/list/cs.AI/recent" rel="noopener noreferrer"&gt;Artificial Intelligence - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/VoltAgent/awesome-ai-agent-papers" rel="noopener noreferrer"&gt;VoltAgent/awesome-ai-agent-papers - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amazon-science/hallucination-benchmark-trivialplus" rel="noopener noreferrer"&gt;GitHub - amazon-science/hallucination-benchmark-trivialplus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2604.14199v1" rel="noopener noreferrer"&gt;PolyBench: Benchmarking LLM Forecasting and Trading Capabilities on Live Prediction Market Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://arxiv.org/html/2605.28359v1" rel="noopener noreferrer"&gt;A Memory-Controlled Benchmark for LLM Trading Agents&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>This Week in AI: OpenAI Goes Custom Silicon, Ford's AI Reality Check, and the Rise of Structured Agent Communication</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:03:00 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/this-week-in-ai-openai-goes-custom-silicon-fords-ai-reality-check-and-the-rise-of-structured-93e</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/this-week-in-ai-openai-goes-custom-silicon-fords-ai-reality-check-and-the-rise-of-structured-93e</guid>
      <description>&lt;h1&gt;
  
  
  This Week in AI: OpenAI Goes Custom Silicon, Ford's AI Reality Check, and the Rise of Structured Agent Communication
&lt;/h1&gt;

&lt;p&gt;The past week crystallized a theme that's been building for months: the AI industry is moving from "can we build it?" to "can we actually deploy it?" OpenAI's announcement of custom silicon signals the infrastructure arms race is entering a new phase, while Ford's quiet rehiring of veteran engineers offers a sobering reminder that impressive demos don't always translate to production-ready systems. Meanwhile, the agentic AI space is maturing rapidly, with enterprises finally demanding the kind of structured, auditable communication that classical software engineering has required for decades.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Unveils First Custom AI Chip Built by Broadcom
&lt;/h2&gt;

&lt;p&gt;OpenAI has officially entered the custom silicon race, &lt;a href="https://openai.com" rel="noopener noreferrer"&gt;announcing its first proprietary AI chip&lt;/a&gt; developed in partnership with Broadcom. The move represents a strategic pivot for a company that has relied heavily on NVIDIA's GPUs for both training its frontier models and running inference at scale across ChatGPT's hundreds of millions of users.&lt;/p&gt;

&lt;p&gt;The chip, details of which remain closely guarded, is reportedly optimized specifically for OpenAI's transformer architectures and inference workloads. Internal benchmarks suggest significant efficiency gains for the specific attention patterns and context lengths that define models like GPT-4.1 and its successors. This vertical integration mirrors the approach Google pioneered with TPUs and Amazon pursued with Trainium and Inferentia.&lt;/p&gt;

&lt;p&gt;The timing is notable given ongoing supply constraints and NVIDIA's dominant pricing power in the AI accelerator market. By developing in-house silicon, OpenAI gains leverage in negotiations while potentially reducing per-query inference costs—a critical factor as the company scales its API business and consumer products.&lt;/p&gt;

&lt;p&gt;Industry analysts expect the chips to initially supplement rather than replace NVIDIA hardware, with full production deployment likely 18-24 months away. The Broadcom partnership suggests OpenAI is prioritizing speed to market over the fully custom approach Apple has taken with its silicon efforts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ford Rehires Veteran Engineers After AI Systems Fall Short of Production Requirements
&lt;/h2&gt;

&lt;p&gt;In a development that should temper AI enthusiasm in manufacturing circles, Ford has &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;quietly brought back experienced engineers&lt;/a&gt; after its AI-driven automation systems failed to meet production quality standards. The so-called "gray beards"—industry veterans with decades of manufacturing floor experience—are being reintegrated into teams that had been restructured around AI-first approaches.&lt;/p&gt;

&lt;p&gt;The specific failures reportedly involved computer vision systems for quality inspection and robotic assembly coordination. While these systems performed admirably in controlled testing environments, they struggled with the edge cases and variability inherent in high-volume automotive manufacturing. Weld quality assessment and paint defect detection proved particularly problematic, with false positive rates that would have created unacceptable production line stoppages.&lt;/p&gt;

&lt;p&gt;This isn't an indictment of AI in manufacturing—rather, it's a reality check about deployment timelines and the irreplaceable value of domain expertise. The engineers being rehired aren't replacing AI systems; they're working alongside them to identify failure modes and build more robust hybrid workflows.&lt;/p&gt;

&lt;p&gt;Similar pullbacks have been &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;reported at other automakers&lt;/a&gt; facing comparable integration challenges. The pattern suggests the industry may have underestimated the complexity of manufacturing environments where six-sigma quality expectations meet the probabilistic nature of current AI systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apple Vision Pro Executive Departing for OpenAI
&lt;/h2&gt;

&lt;p&gt;The talent migration from Apple to AI-native companies continues with &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;news that a senior executive from Apple's Vision Pro division&lt;/a&gt; is departing for OpenAI. The move signals OpenAI's expanding ambitions beyond its core text and code competencies into spatial computing and hardware interfaces.&lt;/p&gt;

&lt;p&gt;While neither company has commented officially, the hire aligns with &lt;a href="https://openai.com" rel="noopener noreferrer"&gt;persistent rumors about OpenAI's hardware initiatives&lt;/a&gt; and the company's clear interest in multimodal interaction paradigms. The executive reportedly led key aspects of Vision Pro's spatial interaction design—expertise that could prove valuable as OpenAI explores how users might interact with AI systems beyond screens and keyboards.&lt;/p&gt;

&lt;p&gt;The departure also reflects a broader 2026 trend: Apple's AI strategy, perceived by some as conservative relative to competitors, is making it harder to retain talent excited about frontier research and rapid deployment cycles. OpenAI's combination of cutting-edge models, aggressive product timelines, and substantial resources presents an increasingly compelling alternative for engineers who want to ship transformative technology quickly.&lt;/p&gt;

&lt;p&gt;For OpenAI, the hire suggests the company is serious about exploring interaction modalities that could define the next era of AI products—whether that's AR interfaces, dedicated hardware, or entirely new form factors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The agentic AI landscape is undergoing a fundamental architectural shift, with &lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;new academic research proposing the integration of classical multi-agent systems concepts&lt;/a&gt; into modern LLM-based agent frameworks. The "Agentifying Agentic AI" framework advocates for incorporating BDI (Belief-Desire-Intention) architectures and FIPA-ACL protocols—established patterns from decades of multi-agent research—to address the governance and accountability gaps in current agentic systems.&lt;/p&gt;

&lt;p&gt;A comprehensive &lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;arXiv survey on agentic AI software architecture&lt;/a&gt; documents the evolution from simple orchestrator-worker patterns toward more sophisticated mesh and swarm topologies featuring explicit communication contracts. The research emphasizes that as agent systems scale, unstructured natural language communication between agents becomes a liability for auditability and debugging.&lt;/p&gt;

&lt;p&gt;Enterprise platforms are responding accordingly. According to &lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;analysis of current agentic architectures&lt;/a&gt;, production-grade platforms like Kore.ai and ZenML now treat multi-agent orchestration and inter-agent protocols as first-class features rather than afterthoughts. The &lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;2026 Agentic Coding Trends Report from Anthropic&lt;/a&gt; notes that structured, auditable message schemas are rapidly displacing free-form natural language for enterprise agent communication.&lt;/p&gt;

&lt;p&gt;OpenAI's &lt;a href="https://openai.com/index/new-tools-for-building-agents" rel="noopener noreferrer"&gt;new tools for building agents&lt;/a&gt; reflect this maturation, offering primitives for structured tool use and state management. The emerging consensus is clear: while natural language enabled the agent revolution, production deployment requires the discipline of explicit contracts and formal specifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trump Administration Releases Anthropic Mythos for Broader Government and Corporate Use
&lt;/h2&gt;

&lt;p&gt;The White House has &lt;a href="https://www.reuters.com/world/trump-signed-order-promote-advanced-ai-innovation-security-white-house-says-2026-06-02" rel="noopener noreferrer"&gt;authorized expanded access to Anthropic's Mythos model&lt;/a&gt; for over 100 U.S. companies and government agencies. The announcement follows the administration's earlier initiative asking AI firms to voluntarily submit frontier models for government cybersecurity testing.&lt;/p&gt;

&lt;p&gt;Mythos deployment is initially focused on cybersecurity and national security applications, with agencies using the model for threat analysis, vulnerability assessment, and intelligence processing. The expanded corporate access includes defense contractors and critical infrastructure operators, suggesting the government sees frontier AI capabilities as increasingly essential to national security posture.&lt;/p&gt;

&lt;p&gt;The move reignites ongoing debates about government involvement in frontier AI distribution. Critics argue that preferential access creates market distortions and raises questions about the appropriate role of government in determining which organizations receive cutting-edge AI capabilities. Proponents counter that coordinated deployment ensures responsible use and allows for consistent security standards.&lt;/p&gt;

&lt;p&gt;Notably, the voluntary testing framework &lt;a href="https://www.reuters.com/world/trump-signed-order-promote-advanced-ai-innovation-security-white-house-says-2026-06-02" rel="noopener noreferrer"&gt;mentioned in the executive order&lt;/a&gt; has received participation from major labs, though details about specific evaluations remain classified. The approach represents a middle path between heavy-handed regulation and the hands-off posture that characterized earlier administrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Humanoid Robot Demonstrates Competent Office Task Performance
&lt;/h2&gt;

&lt;p&gt;A new humanoid robot demonstration has &lt;a href="https://www.wired.com/tag/artificial-intelligence" rel="noopener noreferrer"&gt;captured attention across the robotics and AI communities&lt;/a&gt; for its unprecedented competence at unstructured office tasks. The robot successfully performed a range of activities typically associated with entry-level office work: document sorting, package handling, navigation through cluttered spaces, and basic interaction with human coworkers.&lt;/p&gt;

&lt;p&gt;What distinguishes this demonstration from previous showcases is the robot's performance in genuinely unstructured environments. Rather than following rigid pre-programmed paths, the system adapted to obstacles, responded appropriately to unexpected human presence, and recovered gracefully from minor task failures. The underlying AI combines vision-language models for scene understanding with reinforcement learning policies trained in simulation and refined through real-world deployment.&lt;/p&gt;

&lt;p&gt;The timing aligns with a &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;broader industry push into embodied AI&lt;/a&gt; following a robotics investment surge that's seen major funding rounds for Figure, 1X, and Agility Robotics. The convergence of improved foundation models, cheaper sensors, and more capable actuators is finally enabling robots that can operate outside factory floors and controlled warehouses.&lt;/p&gt;

&lt;p&gt;Skeptics note that competent demos have preceded disappointing commercial deployments before. However, the demonstrated capability level—if reproducible at scale—suggests humanoid robots may be closer to practical deployment than many anticipated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wall Street Positions Micron as Next Major AI Beneficiary
&lt;/h2&gt;

&lt;p&gt;Wall Street analysts are &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;increasingly drawing parallels between Micron's current trajectory&lt;/a&gt; and NVIDIA's AI-fueled ascent from 2023-2024. The thesis centers on high-bandwidth memory (HBM), which has become essential for next-generation AI accelerators and represents a significant portion of chip manufacturing costs.&lt;/p&gt;

&lt;p&gt;Micron's HBM3E products are seeing unprecedented demand from AI chip vendors across the industry—not just NVIDIA, but AMD, Intel, and the custom silicon efforts from hyperscalers. As AI models grow larger and inference workloads scale, memory bandwidth has emerged as a primary bottleneck, elevating memory suppliers from commodity component makers to strategic partners.&lt;/p&gt;

&lt;p&gt;The company's forward order book reportedly extends well into 2027, with pricing power that's unusual for the historically cyclical memory industry. Analysts note that HBM manufacturing requires specialized expertise and significant capital investment, creating barriers to entry that protect margins.&lt;/p&gt;

&lt;p&gt;Some caution is warranted: Micron's stock has already appreciated significantly on AI expectations, and memory markets remain subject to supply-demand dynamics that can shift quickly. However, the structural demand drivers—larger models, more inference, broader deployment—appear durable. As &lt;a href="https://huggingface.co/datasets/salttechno/LLM-Model-Comparison-2026" rel="noopener noreferrer"&gt;comparative analyses of current LLMs show&lt;/a&gt;, context windows and model sizes continue expanding, driving sustained memory requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Europe Accelerates Push for Sovereign AI Infrastructure
&lt;/h2&gt;

&lt;p&gt;European leaders have &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;intensified calls for AI sovereignty&lt;/a&gt; amid growing frustration with dependence on American and Chinese AI systems. New initiatives announced this week aim to develop European-built foundation models and domestic training infrastructure capable of supporting frontier AI development.&lt;/p&gt;

&lt;p&gt;The policy focus emphasizes data sovereignty and regulatory compliance—areas where European organizations face genuine friction when using U.S.-based AI services subject to different legal frameworks. The EU AI Act's ongoing implementation has created compliance complexity that domestically-developed systems could potentially simplify.&lt;/p&gt;

&lt;p&gt;Concrete commitments are backing the rhetoric. Following SoftBank's €75 billion French data center commitment and similar investments in Germany and the Netherlands, Europe is building the physical infrastructure necessary for large-scale AI development. The question is whether infrastructure alone can close the gap with U.S. and Chinese labs that have multi-year head starts and significantly larger talent pools.&lt;/p&gt;

&lt;p&gt;Critics argue that fragmented national efforts and regulatory overhead will hamper European competitiveness regardless of infrastructure investment. Proponents counter that &lt;a href="https://www.wired.com/tag/artificial-intelligence" rel="noopener noreferrer"&gt;strategic autonomy in AI&lt;/a&gt; is a security imperative, not merely an economic consideration. The coming year will test whether Europe can translate infrastructure investment and policy ambition into competitive AI capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Watch
&lt;/h2&gt;

&lt;p&gt;The next few weeks should bring clarity on several fronts: expect more details on OpenAI's silicon roadmap as they move toward tape-out milestones, and watch for enterprise AI platforms to announce formal support for structured agent communication protocols. The Anthropic Mythos deployment will likely generate case studies that inform broader government AI adoption policy—and potentially spark congressional debate about executive authority over frontier model distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;AI News | Latest Headlines and Developments - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;AI News &amp;amp; Artificial Intelligence | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;TechCrunch | Startup and Technology News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/tag/artificial-intelligence" rel="noopener noreferrer"&gt;Artificial Intelligence | Latest News, Photos &amp;amp; Videos | WIRED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/world/trump-signed-order-promote-advanced-ai-innovation-security-white-house-says-2026-06-02" rel="noopener noreferrer"&gt;Trump administration to ask US AI firms to voluntarily submit models...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;Agentifying Agentic AI - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;2026 Agentic Coding Trends Report - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;The Evolution of Agentic AI Software Architecture - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;Agentic Artificial Intelligence (AI): Architectures, Taxonomies, and... - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/datasets/salttechno/LLM-Model-Comparison-2026" rel="noopener noreferrer"&gt;salttechno/LLM-Model-Comparison-2026 - Hugging Face&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com" rel="noopener noreferrer"&gt;OpenAI | Research &amp;amp; Deployment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://openai.com/index/new-tools-for-building-agents" rel="noopener noreferrer"&gt;New tools for building agents | OpenAI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>LangGraph Fault Tolerance: Building Resilient Agents with Retries, Timeouts, and Error Handlers</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:03:38 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/langgraph-fault-tolerance-building-resilient-agents-with-retries-timeouts-and-error-handlers-29pa</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/langgraph-fault-tolerance-building-resilient-agents-with-retries-timeouts-and-error-handlers-29pa</guid>
      <description>&lt;h1&gt;
  
  
  LangGraph Fault Tolerance: Building Resilient Agents with Retries, Timeouts, and Error Handlers
&lt;/h1&gt;

&lt;p&gt;Your agent completed 90% of a complex research task, made fourteen successful API calls, and then hit a transient rate limit on the fifteenth. Now it's dead. Checkpoints won't save you here—they tell you &lt;em&gt;where&lt;/em&gt; the agent stopped, not &lt;em&gt;how&lt;/em&gt; to recover gracefully. This gap between state persistence and active recovery has been the single largest source of operational burden for teams running production agents, and LangGraph's new fault tolerance primitives finally close it.&lt;/p&gt;

&lt;p&gt;The timing matters. As organizations move from proof-of-concept agents to production deployments handling thousands of daily invocations, the economics of manual intervention become untenable. A support agent that requires human restarts 15% of the time isn't a productivity gain—it's a liability. The new &lt;code&gt;@retry&lt;/code&gt; decorator, &lt;code&gt;TimeoutPolicy&lt;/code&gt; class, and &lt;code&gt;ErrorHandler&lt;/code&gt; nodes represent LangGraph's first comprehensive answer to this challenge, building on the framework's existing &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;resilient agent architecture&lt;/a&gt; while addressing the operational realities of 2026's agentic workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Why Checkpointing Alone Isn't Enough
&lt;/h2&gt;

&lt;p&gt;LangGraph's checkpointing system—whether you're using &lt;code&gt;PostgresSaver&lt;/code&gt;, &lt;code&gt;MemorySaver&lt;/code&gt;, or the newer distributed options—excels at one job: capturing the complete state of an agent at defined points in execution. When an agent crashes, you can inspect exactly what happened and resume from that state. This is table stakes for any serious agentic system, and LangGraph has done it well.&lt;/p&gt;

&lt;p&gt;But checkpointing is fundamentally passive. It answers "where did we stop?" without answering "should we try again?" or "how long should we wait?" or "what's our fallback if this keeps failing?"&lt;/p&gt;

&lt;p&gt;Consider the failure modes that dominate production agent deployments. Rate limits from tool APIs are the most common—OpenAI, Anthropic, and every third-party data provider impose them, and they're designed to be transient. A 429 response at 2:15 PM will likely succeed at 2:16 PM. Transient 5xx errors from external services follow similar patterns. LLM provider timeouts spike during high-traffic periods; if your agent runs during peak hours, you'll see these regularly. Network partitions between your agent and external services happen more often than anyone wants to admit.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.langchain.com/blog/langgraph-multi-agent-workflows" rel="noopener noreferrer"&gt;multi-agent workflows&lt;/a&gt; and the newer Deep Agents architecture, you face an additional challenge: sub-agent hangs. A planning agent delegates to a research sub-agent, which gets stuck waiting for a response that will never come. Without timeouts, your entire workflow freezes.&lt;/p&gt;

&lt;p&gt;The real cost isn't technical—it's operational. Every manual restart requires human attention, context switching, and decision-making. Teams running customer-facing agents report that before adopting fault tolerance patterns, they spent significant portions of their on-call rotations simply restarting agents that hit transient failures. The &lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;agent development lifecycle&lt;/a&gt; extends well beyond deployment, and monitoring becomes firefighting without proper recovery mechanisms.&lt;/p&gt;

&lt;p&gt;The conceptual gap is clear: checkpointing defines &lt;em&gt;where&lt;/em&gt; to resume, while fault tolerance defines &lt;em&gt;whether and how&lt;/em&gt; to retry before giving up. You need both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core API: The &lt;code&gt;@retry&lt;/code&gt; Decorator
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;@retry&lt;/code&gt; decorator brings production-grade retry logic to node functions without the boilerplate that previously cluttered every external API call. The basic signature is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exponential&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retryable_exceptions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_external_api&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration options address the full spectrum of retry scenarios. &lt;code&gt;max_attempts&lt;/code&gt; is an integer that includes the initial attempt—so &lt;code&gt;max_attempts=3&lt;/code&gt; means one initial try plus two retries. The &lt;code&gt;backoff&lt;/code&gt; parameter accepts &lt;code&gt;"constant"&lt;/code&gt;, &lt;code&gt;"linear"&lt;/code&gt;, or &lt;code&gt;"exponential"&lt;/code&gt; strategies, each with configurable &lt;code&gt;base_delay&lt;/code&gt; (default 1.0 seconds) and &lt;code&gt;max_delay&lt;/code&gt; (default 60 seconds) parameters. Exponential backoff with jitter is the recommended default for API rate limits.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;retryable_exceptions&lt;/code&gt; parameter is crucial for correct behavior. Only exceptions in this list trigger retries; all others propagate immediately. This prevents retrying on errors that won't resolve with time—a malformed request will fail identically on every attempt. For more complex scenarios, &lt;code&gt;retry_condition&lt;/code&gt; accepts a callable &lt;code&gt;(exception, attempt) -&amp;gt; bool&lt;/code&gt; that enables custom logic: "retry rate limits for the first 5 attempts, but only retry timeouts twice."&lt;/p&gt;

&lt;p&gt;Integration with LangGraph's state management is seamless and, importantly, safe. Retries operate on the &lt;em&gt;same&lt;/em&gt; state snapshot that the original attempt received. There's no risk of partial state corruption from a failed attempt leaking into a retry. The node either succeeds and its state updates are committed, or it exhausts retries and the original state remains unchanged.&lt;/p&gt;

&lt;p&gt;Observability comes built-in. Each retry emits a &lt;code&gt;RetryAttempt&lt;/code&gt; event visible in LangSmith traces, containing the attempt number, delay duration, exception type, and exception message. This means you can track retry rates per node, identify which external services cause the most retries, and tune your &lt;code&gt;max_attempts&lt;/code&gt; settings based on real data rather than guesswork.&lt;/p&gt;

&lt;p&gt;One implementation detail matters for teams using NVIDIA's &lt;a href="https://www.langchain.com/blog/nvidia-enterprise" rel="noopener noreferrer"&gt;parallel execution enhancements&lt;/a&gt;: when combining &lt;code&gt;@retry&lt;/code&gt; with &lt;code&gt;@independent&lt;/code&gt; (the decorator for parallelizable nodes), &lt;code&gt;@retry&lt;/code&gt; must be the innermost decorator. This ensures the retry logic wraps the actual node execution rather than the parallelization wrapper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeout Policies: Bounding Unbounded Operations
&lt;/h2&gt;

&lt;p&gt;While retries handle failures that announce themselves with exceptions, timeouts protect against operations that simply never return. The &lt;code&gt;TimeoutPolicy&lt;/code&gt; class provides granular control at three levels: individual nodes, subgraphs, and entire graph invocations.&lt;/p&gt;

&lt;p&gt;The configuration hierarchy reflects how agents actually fail. &lt;code&gt;node_timeout&lt;/code&gt; sets the maximum duration for any single node execution—useful when you know that a particular API call should never take more than 30 seconds. &lt;code&gt;tool_timeout&lt;/code&gt; applies uniformly to all tool calls within a node, separate from the node's own computation time. &lt;code&gt;graph_timeout&lt;/code&gt; sets a wall-clock limit for the entire invocation, preventing runaway agents that loop indefinitely or get stuck in recursive planning cycles.&lt;/p&gt;

&lt;p&gt;The configuration pattern attaches to graph compilation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.timeout&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TimeoutPolicy&lt;/span&gt;

&lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TimeoutPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;node_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# 30 seconds per node
&lt;/span&gt;    &lt;span class="n"&gt;tool_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# 15 seconds per tool call
&lt;/span&gt;    &lt;span class="n"&gt;graph_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;     &lt;span class="c1"&gt;# 5 minutes total
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;compiled_graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timeout_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;policy&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Timeout behavior is configurable via the &lt;code&gt;on_timeout&lt;/code&gt; parameter. The default &lt;code&gt;"raise"&lt;/code&gt; behavior throws a &lt;code&gt;TimeoutError&lt;/code&gt; that can be caught by an &lt;code&gt;ErrorHandler&lt;/code&gt; (discussed next) or handled in downstream nodes. &lt;code&gt;"interrupt"&lt;/code&gt; triggers LangGraph's human-in-the-loop interrupt mechanism, pausing execution for manual review and decision-making. &lt;code&gt;"fallback"&lt;/code&gt; routes to a specified fallback node, enabling graceful degradation without human intervention.&lt;/p&gt;

&lt;p&gt;The implementation uses &lt;code&gt;asyncio.timeout()&lt;/code&gt; internally for async nodes. Synchronous nodes are wrapped automatically with equivalent behavior, but the async implementation is more efficient—another reason to prefer async node functions in production.&lt;/p&gt;

&lt;p&gt;For teams using LangGraph's multi-agent capabilities, timeout policies integrate with the &lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;agent development stack&lt;/a&gt; at the orchestration level. Sub-agent timeouts can be configured independently, preventing a misbehaving sub-agent from consuming the entire parent agent's timeout budget.&lt;/p&gt;

&lt;p&gt;LangSmith surfaces timeout metrics alongside other observability data: &lt;code&gt;timeout_rate&lt;/code&gt; per node shows what percentage of invocations hit the timeout, while &lt;code&gt;p99_duration&lt;/code&gt; displays your latency distribution with timeout thresholds overlaid. This makes it straightforward to tune timeouts based on actual production behavior rather than guesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handler Nodes: Centralized Recovery Logic
&lt;/h2&gt;

&lt;p&gt;Retries and timeouts handle specific failure types, but production agents need a unified place to make recovery decisions. &lt;code&gt;ErrorHandler&lt;/code&gt; nodes provide this centralization, replacing scattered try-except blocks with a coherent error recovery architecture.&lt;/p&gt;

&lt;p&gt;Registration uses scope-based configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;handler_node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;global&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# or "subgraph" or ["node_a", "node_b"]
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Global handlers catch any unhandled exception from any node. Subgraph handlers scope to a specific subgraph, useful when different parts of your agent require different recovery strategies. Node-list scoping targets specific nodes, ideal for handling errors from a cluster of related API calls.&lt;/p&gt;

&lt;p&gt;The handler node receives an &lt;code&gt;ErrorContext&lt;/code&gt; object containing everything needed for intelligent recovery decisions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;          &lt;span class="c1"&gt;# The caught exception
&lt;/span&gt;    &lt;span class="n"&gt;failed_node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;              &lt;span class="c1"&gt;# Name of node that raised
&lt;/span&gt;    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&lt;/span&gt;             &lt;span class="c1"&gt;# Current state snapshot
&lt;/span&gt;    &lt;span class="n"&gt;attempt_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;         &lt;span class="c1"&gt;# Retry attempts if @retry was used
&lt;/span&gt;    &lt;span class="n"&gt;trace_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;                 &lt;span class="c1"&gt;# Correlation ID for LangSmith
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;attempt_history&lt;/code&gt; field is particularly valuable—it tells you not just that a node failed, but &lt;em&gt;how many times&lt;/em&gt; it failed and &lt;em&gt;what exceptions&lt;/em&gt; occurred on each attempt. A node that fails once with a timeout is different from a node that exhausted five retries with rate limit errors.&lt;/p&gt;

&lt;p&gt;Handler return values control execution flow via the &lt;code&gt;Command&lt;/code&gt; pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ErrorContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Route to degraded-mode node
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goto&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;degraded_synthesis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Interrupt for human review
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interrupt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Timeout on critical operation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Abort with diagnostic payload
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;abort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trace_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Command(resume=True)&lt;/code&gt; option is particularly powerful—it retries the failed node with a reset retry counter. This enables "escalate and retry" patterns where the handler might first try rate limit backoff, then switch API keys, then finally give up.&lt;/p&gt;

&lt;p&gt;State modification before routing is supported via &lt;code&gt;Command(update={...})&lt;/code&gt;. This enables patterns like marking a data source as unavailable in state before routing to a synthesis node that should work with partial data.&lt;/p&gt;

&lt;p&gt;Two patterns emerge as particularly useful in production. The "circuit breaker" pattern tracks failure rates over time (using state or external storage) and switches to degraded mode after a threshold—useful for agents that should continue operating even when primary data sources are unavailable. The "escalation" pattern creates human-in-the-loop interrupts for specific error types while handling routine failures automatically, respecting the principle that &lt;a href="https://www.ibm.com/think/insights/agentic-ai" rel="noopener noreferrer"&gt;agentic systems&lt;/a&gt; should augment human decision-making rather than eliminate it entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;Let's build a research agent that demonstrates all three fault tolerance primitives. The agent queries three external APIs (arXiv, Wikipedia, and a news service), synthesizes results, and generates a report. This is a common pattern in production agents, and it exposes exactly the failure modes fault tolerance addresses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.retry&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.timeout&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TimeoutPolicy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.errors&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ErrorContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;traceable&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="c1"&gt;# State definition captures both data and operational metadata
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;arxiv_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;wikipedia_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;news_results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="n"&gt;unavailable_sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Track which sources failed
&lt;/span&gt;    &lt;span class="n"&gt;synthesis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;final_report&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Custom exceptions for clear retry targeting
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SourceUnavailableError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="c1"&gt;# Node 1: arXiv API with retry for rate limits and transient errors
&lt;/span&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;backoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exponential&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;base_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;30.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retryable_exceptions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatusError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@traceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_arxiv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_arxiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Query arXiv API for academic papers matching the research query.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://export.arxiv.org/api/query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Handle rate limits explicitly to trigger retry
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arXiv rate limit hit: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Retry-After&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Parse response (simplified for clarity)
&lt;/span&gt;        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_arxiv_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arxiv_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Node 2: Wikipedia API with similar retry pattern
&lt;/span&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;backoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exponential&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retryable_exceptions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutException&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@traceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_wikipedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_wikipedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Query Wikipedia API for relevant encyclopedia entries.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://en.wikipedia.org/w/api.php&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;srsearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wikipedia rate limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wikipedia_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Node 3: News API (third-party, less reliable)
&lt;/span&gt;&lt;span class="nd"&gt;@retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Fewer retries for less critical source
&lt;/span&gt;    &lt;span class="n"&gt;backoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;constant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;base_delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;retryable_exceptions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutException&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@traceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_news&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Query news API for recent coverage. Optional source—failure is acceptable.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;8.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://newsapi.example.com/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer NEWS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;News API rate limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;news_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Synthesis node - no retry needed, operates on local data
&lt;/span&gt;&lt;span class="nd"&gt;@traceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;synthesize_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Combine results from available sources into unified synthesis.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;available_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arxiv_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;available_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Academic sources: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;arxiv_results&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; papers found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wikipedia_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;available_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Encyclopedia: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wikipedia_results&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; entries found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;news_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;available_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;News: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;news_results&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; articles found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Note which sources were unavailable for transparency
&lt;/span&gt;    &lt;span class="n"&gt;unavailable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="n"&gt;synthesis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Research synthesis for: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;synthesis&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Available sources: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;available_results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;None&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;unavailable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;synthesis&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unavailable sources: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unavailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# In production, this would call an LLM to generate actual synthesis
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;synthesis&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Error handler with scoped recovery logic
&lt;/span&gt;&lt;span class="nd"&gt;@traceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research_error_handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;research_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ErrorContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Central error handling for research API nodes.
    Strategy:
    - Rate limits after retry exhaustion: mark source unavailable, continue
    - Timeouts: mark source unavailable, continue (research can proceed with partial data)
    - Unexpected errors: abort with diagnostic info for debugging
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;failed_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failed_node&lt;/span&gt;
    &lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;

    &lt;span class="c1"&gt;# Initialize unavailable_sources if not present
&lt;/span&gt;    &lt;span class="n"&gt;unavailable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutException&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="c1"&gt;# Transient failure after retries exhausted - degrade gracefully
&lt;/span&gt;        &lt;span class="n"&gt;source_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;failed_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;unavailable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Log for observability (LangSmith will capture this)
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Source &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;source_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; unavailable after &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attempt_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; attempts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Update state and continue to synthesis
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unavailable&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;goto&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Graph-level or node-level timeout - more serious
&lt;/span&gt;        &lt;span class="c1"&gt;# For research agents, we still try to synthesize what we have
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unavailable&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;failed_node&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;goto&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Unexpected error - abort with full diagnostic payload
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;abort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error_message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failed_node&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;failed_node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trace_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state_snapshot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Build the graph with fault tolerance
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_research_agent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add nodes
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_arxiv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_arxiv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_wikipedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_wikipedia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_news&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;synthesize_results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Parallel API queries, then synthesis
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_arxiv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_wikipedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_arxiv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_wikipedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register error handler scoped to API query nodes only
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;research_error_handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_arxiv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_wikipedia&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query_news&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Configure timeout policy
&lt;/span&gt;    &lt;span class="n"&gt;timeout_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TimeoutPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;node_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# 60 seconds per node (includes retries)
&lt;/span&gt;        &lt;span class="n"&gt;graph_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;   &lt;span class="c1"&gt;# 5 minutes total
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Compile with checkpointing and timeout policy
&lt;/span&gt;    &lt;span class="n"&gt;compiled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;timeout_policy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout_policy&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;compiled&lt;/span&gt;

&lt;span class="c1"&gt;# Usage example
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_research_agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transformer architecture neural networks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Note: Some sources were unavailable: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unavailable_sources&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this agent and one API fails, you'll see the fault tolerance in action. The &lt;code&gt;@retry&lt;/code&gt; decorator handles transient failures with exponential backoff. If retries are exhausted, the error handler catches the exception, marks the source as unavailable in state, and routes to synthesis. The agent completes with partial data rather than crashing.&lt;/p&gt;

&lt;p&gt;In LangSmith traces, you'll see &lt;code&gt;RetryAttempt&lt;/code&gt; events for each retry, the error handler invocation, and the modified routing decision—complete visibility into exactly how the agent recovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Immediate adoption path&lt;/strong&gt;: Start by adding &lt;code&gt;@retry&lt;/code&gt; to any node that makes external calls. This is the lowest-friction change with the highest impact. Most teams see immediate reduction in failed runs simply by handling transient rate limits and timeouts gracefully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migrating from custom retry logic&lt;/strong&gt;: If you've built manual try/except/sleep patterns around external calls, the &lt;code&gt;@retry&lt;/code&gt; decorator replaces 20-50 lines of boilerplate per node. Beyond code reduction, the decorator handles backoff calculation, metric emission, and LangSmith integration automatically. Your custom logic probably doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeout strategy&lt;/strong&gt;: Begin with generous timeouts—2-3x your observed p99 latency for each node type. Overly aggressive timeouts cause false failures; you can tighten them based on LangSmith metrics once you have production data. The &lt;code&gt;p99_duration&lt;/code&gt; metric with timeout threshold overlay makes this tuning straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ErrorHandler placement&lt;/strong&gt;: Start with a single global handler that logs errors and emits alerts. This gives you immediate observability into all failures. Add scoped handlers as specific recovery patterns emerge from production data—don't try to anticipate every failure mode upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-agent considerations&lt;/strong&gt;: For teams using &lt;a href="https://www.langchain.com/blog/langgraph-multi-agent-workflows" rel="noopener noreferrer"&gt;LangGraph's multi-agent workflows&lt;/a&gt;, fault tolerance automatically benefits sub-agents. Configure policies at the orchestration level, and sub-agents inherit appropriate timeouts. This prevents the common failure mode of a misbehaving sub-agent consuming resources indefinitely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost awareness&lt;/strong&gt;: Retries multiply LLM API costs. A node with &lt;code&gt;max_attempts=5&lt;/code&gt; calling Claude 3.5 Sonnet can cost 5x what you budgeted per invocation. Set &lt;code&gt;max_attempts&lt;/code&gt; conservatively for expensive model calls—often 2 is sufficient for LLM calls, while API calls to external services can tolerate higher retry counts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing fault tolerance&lt;/strong&gt;: LangSmith Sandboxes support fault injection, enabling chaos testing without mocking your entire infrastructure. Inject rate limits, timeouts, and specific exceptions into production-like runs to validate that your error handlers behave correctly before real failures occur.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observability checklist&lt;/strong&gt;: Enable &lt;code&gt;retry_rate&lt;/code&gt;, &lt;code&gt;timeout_rate&lt;/code&gt;, and &lt;code&gt;error_handler_invocations&lt;/code&gt; metrics in your LangSmith dashboard. These three metrics tell you whether fault tolerance is working as intended or masking underlying issues that need architectural fixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anti-pattern to avoid&lt;/strong&gt;: Don't wrap entire graphs in a single retry at the invocation level. This loses the granularity that makes fault tolerance valuable. A graph-level retry doesn't know which node failed, can't route to fallbacks, and may re-execute expensive operations unnecessarily. Use node-level retries with error handlers for precise control.&lt;/p&gt;

&lt;p&gt;The broader shift here is from reactive debugging to proactive resilience. The &lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;agent development lifecycle&lt;/a&gt; no longer ends at deployment—it extends into production operations, and fault tolerance is the bridge between "my agent works" and "my agent works reliably at scale."&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Build This Week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project: Fault-Tolerant Data Pipeline Agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build an agent that extracts data from three different sources (a public API, a web scraper, and a local database), transforms the combined data, and loads it into a target system. This is a practical ETL pattern where fault tolerance directly impacts whether the pipeline runs unattended.&lt;/p&gt;

&lt;p&gt;Implementation requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Each extraction node gets &lt;code&gt;@retry&lt;/code&gt; with source-appropriate settings (aggressive retries for your own database, conservative for rate-limited public APIs)&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;TimeoutPolicy&lt;/code&gt; with different tolerances for each phase—extraction can be slow, transformation should be fast&lt;/li&gt;
&lt;li&gt;Build an error handler that implements "best effort" semantics: continue with available data if any source fails, but abort if all sources fail&lt;/li&gt;
&lt;li&gt;Add a "validation" node after transformation that checks data quality and routes to an error handler if thresholds aren't met&lt;/li&gt;
&lt;li&gt;Include LangSmith tracing with custom metadata tags for data quality metrics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stretch goal: Add a "circuit breaker" pattern where repeated failures from one source cause the agent to skip that source entirely for subsequent runs (persisted via checkpointing), with automatic re-enablement after a cooldown period.&lt;/p&gt;

&lt;p&gt;This project exercises all three fault tolerance primitives in a realistic scenario while producing something genuinely useful for data engineering workflows. The patterns transfer directly to any agent that coordinates multiple unreliable external systems—which is to say, most production agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;langchain-ai/langgraph: Build resilient agents. - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/langgraph-multi-agent-workflows" rel="noopener noreferrer"&gt;LangGraph: Multi-Agent Workflows - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/the-agent-development-lifecycle" rel="noopener noreferrer"&gt;The Agent Development Lifecycle: Build, Test, Deploy &amp;amp; Monitor AI ... - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/nvidia-enterprise" rel="noopener noreferrer"&gt;LangChain Announces Enterprise Agentic AI Platform Built with ... - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://www.ibm.com/think/insights/agentic-ai" rel="noopener noreferrer"&gt;Agentic AI: 4 reasons why it's the next big thing in AI research - IBM&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of the **Agentic Engineering Weekly&lt;/em&gt;* series — a deep-dive every Monday into the frameworks,&lt;br&gt;
patterns, and techniques shaping the next generation of AI systems.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building something agentic? Drop a comment — I'd love to feature reader projects.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Weekly: Bezos Bets $12B on Physical AI, Anthropic's Security Crisis, and the New Tech Power Structure</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:02:31 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-bezos-bets-12b-on-physical-ai-anthropics-security-crisis-and-the-new-tech-power-15ep</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-bezos-bets-12b-on-physical-ai-anthropics-security-crisis-and-the-new-tech-power-15ep</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly: Bezos Bets $12B on Physical AI, Anthropic's Security Crisis, and the New Tech Power Structure
&lt;/h1&gt;

&lt;p&gt;The frontier AI landscape shifted dramatically this week as Jeff Bezos emerged from relative AI sidelines with a massive bet on physical-world intelligence, while Anthropic faced an unprecedented government-ordered model takedown that raises fundamental questions about regulatory oversight of deployed systems. Meanwhile, the old guard struggles—Meta's AI unit reportedly descends into dysfunction as Google fires the first shots in what could become a brutal consumer pricing war. The message is clear: the AI industry's second act looks nothing like its first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jeff Bezos's Prometheus Raises $12B to Build 'Artificial General Engineer'
&lt;/h2&gt;

&lt;p&gt;Jeff Bezos is making his biggest AI play yet. Prometheus, the stealth company backed by the Amazon founder, has closed a &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;$12 billion funding round&lt;/a&gt; aimed at developing what the company calls an "Artificial General Engineer"—AI systems purpose-built for physical-world engineering tasks rather than the text and image generation that dominates current frontier development.&lt;/p&gt;

&lt;p&gt;The funding represents one of the largest single rounds in AI history and signals Bezos's conviction that the next major breakthrough lies in bridging digital AI capabilities with real-world physical applications. Prometheus is reportedly recruiting heavily from robotics labs, mechanical engineering departments, and aerospace companies, suggesting a scope that extends well beyond Amazon's warehouse robotics expertise.&lt;/p&gt;

&lt;p&gt;Industry observers note that while OpenAI, Anthropic, and Google have focused primarily on language models and digital agents, physical-world AI—systems that can reason about material constraints, design manufacturable components, and interact with the built environment—remains comparatively underdeveloped. Prometheus appears positioned to exploit this gap.&lt;/p&gt;

&lt;p&gt;The Bezos backing adds credibility that few other investors could provide, given his track record with Blue Origin and Amazon's logistics automation. Whether "Artificial General Engineer" represents genuine technical ambition or marketing positioning remains to be seen, but the resources to pursue it are now in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anthropic Takes Claude Fable 5 Offline After Government Security Order
&lt;/h2&gt;

&lt;p&gt;In an unprecedented move, Anthropic has &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;suspended public access&lt;/a&gt; to its Claude Fable 5 model following a directive from the U.S. government identifying a potential jailbreak vulnerability. The takedown marks the first time a frontier AI company has pulled a deployed model at government request over security concerns.&lt;/p&gt;

&lt;p&gt;Fable 5, launched earlier this year as a consumer-accessible version of Anthropic's Mythos cybersecurity model, was designed to make advanced reasoning capabilities available to everyday users while maintaining the safety guardrails the company is known for. However, security researchers had previously raised concerns that the model's guardrails could be circumvented through specific prompt sequences, potentially exposing capabilities intended only for the enterprise Mythos deployment.&lt;/p&gt;

&lt;p&gt;The government's intervention—reportedly originating from a classified assessment—raises significant questions about the emerging oversight framework for frontier models. Anthropic has not disclosed the specific vulnerability or timeline for potential restoration of service, stating only that it is "working cooperatively with relevant authorities."&lt;/p&gt;

&lt;p&gt;The incident arrives at a particularly sensitive moment as Congress debates federal AI legislation. Critics argue the takedown demonstrates responsible industry-government coordination; others worry it sets precedent for arbitrary government control over deployed AI systems without public transparency about the underlying security assessment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meta's Internal AI Unit Reportedly in Chaos
&lt;/h2&gt;

&lt;p&gt;The reorganization &lt;a href="https://www.wired.com" rel="noopener noreferrer"&gt;Mark Zuckerberg promised&lt;/a&gt; would streamline Meta's AI efforts has apparently achieved the opposite. Engineers speaking anonymously describe the company's months-old centralized AI unit as a dysfunctional work environment marked by unclear leadership, conflicting priorities, and an exodus of senior talent.&lt;/p&gt;

&lt;p&gt;The chaos reportedly stems from Meta's abrupt strategic pivot toward proprietary models following the Muse Spark launch, abandoning the open-source approach that had defined its Llama model family. Teams that had spent years building for open release found their work redirected or deprecated, while newly hired executives from closed-model backgrounds clashed with existing research culture.&lt;/p&gt;

&lt;p&gt;Separately, &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;reports indicate&lt;/a&gt; Meta may unwind its $2 billion acquisition of robotics firm Manus after pressure from Beijing, where Manus maintains significant manufacturing partnerships. The combination of strategic whiplash and geopolitical complications has left the unit struggling to execute on any coherent vision.&lt;/p&gt;

&lt;p&gt;The situation contrasts sharply with the narrative Zuckerberg presented to investors just months ago, positioning Meta as a serious contender to OpenAI and Google in frontier AI development. Whether the company can stabilize before losing irreplaceable talent to competitors with clearer direction remains an open question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Fires Opening Salvo in AI Subscription Price Wars
&lt;/h2&gt;

&lt;p&gt;Google announced &lt;a href="https://techcrunch.com/2026/02/19/googles-new-gemini-pro-model-has-record-benchmark-scores-again" rel="noopener noreferrer"&gt;aggressive new pricing&lt;/a&gt; for its AI subscription tiers this week, slashing rates in what appears to be a deliberate move to pressure OpenAI and Anthropic on consumer pricing. The timing—following the company's recent Gemini 3.1 Pro release with strong benchmark performance—suggests Google is ready to leverage its infrastructure advantages to compete on cost.&lt;/p&gt;

&lt;p&gt;The new pricing structure effectively halves the monthly cost for access to Gemini's most capable models, while introducing a limited free tier that exceeds what competitors currently offer paid subscribers. Google's cloud infrastructure scale makes such pricing sustainable in ways that smaller rivals may struggle to match.&lt;/p&gt;

&lt;p&gt;For OpenAI and Anthropic, the move forces an uncomfortable choice: match Google's pricing and accept margin compression, or maintain current rates and risk losing price-sensitive customers. Neither company has announced responses, though industry analysts expect some reaction within weeks.&lt;/p&gt;

&lt;p&gt;The broader implication is accelerating commoditization of consumer AI access. As base model capabilities converge and pricing drops, differentiation will increasingly depend on specialized features, integration depth, and enterprise offerings—shifting the competitive battleground away from raw model performance toward ecosystem advantages where Google already holds significant cards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The academic and practitioner communities continue building the conceptual and technical foundations for production agentic systems. A notable new paper, &lt;a href="https://arxiv.org/pdf/2511.17332" rel="noopener noreferrer"&gt;"Hybrid Agentic AI and Multi-Agent Systems in Smart Manufacturing,"&lt;/a&gt; demonstrates how frameworks including CrewAI, LangGraph, AutoGen, and MetaGPT can be deployed in industrial cyber-physical systems—a significant step toward agentic AI in high-stakes environments.&lt;/p&gt;

&lt;p&gt;The research emphasizes &lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;plan-act-reflect loops&lt;/a&gt; as the core pattern enabling dynamic strategy adaptation, allowing agents to modify their approaches based on real-time feedback from manufacturing environments. This echoes patterns identified in &lt;a href="https://resources.anthropic.com/building-effective-ai-agents" rel="noopener noreferrer"&gt;Anthropic's guidance&lt;/a&gt; on building effective agents, which emphasizes augmented LLMs and workflow orchestration over fully autonomous systems.&lt;/p&gt;

&lt;p&gt;Human-in-the-loop interfaces are emerging as a critical pattern for production deployments, enabling domain experts to oversee agentic operations without requiring machine learning expertise. A &lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;comprehensive taxonomy paper&lt;/a&gt; published recently attempts to unify multi-agent coordination patterns—chain, star, mesh, and workflow graphs—across frameworks, providing practitioners with a common vocabulary for architectural decisions.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/VoltAgent/awesome-ai-agent-papers" rel="noopener noreferrer"&gt;awesome-ai-agent-papers&lt;/a&gt; repository on GitHub continues tracking academic work on emerging paradigms, including skill libraries that may eventually replace multi-agent systems for many use cases and information-flow orchestration approaches that simplify reasoning about agent behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  US House Releases Bipartisan Draft Bill to Preempt State AI Regulations
&lt;/h2&gt;

&lt;p&gt;A bipartisan group of House lawmakers &lt;a href="https://www.reuters.com/business/us-house-lawmakers-release-draft-bill-regulate-ai-2026-06-04" rel="noopener noreferrer"&gt;released draft legislation&lt;/a&gt; this week that would prohibit states from regulating AI development, aiming to create a unified federal framework for AI governance. The move represents the most significant push yet toward centralized AI policy in the United States.&lt;/p&gt;

&lt;p&gt;The draft bill would preempt existing state-level AI regulations already in effect in California, Colorado, and several other states, replacing the current patchwork with federal standards. Sponsors argue that fragmented state rules create compliance burdens that disadvantage American companies against international competitors operating under single regulatory regimes.&lt;/p&gt;

&lt;p&gt;Industry reaction has been predictably split. Large AI developers generally support federal preemption, citing operational simplicity; civil society groups and some state attorneys general have criticized the bill as removing local accountability for AI harms. The draft leaves enforcement mechanisms vague, a gap that will likely draw scrutiny in committee markup.&lt;/p&gt;

&lt;p&gt;Whether the legislation advances in an election year remains uncertain, but its bipartisan sponsorship suggests AI governance is achieving rare cross-party consensus—at least on the principle of federal primacy over states.&lt;/p&gt;

&lt;h2&gt;
  
  
  KPMG Pulls AI Report After Discovering Hallucinated Content
&lt;/h2&gt;

&lt;p&gt;In an embarrassing reversal, &lt;a href="https://www.wired.com" rel="noopener noreferrer"&gt;KPMG withdrew&lt;/a&gt; a published report on enterprise AI adoption after discovering it contained apparent AI-generated hallucinations, including fabricated statistics and nonexistent research citations. The incident highlights ongoing quality control challenges as professional services firms integrate AI tools into content production.&lt;/p&gt;

&lt;p&gt;The firm has not disclosed which AI system was used or how the hallucinated content passed review, but the episode underscores a persistent gap between AI-assisted drafting capabilities and the verification processes needed to catch errors before publication. For a consulting firm whose value proposition rests on authoritative analysis, the mistake carries reputational implications beyond the immediate retraction.&lt;/p&gt;

&lt;p&gt;Industry observers note this is unlikely to be an isolated incident. As AI writing assistance becomes ubiquitous across professional services, the risk of sophisticated-sounding but fabricated content reaching clients and public audiences grows proportionally. The KPMG case may accelerate development of verification tooling and audit trails for AI-assisted professional content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Industry Power Structure Shifts: FAANG Becomes MANGOS
&lt;/h2&gt;

&lt;p&gt;Industry observers are &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;noting a symbolic shift&lt;/a&gt; in tech's informal power structure as the venerable FAANG acronym gives way to new formulations reflecting the AI era's changed landscape. The emergence of "MANGOS"—Microsoft, Apple, Nvidia, Google, OpenAI, and SpaceX—captures how AI infrastructure and applications have reshuffled the hierarchy.&lt;/p&gt;

&lt;p&gt;The SpaceX IPO, expected later this year, would cement the company's position among the most valuable technology firms globally, while OpenAI's commercial momentum has made it impossible to discuss frontier tech without including it. Meanwhile, Netflix and Meta—both original FAANG members—have seen their influence on the industry's direction diminish relative to companies driving AI infrastructure.&lt;/p&gt;

&lt;p&gt;In a noteworthy detail, &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Amazon CEO&lt;/a&gt; Andy Jassy reportedly raised concerns about Anthropic model vulnerabilities with government contacts prior to the Fable 5 takedown—a reminder that despite Amazon's significant investment in Anthropic, the relationship between major cloud providers and their AI portfolio companies remains complex.&lt;/p&gt;

&lt;p&gt;The acronym shift may seem trivial, but it reflects genuine reordering of which companies set the industry's agenda. Infrastructure providers and AI-native companies have displaced consumer internet platforms as the center of gravity.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What to Watch:&lt;/strong&gt; The coming weeks will test whether Anthropic can resolve the Fable 5 situation without lasting damage to user trust and whether Google's pricing moves trigger a broader race to the bottom. The federal preemption bill's committee progress bears monitoring—if it advances quickly, the current fragmented AI regulatory landscape could look very different by year's end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;AI News &amp;amp; Artificial Intelligence | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Artificial Intelligence - AI News - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;TechCrunch | Startup and Technology News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com" rel="noopener noreferrer"&gt;WIRED - The Latest in Technology, Science, Culture and Business | WIRED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/business/us-house-lawmakers-release-draft-bill-regulate-ai-2026-06-04" rel="noopener noreferrer"&gt;US House lawmakers release draft bill to prohibit state AI rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2511.17332" rel="noopener noreferrer"&gt;[PDF] Hybrid Agentic AI and Multi-Agent Systems in Smart Manufacturing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;Agentifying Agentic AI - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;Agentic Artificial Intelligence (AI): Architectures, Taxonomies, and ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/VoltAgent/awesome-ai-agent-papers" rel="noopener noreferrer"&gt;VoltAgent/awesome-ai-agent-papers - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://resources.anthropic.com/building-effective-ai-agents" rel="noopener noreferrer"&gt;Building Effective AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://techcrunch.com/2026/02/19/googles-new-gemini-pro-model-has-record-benchmark-scores-again" rel="noopener noreferrer"&gt;Google's new Gemini Pro model has record benchmark scores — again | TechCrunch&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>LangSmith Engine: Self-Improving Agents That Debug Other Agents</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 08 Jun 2026 12:06:38 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/langsmith-engine-self-improving-agents-that-debug-other-agents-305d</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/langsmith-engine-self-improving-agents-that-debug-other-agents-305d</guid>
      <description>&lt;h1&gt;
  
  
  LangSmith Engine: Self-Improving Agents That Debug Other Agents
&lt;/h1&gt;

&lt;p&gt;The moment your agent portfolio grows beyond a handful of deployments, you hit an uncomfortable truth: you're now spending more time debugging agents than building them. At &lt;a href="https://interrupt.langchain.com" rel="noopener noreferrer"&gt;Interrupt 2026&lt;/a&gt;, LangChain unveiled something that directly addresses this scaling problem—LangSmith Engine, an autonomous agent whose sole purpose is analyzing, diagnosing, and suggesting fixes for your production agent failures. This isn't another dashboard with fancier visualizations. It's the formalization of a meta-agent paradigm where the work of improving agents becomes itself an agentic task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: The Meta-Agent Paradigm Shift
&lt;/h2&gt;

&lt;p&gt;The announcement landed during Harrison Chase's keynote at &lt;a href="https://interrupt.langchain.com" rel="noopener noreferrer"&gt;Interrupt 2026&lt;/a&gt;, held May 13-14 in San Francisco. Engine represents a categorical shift from passive observability—where humans sift through traces trying to understand what went wrong—to active diagnosis where an agent formulates hypotheses, tests them against historical data, and generates concrete remediation suggestions.&lt;/p&gt;

&lt;p&gt;Why does this matter right now? The &lt;a href="https://pub.towardsai.net/a-developers-guide-to-agentic-frameworks-in-2026-3f22a492dc3d" rel="noopener noreferrer"&gt;2026 agentic AI landscape&lt;/a&gt; has matured to the point where organizations are running not one or two experimental agents, but entire portfolios of production systems. When you're operating dozens of agents across customer support, data pipelines, and internal tooling, the manual trace inspection that worked for a single prototype becomes untenable. Teams report spending 60-70% of their agent engineering time on post-deployment debugging rather than capability development.&lt;/p&gt;

&lt;p&gt;The architectural insight driving Engine is subtle but profound: agent improvement itself has the characteristics of an agentic task. It requires reasoning over incomplete information, tool use to query trace databases, hypothesis generation and testing, and memory of past investigations to avoid re-diagnosing known issues. By treating debugging as a first-class agent workflow rather than a human dashboard activity, LangChain is betting that AI can accelerate the agent improvement loop just as dramatically as agents accelerated other knowledge work.&lt;/p&gt;

&lt;p&gt;Engine draws a sharp distinction from traditional APM tools. Where Datadog or New Relic might tell you that your agent's P95 latency spiked, Engine investigates &lt;em&gt;why&lt;/em&gt;—was it a slow tool call, an LLM inference delay, or an orchestration bottleneck from suboptimal state checkpointing? And crucially, it proposes what to do about it with specific code changes, prompt rewrites, or architectural modifications.&lt;/p&gt;

&lt;p&gt;The target audience is clear: teams operating five or more agents in production who need automated quality feedback loops. If you're still iterating on a single agent, the overhead of deploying Engine probably isn't worth it. But once you cross that threshold where agent failures are a daily occurrence rather than an exceptional event, Engine's value proposition becomes compelling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: How an Agent Debugs Agents
&lt;/h2&gt;

&lt;p&gt;Engine's architecture rests on SmithDB, a new data layer for agent observability that LangChain announced in the same week. SmithDB provides structured trace storage optimized specifically for agent queries—not generic time-series data, but relational structures that capture parent-child relationships between agent calls, tool invocations, and LLM inference requests. This foundation enables the kind of complex trace traversal that Engine's investigations require.&lt;/p&gt;

&lt;p&gt;The overall system follows a three-layer architecture: trace ingestion, pattern detection, and remediation generation. Trace ingestion handles the firehose of observability data from your &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;LangGraph deployments&lt;/a&gt;, normalizing the heterogeneous data from different agent types into a consistent schema. Pattern detection runs continuously, applying both rule-based heuristics and learned classifiers to identify anomalies worth investigating. Remediation generation is where Engine's agentic nature emerges—it spins up investigation workflows that can last minutes or hours depending on the complexity of the issue.&lt;/p&gt;

&lt;p&gt;Engine's reasoning loop follows a &lt;a href="https://github.com/nirdiamant/genai_agents" rel="noopener noreferrer"&gt;ReAct-style&lt;/a&gt; cycle: observe anomaly, formulate hypothesis, execute investigative action, evaluate results, repeat. For example, when detecting elevated failure rates in a customer support agent, Engine might hypothesize that a recent prompt change caused the regression. It then queries SmithDB for traces before and after the change, diffs the prompt versions, examines failure modes in both cohorts, and either confirms or rejects the hypothesis before moving to alternatives.&lt;/p&gt;

&lt;p&gt;Memory integration is essential for avoiding duplicate work. Engine maintains episodic memory of past investigations, indexed by failure signature and root cause. When a similar pattern emerges, Engine retrieves relevant past investigations, potentially short-circuiting the diagnosis with a "we've seen this before" assessment. This connects to the &lt;a href="https://github.com/TsinghuaC3I/Awesome-Memory-for-Agents" rel="noopener noreferrer"&gt;broader memory architecture&lt;/a&gt; patterns emerging in agentic systems—treating investigative context as a persistent asset rather than a single-session artifact.&lt;/p&gt;

&lt;p&gt;Engine's tool repertoire includes trace querying (SQL-like interfaces to SmithDB), diff generation (comparing prompt versions, tool configurations, and agent code), prompt variation testing (spinning up isolated evaluation runs with modified prompts), and cost impact estimation (projecting how suggested changes would affect token budgets based on historical patterns).&lt;/p&gt;

&lt;p&gt;A subtle but important design decision: Engine avoids infinite recursion by operating in a separate instrumentation namespace. Engine's own traces are never visible to itself—it cannot enter a pathological loop of debugging its own debugging attempts. This namespace isolation is enforced at the SDK level, ensuring Engine's investigation activities remain invisible to its own pattern detection systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace Analysis Patterns Engine Detects
&lt;/h2&gt;

&lt;p&gt;Engine ships with a library of detection patterns refined against LangChain's internal agent fleet, and teams can extend this library with custom detectors. The most impactful built-in patterns address the failure modes that consume the majority of debugging time.&lt;/p&gt;

&lt;p&gt;Tool call failure cascades represent one of the trickiest patterns to diagnose manually. When an agent makes a tool call that fails, the downstream behavior depends heavily on how the failure is handled—does the agent retry? Fall back to an alternative? Propagate the error? Engine distinguishes between recoverable retry patterns (where a transient failure resolves on retry) and true cascade failures (where one failed tool call corrupts state that triggers subsequent failures). This distinction matters because the remediation differs dramatically: retry patterns might need backoff tuning while cascades require architectural changes to state management.&lt;/p&gt;

&lt;p&gt;Prompt drift detection catches a subtle but common issue. Over time, production prompts diverge from the versions that were evaluated during development—through hotfixes, A/B test winners that weren't properly documented, or well-intentioned tweaks that accumulate. Engine maintains a baseline registry of evaluated prompts and flags when production traces show prompts that have drifted beyond configurable thresholds. This directly addresses the &lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;observability challenges&lt;/a&gt; identified in empirical studies of agentic systems.&lt;/p&gt;

&lt;p&gt;Latency attribution decomposes end-to-end response times into their constituent parts: LLM inference time, tool execution duration, and orchestration overhead (the time spent in your agent code between LLM calls). This decomposition reveals whether performance issues stem from model latency, slow external APIs, or inefficient agent logic—each requiring different remediation approaches.&lt;/p&gt;

&lt;p&gt;Cost anomaly detection goes beyond simple budget alerts. When Engine flags a run that exceeded expected token budgets, it provides root cause analysis: was it excessive tool call chatter? A prompt that triggered verbose responses? A retry loop that repeated expensive operations? This contextual information transforms a "you spent too much" alert into actionable guidance on where to optimize.&lt;/p&gt;

&lt;p&gt;State corruption patterns are particularly valuable for teams using &lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;checkpointed agent architectures&lt;/a&gt;. Engine detects when saved state leads to invalid downstream behavior—for example, when a checkpoint captures a partial tool response that causes parsing failures on resume. These bugs are notoriously difficult to reproduce in development because they depend on precise timing and state sequences.&lt;/p&gt;

&lt;p&gt;Internal benchmarks from LangChain's own agent fleet show 47x faster mean-time-to-diagnosis when using Engine compared to manual trace inspection. This metric captures the time from anomaly detection to root cause identification—not including remediation, which still requires human judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Remediation Suggestion Pipeline
&lt;/h2&gt;

&lt;p&gt;Diagnosis without actionable suggestions is just sophisticated complaining. Engine's remediation pipeline transforms investigative conclusions into concrete, applicable fixes.&lt;/p&gt;

&lt;p&gt;The key design principle is specificity: Engine generates actual code patches, not abstract descriptions. When Engine determines that a tool retry should include exponential backoff, it doesn't suggest "consider adding backoff logic"—it produces a diff that can be applied to your agent definition. This aligns with &lt;a href="https://arxiv.org/html/2601.02749v1" rel="noopener noreferrer"&gt;emerging research&lt;/a&gt; on agentic systems that suggests concrete, executable outputs drive higher adoption than abstract recommendations.&lt;/p&gt;

&lt;p&gt;Prompt rewrite suggestions represent Engine's most frequently used remediation type. When Engine identifies prompt-related failures—ambiguous instructions that lead to tool misuse, missing context that causes hallucinations, or overly verbose system prompts that consume unnecessary tokens—it proposes alternative formulations. These suggestions come packaged with A/B test configurations, allowing teams to validate improvements before full deployment.&lt;/p&gt;

&lt;p&gt;Guard rail recommendations address systematic vulnerabilities rather than individual failures. When Engine observes patterns like repeated jailbreak attempts, PII exposure in tool outputs, or runaway token consumption, it suggests where to add protective nodes—ContentFilter for safety violations, RateLimiter for cost control, or validation gates for data integrity. These suggestions reference specific positions in your &lt;a href="https://www.langchain.com/blog/langgraph-multi-agent-workflows" rel="noopener noreferrer"&gt;LangGraph agent topology&lt;/a&gt;, making implementation straightforward.&lt;/p&gt;

&lt;p&gt;Every suggestion includes a confidence score reflecting Engine's uncertainty. High-confidence suggestions (0.8+) indicate patterns Engine has seen many times with consistent remediation outcomes. Low-confidence suggestions (below 0.5) flag novel patterns or ambiguous root causes where human judgment is essential. This calibration helps teams prioritize which suggestions to evaluate first and which require careful human review.&lt;/p&gt;

&lt;p&gt;Integration with LangChain's Fleet deployment system enables staged rollouts. Engine suggestions can be automatically staged as draft deployments pending human approval—the fix exists as a deployable artifact but won't reach production until a human explicitly approves it. This preserves the human-in-the-loop requirement that remains essential for production changes while reducing the friction between diagnosis and deployment.&lt;/p&gt;

&lt;p&gt;The limitations are explicit and by design: Engine cannot modify deployed agents directly. Even high-confidence suggestions with clear positive impact require human approval. This constraint acknowledges both the liability implications of automated production changes and the reality that Engine may have blind spots in understanding business context that would affect remediation decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;Let's walk through setting up Engine on an existing LangGraph agent. We'll start with a customer support agent that's already instrumented with LangSmith tracing, then configure Engine to monitor and investigate its failures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# engine_setup.py
# Setting up LangSmith Engine for automated agent debugging
# Requires: langsmith&amp;gt;=0.4.0, langgraph&amp;gt;=0.5.0, langsmith-engine&amp;gt;=1.0.0
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith_engine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InvestigationConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Scope&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.checkpoint.memory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MemorySaver&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize LangSmith client with Engine capabilities
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LANGSMITH_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;# Engine requires the engine_enabled flag for trace access
&lt;/span&gt;    &lt;span class="n"&gt;engine_enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define investigation scope - which agents Engine should monitor
# This prevents Engine from investigating its own traces (separate namespace)
&lt;/span&gt;&lt;span class="n"&gt;investigation_scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;project_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer-support-prod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer-support-staging&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;# Exclude Engine's own project to prevent recursion
&lt;/span&gt;    &lt;span class="n"&gt;exclude_projects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;langsmith-engine-internal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;# Only investigate traces with specific tags
&lt;/span&gt;    &lt;span class="n"&gt;required_tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;production&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="c1"&gt;# Time window for historical analysis
&lt;/span&gt;    &lt;span class="n"&gt;lookback_hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;168&lt;/span&gt;  &lt;span class="c1"&gt;# One week of trace history
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Configure investigation behavior
&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InvestigationConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# Maximum depth of causal chain analysis
&lt;/span&gt;    &lt;span class="n"&gt;max_investigation_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Token budget cap for Engine's own LLM calls per investigation
&lt;/span&gt;    &lt;span class="n"&gt;max_tokens_per_investigation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Confidence threshold for auto-staging suggestions to Fleet
&lt;/span&gt;    &lt;span class="n"&gt;auto_stage_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Patterns to prioritize (Engine will investigate these first)
&lt;/span&gt;    &lt;span class="n"&gt;priority_patterns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_cascade_failure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_drift&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_anomaly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="c1"&gt;# Memory configuration for investigation history
&lt;/span&gt;    &lt;span class="n"&gt;memory_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;episodic_retention_days&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;similarity_threshold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# For matching similar past issues
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_retrieved_investigations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize Engine with scope and configuration
&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;investigation_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Model for Engine's reasoning (Claude or GPT-4 class recommended)
&lt;/span&gt;    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-20250514&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Notification webhook for completed investigations
&lt;/span&gt;    &lt;span class="n"&gt;webhook_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Start continuous monitoring (runs as background process)
# Engine will automatically trigger investigations when anomalies are detected
&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_monitoring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# Anomaly detection interval
&lt;/span&gt;    &lt;span class="n"&gt;check_interval_seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Thresholds that trigger automatic investigation
&lt;/span&gt;    &lt;span class="n"&gt;triggers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failure_rate_threshold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;gt;5% failures triggers investigation
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_p95_multiplier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# 2x normal P95 triggers investigation
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_anomaly_zscore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;       &lt;span class="c1"&gt;# 3 std devs above mean triggers investigation
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Engine monitoring started. Investigations will run automatically.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's look at manually triggering an investigation and processing the results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# investigate_incident.py
# Manually triggering and processing an Engine investigation
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith_engine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InvestigationReport&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="c1"&gt;# Assuming engine is already initialized from previous setup
# Trigger investigation for a specific trace that showed anomalous behavior
&lt;/span&gt;&lt;span class="n"&gt;investigation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;investigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# Can investigate by trace_id, run_id, or time range with filters
&lt;/span&gt;    &lt;span class="n"&gt;trace_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc123-def456-ghi789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Or investigate a pattern across multiple traces
&lt;/span&gt;    &lt;span class="c1"&gt;# pattern_query={
&lt;/span&gt;    &lt;span class="c1"&gt;#     "failure_type": "tool_timeout",
&lt;/span&gt;    &lt;span class="c1"&gt;#     "time_range": (datetime.now() - timedelta(hours=24), datetime.now()),
&lt;/span&gt;    &lt;span class="c1"&gt;#     "min_occurrences": 10
&lt;/span&gt;    &lt;span class="c1"&gt;# },
&lt;/span&gt;
    &lt;span class="c1"&gt;# Investigation focus hints (optional, speeds up diagnosis)
&lt;/span&gt;    &lt;span class="n"&gt;initial_hypotheses&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_regression&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Investigation runs asynchronously - can poll or await
&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InvestigationReport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;investigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;await_completion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout_seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Parse the investigation report
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Investigation ID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Duration: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration_seconds&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Engine tokens consumed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Root cause analysis
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== Root Cause Analysis ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Primary cause: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root_cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confidence: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root_cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Evidence traces: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root_cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;supporting_traces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# View the hypothesis chain (Engine's reasoning process)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== Investigation Chain ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hypothesis_chain&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Hypothesis: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hypothesis&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   Action: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action_taken&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   Result: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   Verdict: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Confirmed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confirmed&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Rejected&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Remediation suggestions
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== Suggested Remediations ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;suggestions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Type: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confidence: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# For code changes, show the diff
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code_diff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Diff:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;code_diff&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# For prompt changes, show before/after
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_change&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Original prompt hash: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;original_hash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Suggested prompt:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_prompt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Apply suggestion if confidence is high enough
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_rewrite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Stage the suggestion in Fleet (requires human approval to deploy)
&lt;/span&gt;        &lt;span class="n"&gt;deployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stage_to_fleet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;fleet_project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer-support-prod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;variant_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;engine-suggestion-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;traffic_percentage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# Start with 10% A/B test
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Staged as Fleet variant: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;variant_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, here's how to verify that a suggested fix actually improved agent performance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# verify_improvement.py
# Running evaluation to verify Engine's suggested fix
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith.evaluation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;evaluate&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith_engine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Get the suggestion that was staged
&lt;/span&gt;&lt;span class="n"&gt;suggestion_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;suggestion-xyz789&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;suggestion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_suggestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suggestion_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run evaluation comparing original vs suggested prompt
&lt;/span&gt;&lt;span class="n"&gt;eval_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;# Your agent function with the original configuration
&lt;/span&gt;    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;original&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c1"&gt;# Dataset of test cases (can auto-generate from failure traces)
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_eval_dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;include_failure_cases&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;include_success_cases&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="n"&gt;evaluators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;correctness&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Built-in evaluator
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_accuracy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Custom evaluator for tool use
&lt;/span&gt;        &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;custom_evaluator&lt;/span&gt;  &lt;span class="c1"&gt;# Engine-generated evaluator for this specific issue
&lt;/span&gt;    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="n"&gt;experiment_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pre-fix-baseline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run same evaluation with suggested fix
&lt;/span&gt;&lt;span class="n"&gt;eval_results_fixed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;run_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prompt_change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new_prompt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_eval_dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;evaluators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;correctness&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_accuracy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;custom_evaluator&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;experiment_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;post-fix-comparison&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Compare results
&lt;/span&gt;&lt;span class="n"&gt;comparison&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_experiments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;baseline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;eval_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;experiment_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;eval_results_fixed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;experiment_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Improvement in correctness: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltas&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;correctness&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Improvement in tool accuracy: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltas&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tool_call_accuracy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If improvement is significant, approve the Fleet deployment
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deltas&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;correctness&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;gt;10% improvement
&lt;/span&gt;    &lt;span class="n"&gt;fleet_deployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;approve_deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;approved_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;engine-verification-pipeline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;traffic_percentage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;  &lt;span class="c1"&gt;# Roll out fully
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deployed to production: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fleet_deployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost considerations are important: Engine itself consumes tokens for its investigations. In the configuration above, we capped investigations at 50,000 tokens each. For teams running frequent investigations, budgeting $50-200/month for Engine's own LLM costs is typical. The ROI calculation centers on engineer time saved—if Engine saves 10 hours of debugging per month at $100/hour effective cost, the investment pays back quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;Engine makes the most sense for teams with specific operational characteristics. If you're running more than 1,000 daily agent runs and seeing failure rates above 5%, Engine's automated investigation capabilities provide clear time savings. Below those thresholds, the overhead of setting up and maintaining Engine may exceed the manual debugging time it saves.&lt;/p&gt;

&lt;p&gt;The organizational workflow that emerges treats Engine as a "first responder" for agent incidents. When an anomaly triggers, Engine investigates immediately—often completing diagnosis before a human even notices the alert. The human engineer's role shifts from "figure out what happened" to "evaluate Engine's analysis and decide whether to approve the suggested fix." This is a fundamental change in the debugging workflow that requires some adjustment in team processes and expectations.&lt;/p&gt;

&lt;p&gt;For teams already using alerting tools, Engine integrates cleanly. Engine investigation reports can be formatted as structured payloads for PagerDuty, Slack, or email notifications. A typical integration sends a summary with confidence scores immediately upon investigation completion, with links to the full report in LangSmith. High-confidence suggestions might trigger different notification channels than low-confidence ones that require more human analysis.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;competitive landscape&lt;/a&gt; for agent observability is heating up. AgentOps, Helicone, and other tools provide trace visualization and basic alerting. Engine differentiates through its agentic investigation approach—it doesn't just show you what happened, it reasons about why and proposes what to do. However, Engine currently only works with LangSmith traces, creating lock-in for teams considering multi-provider observability strategies.&lt;/p&gt;

&lt;p&gt;Looking at &lt;a href="https://www.langchain.com/blog" rel="noopener noreferrer"&gt;Harrison Chase's comments&lt;/a&gt; during Interrupt, future Engine capabilities will likely include automated rollback recommendations (when Engine detects that a recent deployment caused regression) and cross-agent pattern learning (identifying issues that affect multiple agents in your portfolio and suggesting portfolio-wide fixes). These capabilities would further reduce the human involvement needed in routine agent maintenance.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://machinelearningmastery.com/7-agentic-ai-trends-to-watch-in-2026" rel="noopener noreferrer"&gt;broader trends in agentic AI&lt;/a&gt; suggest that meta-agent patterns like Engine will proliferate. As agent systems become more complex, the meta-level work of monitoring, debugging, and improving those systems will increasingly benefit from agentic approaches. Engine is an early instantiation of this pattern, but expect competitors and alternatives to emerge rapidly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Build This Week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build an Engine-monitored canary agent.&lt;/strong&gt; Take your most failure-prone production agent and set up Engine monitoring with aggressive thresholds (2% failure rate trigger, 1.5x latency multiplier). Run it for one week and review every investigation Engine produces. Your goal isn't to deploy any fixes yet—it's to calibrate your understanding of how Engine reasons about your specific agent's failure modes.&lt;/p&gt;

&lt;p&gt;Document each investigation: Was Engine's root cause analysis accurate? Were the suggested fixes applicable? Where did Engine miss important context? This calibration exercise will teach you where Engine excels (systematic issues with clear trace signatures) and where it struggles (business logic errors that require domain knowledge). You'll emerge with a clear sense of which agent problems to route to Engine versus escalate directly to human engineers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://interrupt.langchain.com" rel="noopener noreferrer"&gt;The Agent Conference by LangChain | Interrupt 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pub.towardsai.net/a-developers-guide-to-agentic-frameworks-in-2026-3f22a492dc3d" rel="noopener noreferrer"&gt;A Developer's Guide to Agentic Frameworks in 2026 - Towards AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;langchain-ai/langgraph: Build resilient agents. - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/langgraph-multi-agent-workflows" rel="noopener noreferrer"&gt;LangGraph: Multi-Agent Workflows - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nirdiamant/genai_agents" rel="noopener noreferrer"&gt;NirDiamant/GenAI_Agents: 50+ tutorials and implementations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TsinghuaC3I/Awesome-Memory-for-Agents" rel="noopener noreferrer"&gt;TsinghuaC3I/Awesome-Memory-for-Agents - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;Agentic Frameworks for Reasoning Tasks: An Empirical Study - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2601.02749v1" rel="noopener noreferrer"&gt;The Path Ahead for Agentic AI: Challenges and Opportunities - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;AI Agent Frameworks Comparison 2026: Complete Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://machinelearningmastery.com/7-agentic-ai-trends-to-watch-in-2026" rel="noopener noreferrer"&gt;7 Agentic AI Trends to Watch in 2026 - MachineLearningMastery.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://www.langchain.com/blog" rel="noopener noreferrer"&gt;LangChain Blog&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of the **Agentic Engineering Weekly&lt;/em&gt;* series — a deep-dive every Monday into the frameworks,&lt;br&gt;
patterns, and techniques shaping the next generation of AI systems.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building something agentic? Drop a comment — I'd love to feature reader projects.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Weekly: The Tokenpocalypse Hits, Agentic Systems Mature, and Security Takes Center Stage</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 08 Jun 2026 12:05:20 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-the-tokenpocalypse-hits-agentic-systems-mature-and-security-takes-center-stage-6l1</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-the-tokenpocalypse-hits-agentic-systems-mature-and-security-takes-center-stage-6l1</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly: The Tokenpocalypse Hits, Agentic Systems Mature, and Security Takes Center Stage
&lt;/h1&gt;

&lt;p&gt;The AI industry's "move fast and worry about costs later" era is officially over. This week brought a stark reckoning as enterprises discovered that unlimited AI access doesn't scale, while simultaneously the agentic programming paradigm crossed critical capability thresholds that make these tools harder than ever to abandon. The tension between transformative productivity gains and unsustainable infrastructure economics is now the defining challenge of enterprise AI adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Tokenpocalypse" Arrives: Enterprises Scramble as AI Costs Spiral
&lt;/h2&gt;

&lt;p&gt;The bill for enterprise AI enthusiasm is coming due. &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;TechCrunch reports&lt;/a&gt; on what insiders are calling the "tokenpocalypse"—a widespread scramble across Fortune 500 companies to contain AI inference costs that have blown past even aggressive projections.&lt;/p&gt;

&lt;p&gt;Uber provides the most striking example: the company reportedly exhausted its entire annual employee AI spending budget in just four months, forcing leadership to implement hard caps on individual usage. The culprit isn't frivolous prompts—it's the multiplicative effect of thousands of employees using AI assistants for routine tasks, each interaction consuming tokens that add up to staggering monthly invoices.&lt;/p&gt;

&lt;p&gt;The pattern repeats across industries. Financial services firms report inference costs 3-4x initial estimates. Healthcare organizations are renegotiating API contracts mid-year. Even AI-native startups are implementing usage monitoring dashboards that would have seemed paranoid twelve months ago.&lt;/p&gt;

&lt;p&gt;What makes this particularly thorny is the asymmetry between costs and benefits. The productivity gains are real—many organizations report genuine efficiency improvements—but token economics create a usage-punishing model where success breeds expense. The more valuable AI proves, the more employees use it, and the faster budgets evaporate.&lt;/p&gt;

&lt;p&gt;Expect a wave of cost optimization tooling, smarter routing between model tiers, and some uncomfortable conversations about which use cases justify frontier model pricing versus smaller, cheaper alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The capability gap between agentic AI systems and human researchers is narrowing faster than most predictions anticipated. &lt;a href="https://www.anthropic.com/institute/recursive-self-improvement" rel="noopener noreferrer"&gt;Anthropic reports&lt;/a&gt; that Claude's open-ended task success rate reached 76% in May 2026—a remarkable 50 percentage point improvement in just six months. The benchmark measures completion of complex, multi-step tasks without human intervention, making this one of the most meaningful metrics for real-world agent deployment.&lt;/p&gt;

&lt;p&gt;Perhaps more striking is the weak-to-strong supervision experiment: Claude agents recovered 97% of the performance gap between weak and strong oversight, compared to just 23% achieved by human researchers working on the same problem. The compute bill—approximately $18,000 over 800 hours—represents a fraction of equivalent human labor costs, fundamentally changing the economics of research automation.&lt;/p&gt;

&lt;p&gt;Production architectures are converging on &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;multi-agent orchestration patterns&lt;/a&gt;, with orchestrator agents coordinating specialized sub-agents that maintain dedicated context windows. This allows complex workflows to exceed individual context limits while preserving coherent task execution. The &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;framework landscape&lt;/a&gt; is stabilizing around LangGraph, CrewAI, &lt;a href="https://openai.com/index/new-tools-for-building-agents" rel="noopener noreferrer"&gt;OpenAI Agents SDK&lt;/a&gt;, and Microsoft Agent Framework, all now shipping span-aware observability layers for debugging multi-agent interactions.&lt;/p&gt;

&lt;p&gt;Meanwhile, Genkit's new middleware system offers composable hooks for retries, model fallbacks, and tool approval gates—the kind of production-hardening infrastructure that signals agentic systems moving from experimental to enterprise-critical.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Ships Lockdown Mode to Combat Prompt Injection
&lt;/h2&gt;

&lt;p&gt;OpenAI &lt;a href="https://openai.com/index/new-tools-for-building-agents" rel="noopener noreferrer"&gt;launched Lockdown Mode&lt;/a&gt;, a new security feature designed to protect enterprise deployments from prompt injection attacks. The feature creates isolation boundaries between system instructions and user inputs, preventing malicious prompts from extracting sensitive data or hijacking agent behavior.&lt;/p&gt;

&lt;p&gt;The timing is deliberate. As AI agents gain broader system access—executing code, querying databases, managing credentials—the attack surface for prompt injection expands exponentially. A successful injection against a customer service bot is inconvenient; against an agent with API keys and database write access, it's catastrophic.&lt;/p&gt;

&lt;p&gt;Lockdown Mode implements several defensive layers: instruction compartmentalization, output filtering for sensitive patterns, and anomaly detection for unusual agent behavior sequences. It's opt-in for now, but OpenAI is clearly positioning security architecture as a first-class concern rather than an afterthought.&lt;/p&gt;

&lt;p&gt;The company also confirmed that development continues on its &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;"super app" initiative&lt;/a&gt;, which would consolidate ChatGPT, image generation, and agentic capabilities into a unified consumer platform—a direct response to the fragmented experience currently spread across multiple interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Microsoft Launches Scout: OpenClaw-Inspired Personal Assistant
&lt;/h2&gt;

&lt;p&gt;Microsoft &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;debuted Scout&lt;/a&gt;, a new personal assistant that draws architectural inspiration from the open-source OpenClaw framework. The assistant emphasizes persistent context across sessions, proactive task suggestion, and tight integration with Microsoft 365 services.&lt;/p&gt;

&lt;p&gt;Scout represents an interesting pattern: major labs increasingly building production systems on paradigms first developed in community-driven projects. OpenClaw's contribution—a modular agent architecture allowing swappable reasoning and memory components—has been refined and scaled to Microsoft's infrastructure requirements.&lt;/p&gt;

&lt;p&gt;The positioning is clearly competitive with ChatGPT's memory features and Claude's project-based context management. Microsoft is betting that operating system-level integration and enterprise identity management will differentiate Scout in environments where standalone chat interfaces feel disconnected from actual workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anthropic's Pre-IPO Positioning: Daniela Amodei Addresses AI Returns Skepticism
&lt;/h2&gt;

&lt;p&gt;With an IPO reportedly on the horizon, Anthropic is getting ahead of investor skepticism about AI returns. In recent public remarks, Daniela Amodei shared internal productivity data showing the median Anthropic employee reports approximately 4x output improvement using Mythos Preview for their workflows.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;2026 Agentic Coding Trends Report&lt;/a&gt; provides external validation: engineers using agentic coding tools report decreased time-per-task but significantly larger increases in total output volume. The nuance matters—AI doesn't just make existing work faster; it makes previously impractical workloads feasible.&lt;/p&gt;

&lt;p&gt;TELUS offers a concrete case study: their teams shipped code 30% faster, saving over 500,000 hours—roughly 40 minutes saved per AI interaction. At enterprise scale, those minutes compound into strategic advantage.&lt;/p&gt;

&lt;p&gt;The productivity narrative is essential for Anthropic's valuation story, but it also reflects a genuine phase transition in AI deployment. The question is no longer whether AI tools improve individual productivity, but whether organizations can capture those gains at scale without the cost spiral hitting other enterprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackers Exploit Meta AI Support Chatbot to Hijack Instagram Accounts
&lt;/h2&gt;

&lt;p&gt;A social engineering attack &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;exploited Meta's AI-powered support system&lt;/a&gt; to gain unauthorized access to Instagram accounts, highlighting security risks as AI chatbots handle increasingly sensitive authentication workflows.&lt;/p&gt;

&lt;p&gt;The attack vector was clever: users were directed to what appeared to be a legitimate support flow, where the AI assistant was manipulated into initiating account recovery processes without proper verification. The chatbot, trained to be helpful and resolve user issues, became an unwitting accomplice in credential theft.&lt;/p&gt;

&lt;p&gt;The incident raises uncomfortable questions about AI system permissions in customer service contexts. When chatbots can trigger password resets, modify account settings, or escalate to privileged operations, they become high-value targets for social engineering. Traditional security models assumed human operators would catch suspicious patterns; AI systems require different safeguards.&lt;/p&gt;

&lt;p&gt;Meta has patched the specific vulnerability, but the broader architectural challenge remains: balancing AI helpfulness with security requires rethinking how much authority automated systems should have over identity-critical operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  WWDC 2026 Preview: Apple's Siri Overhaul and Apple Intelligence Updates
&lt;/h2&gt;

&lt;p&gt;Apple's WWDC kicks off tomorrow, and &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;all indications point&lt;/a&gt; to the most significant Siri overhaul in the assistant's history. Leaked developer documentation suggests deeper integration with Apple Intelligence, expanded on-device processing capabilities, and—finally—conversational context that persists across sessions.&lt;/p&gt;

&lt;p&gt;The pressure is real. ChatGPT, Claude, and Gemini have established consumer expectations for AI assistants that Siri cannot currently meet. Apple's privacy-first approach, while differentiated, has also meant slower feature deployment compared to cloud-native competitors.&lt;/p&gt;

&lt;p&gt;Expect announcements around improved natural language understanding, more sophisticated task chaining, and tighter integration with third-party apps through enhanced Shortcuts capabilities. The developer story matters too: Apple needs to give iOS developers compelling reasons to build agent-native experiences rather than simply wrapping ChatGPT APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  AirTrunk Commits $30B for 5GW AI Data Centers in India
&lt;/h2&gt;

&lt;p&gt;AirTrunk &lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;announced a $30 billion investment&lt;/a&gt; to build 5 gigawatts of AI-focused data center capacity across India, marking one of the largest single infrastructure commitments in the current AI buildout cycle.&lt;/p&gt;

&lt;p&gt;The scale is staggering—5GW could power roughly 4 million homes—and reflects the voracious power requirements of both training runs and, increasingly, inference at scale. The India location offers advantages in land availability, cooling efficiency in certain regions, and access to technical talent for operations.&lt;/p&gt;

&lt;p&gt;This investment joins a global race for AI compute infrastructure, with hyperscalers and specialized operators locked in competition for power purchase agreements, cooling technology, and the specialized construction expertise required for high-density deployments. The physical layer of AI—often overlooked in discussions of algorithms and architectures—has become a strategic bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Watch
&lt;/h2&gt;

&lt;p&gt;The cost management crisis hitting enterprises this week will force rapid innovation in inference optimization, model routing, and usage governance—expect a wave of startups and tools addressing this gap in the coming months. Meanwhile, the security incidents at Meta and OpenAI's Lockdown Mode response signal that agentic security is moving from theoretical concern to operational priority. Apple's WWDC announcements tomorrow will reveal whether the company can close the consumer AI gap or if the Siri overhaul is too little, too late.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;AI News &amp;amp; Artificial Intelligence | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/institute/recursive-self-improvement" rel="noopener noreferrer"&gt;When AI builds itself | Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com" rel="noopener noreferrer"&gt;TechCrunch | Startup and Technology News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;Multi-Agent AI Systems 2026: Frameworks Compared - Future AGI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;Top 13 Agentic AI Trends to Watch in 2026 - Firecrawl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;2026 Agentic Coding Trends Report - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://openai.com/index/new-tools-for-building-agents" rel="noopener noreferrer"&gt;New tools for building agents | OpenAI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>LangChain 1.0: The Complexity Tax Verdict</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 01 Jun 2026 12:03:34 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/langchain-10-the-complexity-tax-verdict-504i</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/langchain-10-the-complexity-tax-verdict-504i</guid>
      <description>&lt;h1&gt;
  
  
  LangChain 1.0: The Complexity Tax Verdict
&lt;/h1&gt;

&lt;p&gt;The framework wars of 2024-2025 asked one question repeatedly: is LangChain's abstraction layer worth the cognitive overhead? With the &lt;a href="https://www.langchain.com/blog/march-2026-langchain-newsletter" rel="noopener noreferrer"&gt;1.0 stable release&lt;/a&gt; now shipping, we finally have an answer — but it's not the binary verdict most teams wanted. LangChain 1.0 is a much better version of what came before, not a fundamentally different framework, and understanding that distinction determines whether migration or adoption makes sense for your specific workload.&lt;/p&gt;

&lt;p&gt;The timing matters. We're watching the agentic AI landscape consolidate rapidly, with &lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;Alice Labs' production analysis&lt;/a&gt; ranking LangGraph first for complex stateful workflows across their 18+ deployments — but also noting that alternatives like Claude Agent SDK, CrewAI, and Pydantic AI have closed the gap significantly. The complexity tax question isn't academic anymore; it's a quarterly planning decision that affects team velocity, operational costs, and system maintainability.&lt;/p&gt;

&lt;p&gt;This deep-dive evaluates LangChain 1.0 against its own promises and its competitors' capabilities. We'll walk through the agent protocol standardization, the LangGraph runtime architecture, and a production-ready code implementation — then map these capabilities against the decision matrix you'll actually use when choosing frameworks. The goal isn't advocacy; it's giving you the technical clarity to make the right call for your specific constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agent Protocol: What Actually Shipped in 1.0
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.digitalapplied.com/blog/langchain-1-deep-dive-agent-protocol-runtime-2026" rel="noopener noreferrer"&gt;agent protocol standardization&lt;/a&gt; in LangChain 1.0 represents the most significant breaking change from the 0.x era — and the primary reason the migration is worth considering. The unified interface for agent instantiation, tool binding, and message handling now works consistently across both base LangChain and LangGraph, eliminating the cognitive overhead of remembering which API surface applied to which context.&lt;/p&gt;

&lt;p&gt;Tool binding consolidation delivers the most visible improvement. The &lt;code&gt;@tool&lt;/code&gt; decorator pattern now generates JSON schemas automatically from Python type hints, deprecating the legacy &lt;code&gt;Tool&lt;/code&gt; class constructors that required manual schema definition. This isn't just convenience — it eliminates a category of runtime errors where schema mismatches caused silent failures in production. The &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;State of Agent Engineering report&lt;/a&gt; notes that tool schema errors were among the top three debugging pain points in 2025 production deployments.&lt;/p&gt;

&lt;p&gt;The Runnable protocol stability finally gives teams a canonical API to learn once and apply everywhere. &lt;code&gt;invoke()&lt;/code&gt;, &lt;code&gt;stream()&lt;/code&gt;, and &lt;code&gt;batch()&lt;/code&gt; are the three methods — that's it. The 0.x-era &lt;code&gt;__call__&lt;/code&gt; overloads are gone, which breaks existing code but eliminates the confusion about which invocation pattern to use when. Native async support through &lt;code&gt;ainvoke()&lt;/code&gt; and &lt;code&gt;astream()&lt;/code&gt; now includes proper cancellation semantics; the 0.x implementation had documented race conditions in cleanup handlers that caused resource leaks in long-running deployments.&lt;/p&gt;

&lt;p&gt;The callback system overhaul deserves attention from teams building observability infrastructure. Typed callback handlers replace string-based event names, enabling IDE autocomplete and static analysis that catches integration errors at development time rather than production. The &lt;code&gt;ChatModel&lt;/code&gt; base class now includes a standardized &lt;code&gt;bind_tools()&lt;/code&gt; method signature that works identically across &lt;a href="https://medium.com/@atnoforgenai/10-ai-agent-frameworks-you-should-know-in-2026-langgraph-crewai-autogen-more-2e0be4055556" rel="noopener noreferrer"&gt;OpenAI, Anthropic, Google, and other providers&lt;/a&gt;, reducing the provider-specific knowledge required to switch models.&lt;/p&gt;

&lt;h2&gt;
  
  
  LangGraph Runtime: The 1.0 Production Architecture
&lt;/h2&gt;

&lt;p&gt;LangGraph's runtime architecture in 1.0 reflects hard-won lessons from production deployments. The &lt;a href="https://www.digitalapplied.com/blog/langchain-1-deep-dive-agent-protocol-runtime-2026" rel="noopener noreferrer"&gt;StateGraph initialization&lt;/a&gt; now requires an explicit &lt;code&gt;state_schema&lt;/code&gt; parameter — a breaking change that emerged from LangGraph 2.0 and carries through to the unified release. This mandatory typing catches state shape mismatches at graph construction time rather than during execution, which matters enormously when debugging distributed systems.&lt;/p&gt;

&lt;p&gt;The checkpointer interface has reached stability with &lt;code&gt;PostgresSaver&lt;/code&gt;, &lt;code&gt;SqliteSaver&lt;/code&gt;, and &lt;code&gt;MemorySaver&lt;/code&gt; sharing identical APIs. Connection pooling is enabled by default, addressing the connection exhaustion issues that plagued early production deployments. The practical implication: you can develop locally with &lt;code&gt;SqliteSaver&lt;/code&gt;, run integration tests with &lt;code&gt;MemorySaver&lt;/code&gt;, and deploy to production with &lt;code&gt;PostgresSaver&lt;/code&gt; without changing node implementation code.&lt;/p&gt;

&lt;p&gt;Edge routing formalization represents a subtle but powerful improvement. The &lt;code&gt;add_conditional_edges()&lt;/code&gt; method now accepts typed routing functions that return &lt;code&gt;Literal&lt;/code&gt; types, enabling compile-time validation of routing logic. Combined with the &lt;a href="https://www.digitalapplied.com/blog/langchain-1-deep-dive-agent-protocol-runtime-2026" rel="noopener noreferrer"&gt;graph validation&lt;/a&gt; that &lt;code&gt;graph.compile()&lt;/code&gt; performs — including reachability analysis and orphan node detection — teams can catch structural errors before deployment rather than discovering them through runtime failures.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;interrupt()&lt;/code&gt; API for &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;human-in-the-loop workflows&lt;/a&gt; is now the canonical pattern, replacing the ad-hoc state mutation approaches that characterized early LangGraph implementations. This matters for compliance-sensitive deployments where human approval gates are mandatory. The interrupt mechanism integrates cleanly with checkpointing, allowing workflows to pause indefinitely without losing state.&lt;/p&gt;

&lt;p&gt;Node lifecycle hooks (&lt;code&gt;on_enter&lt;/code&gt;, &lt;code&gt;on_exit&lt;/code&gt;) address resource management in long-running graphs. Database connections, API clients, and file handles can be properly cleaned up even when nodes fail mid-execution. This isn't glamorous functionality, but it's the difference between graphs that work in demos and graphs that survive production traffic patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;The following implementation demonstrates LangChain 1.0's canonical patterns for a production-ready research agent. This agent searches the web, retrieves documents, and synthesizes findings — a common pattern that exercises tool binding, conditional routing, checkpointing, and observability integration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# langchain_research_agent.py
# Requires: langchain-core&amp;gt;=1.0.0, langchain-openai&amp;gt;=1.0.0, langgraph&amp;gt;=2.0.0
# pip install langchain-core langchain-openai langgraph psycopg2-binary
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.messages&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AIMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.checkpoint.postgres&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PostgresSaver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.prebuilt&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ToolNode&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Define typed state schema - now mandatory in 1.0
# The Annotated pattern with operator.add enables message accumulation
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BaseMessage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Accumulates across nodes
&lt;/span&gt;    &lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Retrieved document content
&lt;/span&gt;    &lt;span class="n"&gt;iteration_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;  &lt;span class="c1"&gt;# Guard against infinite loops
&lt;/span&gt;    &lt;span class="n"&gt;search_queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Track what we've searched
&lt;/span&gt;
&lt;span class="c1"&gt;# 2. Tool definitions using the @tool decorator
# Schema generation is automatic from type hints - no manual JSON schema required
&lt;/span&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search the web for current information on a topic.

    Args:
        query: The search query string to look up

    Returns:
        Summarized search results as a string
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Production: Replace with actual search API (Tavily, SerpAPI, etc.)
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search results for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: [Simulated web content about &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieve documents from the knowledge base on a specific topic.

    Args:
        topic: The topic to retrieve documents about
        max_docs: Maximum number of documents to return

    Returns:
        List of relevant document contents
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Production: Replace with vector store retrieval
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Document &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; about &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_docs&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Initialize the model with tool binding - standardized in 1.0
# bind_tools() works identically across OpenAI, Anthropic, Google providers
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieve_documents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;model_with_tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4. Node implementations with structured error handling
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;research_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Main research node - decides whether to search, retrieve, or synthesize.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Guard against runaway iterations - critical for production
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Maximum iterations reached. Synthesizing available information.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_with_tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Structured error handling with state-based recovery
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;AIMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Research step failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Attempting recovery...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;synthesize_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Synthesize findings from collected documents and search results.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;synthesis_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Based on the following research materials, provide a comprehensive synthesis:

Documents collected: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;  # Limit context window usage

Provide a well-structured summary addressing the original query.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;synthesis_prompt&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="c1"&gt;# 5. Routing function with Literal return type for compile-time validation
# This pattern enables static analysis and IDE support
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;route_research&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Route based on the last message - determines next step in the workflow.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;last_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check for tool calls in the response
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;last_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Check iteration count for forced synthesis
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;iteration&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Check for completion signals in content
&lt;/span&gt;    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SYNTHESIS COMPLETE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# 6. Build the graph with explicit schema - the 1.0 pattern
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResearchState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add nodes
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;research_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ToolNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# Built-in tool execution node
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;synthesize_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Set entry point
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add conditional edges with typed routing
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_conditional_edges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;route_research&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;complete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Tools always return to research for next decision
&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tools&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 7. Compile with production checkpointing
# PostgresSaver with connection pooling for production workloads
&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PostgresSaver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_conn_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://user:pass@localhost:5432/langchain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pool_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Connection pool for concurrent requests
&lt;/span&gt;    &lt;span class="n"&gt;max_overflow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;  &lt;span class="c1"&gt;# Allow burst capacity
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Compile performs reachability analysis and validates graph structure
&lt;/span&gt;&lt;span class="n"&gt;compiled_graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 8. Usage with LangSmith tracing integration
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_research&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute a research workflow with full observability.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.tracers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LangChainTracer&lt;/span&gt;

    &lt;span class="n"&gt;initial_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iteration_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Configure tracing and thread persistence
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configurable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;callbacks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;LangChainTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research-agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Stream execution for real-time progress
&lt;/span&gt;    &lt;span class="n"&gt;final_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;compiled_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Step: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;final_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;final_state&lt;/span&gt;

&lt;span class="c1"&gt;# Example invocation
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_research&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What are the key architectural patterns for production AI agents in 2026?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research-session-001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation demonstrates several 1.0-specific patterns worth noting. The &lt;code&gt;TypedDict&lt;/code&gt; state schema with &lt;code&gt;Annotated&lt;/code&gt; fields enables automatic message accumulation — a common source of bugs in 0.x implementations where developers manually managed list concatenation. The &lt;code&gt;Literal&lt;/code&gt; return type on the routing function allows &lt;code&gt;graph.compile()&lt;/code&gt; to validate that all routing outcomes have corresponding edges defined. The checkpointer configuration shows production-appropriate connection pooling, and the tracing integration demonstrates the LangSmith observability pattern that's now built into the framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Path: 0.x to 1.0 Breaking Changes
&lt;/h2&gt;

&lt;p&gt;Migration from LangChain 0.x to 1.0 requires systematic changes across several dimensions. The &lt;a href="https://www.digitalapplied.com/blog/langchain-1-deep-dive-agent-protocol-runtime-2026" rel="noopener noreferrer"&gt;import reorganization&lt;/a&gt; is the most visible: &lt;code&gt;from langchain.chat_models&lt;/code&gt; becomes &lt;code&gt;from langchain_openai&lt;/code&gt; (or the appropriate provider-specific package). This isn't just renaming — it reflects the architectural decision to separate the core framework from provider implementations, enabling independent versioning and faster provider-specific updates.&lt;/p&gt;

&lt;p&gt;The deprecation of &lt;code&gt;ConversationChain&lt;/code&gt; and &lt;code&gt;LLMChain&lt;/code&gt; represents a philosophical shift. These high-level abstractions hid too much complexity, making debugging difficult when behavior didn't match expectations. The 1.0 pattern favors explicit composition: &lt;code&gt;ChatModel | PromptTemplate | OutputParser&lt;/code&gt; as distinct, inspectable components. Teams with extensive &lt;code&gt;LLMChain&lt;/code&gt; usage should budget time for refactoring, but the resulting code is more maintainable.&lt;/p&gt;

&lt;p&gt;Memory class removal (&lt;code&gt;ConversationBufferMemory&lt;/code&gt;, &lt;code&gt;ConversationSummaryMemory&lt;/code&gt;, etc.) is the most significant breaking change for chat applications. The &lt;a href="https://www.langchain.com/blog/march-2026-langchain-newsletter" rel="noopener noreferrer"&gt;1.0 architecture&lt;/a&gt; expects memory to live in LangGraph state or external storage you manage directly. This eliminates the "magic" behavior that caused confusion about where state actually resided, but requires explicit state management code.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Agent&lt;/code&gt; and &lt;code&gt;AgentExecutor&lt;/code&gt; classes are deprecated for new code. The replacement pattern uses &lt;code&gt;create_react_agent()&lt;/code&gt; which returns a compiled &lt;code&gt;StateGraph&lt;/code&gt; — unifying the mental model between simple agents and complex workflows. Existing &lt;code&gt;AgentExecutor&lt;/code&gt; code will continue to work but won't receive new features.&lt;/p&gt;

&lt;p&gt;Callback handler signatures changed from &lt;code&gt;on_llm_start(serialized, prompts, **kwargs)&lt;/code&gt; to &lt;code&gt;on_llm_start(run_id, messages, **kwargs)&lt;/code&gt;, reflecting the shift from prompt-centric to message-centric APIs. Custom callback handlers require updates, but the new signature is more useful for observability purposes since &lt;code&gt;run_id&lt;/code&gt; enables correlation across distributed traces.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;langchain-community&lt;/code&gt; package split means provider integrations require separate installations: &lt;code&gt;pip install langchain-anthropic&lt;/code&gt;, &lt;code&gt;pip install langchain-google-genai&lt;/code&gt;, etc. This adds installation complexity but reduces dependency bloat for applications using single providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  LangChain vs. Alternatives: The 2026 Decision Matrix
&lt;/h2&gt;

&lt;p&gt;The framework landscape has matured significantly, and the &lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;Alice Labs analysis&lt;/a&gt; provides useful data for comparison. LangGraph maintains the top ranking for complex stateful workflows, but the decision factors are more nuanced than simple rankings suggest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Against Claude Agent SDK&lt;/strong&gt;: Anthropic's native offering provides a simpler API surface and tighter Claude integration, but locks you to a single provider. Choose LangChain when multi-provider flexibility matters — switching models mid-project or running A/B tests across providers becomes trivial with the standardized &lt;code&gt;ChatModel&lt;/code&gt; interface. Choose Claude Agent SDK when you're committed to Claude and want minimal abstraction overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Against CrewAI&lt;/strong&gt;: The &lt;a href="https://github.com/crewaiinc/crewai" rel="noopener noreferrer"&gt;role-based multi-agent abstraction&lt;/a&gt; in CrewAI offers faster initial development for team-of-agents patterns, but the higher-level abstraction limits customization. Choose LangChain when you need fine-grained state control or non-standard agent coordination patterns. The &lt;a href="https://arxiv.org/html/2605.10052v2" rel="noopener noreferrer"&gt;Swarm Skills paper&lt;/a&gt; demonstrates that CrewAI-to-AutoGen translation requires adapter layers, suggesting interoperability challenges when outgrowing the framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Against Pydantic AI&lt;/strong&gt;: For type-safe Python with minimal abstraction, &lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;Pydantic AI&lt;/a&gt; offers excellent developer experience. Choose LangChain when workflow complexity exceeds single-agent patterns — Pydantic AI excels at tool-using chat but doesn't provide the graph execution semantics needed for multi-step coordination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Against Microsoft Semantic Kernel&lt;/strong&gt;: The enterprise-native option for &lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;.NET-first teams&lt;/a&gt;, Semantic Kernel provides deeper Azure integration. Choose LangChain for Python-first teams without .NET requirements. Note that &lt;a href="https://github.com/microsoft/autogen/discussions/7144" rel="noopener noreferrer"&gt;AutoGen's shared state handling&lt;/a&gt; across multi-agent conversations remains a documented challenge.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;decision heuristic from Alice Labs&lt;/a&gt; provides a useful starting point: "Start from your dominant constraint: control (LangGraph), team velocity (CrewAI), type safety (Pydantic AI)." This framingcorrectly identifies that framework selection should derive from constraints, not feature lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you're already on LangChain 0.x&lt;/strong&gt;: The migration is worth the investment. The stability guarantees, consolidated APIs, and improved debugging experience reduce ongoing maintenance burden. Budget 2-4 weeks for a medium-sized codebase, with the primary effort going toward memory class replacement and import reorganization. The &lt;a href="https://www.langchain.com/blog/january-2026-langchain-newsletter" rel="noopener noreferrer"&gt;January 2026 newsletter&lt;/a&gt; includes migration tooling that automates some import updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're evaluating frameworks fresh&lt;/strong&gt;: LangChain 1.0 is the right choice specifically for workflows requiring durable state, conditional branching, and multi-step agent coordination. It's not the right choice for simple single-turn chat or prototype applications where iteration speed matters more than production robustness. The &lt;a href="https://medium.com/@dewasheesh.rana/agentic-ai-design-patterns-2026-ed-e3a5125162c5" rel="noopener noreferrer"&gt;agentic AI design patterns&lt;/a&gt; emerging in 2026 map well to LangGraph's graph-based model, suggesting long-term alignment with industry direction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangSmith coupling consideration&lt;/strong&gt;: The &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;integrated evaluation framework&lt;/a&gt; provides powerful capabilities — automated regression testing, prompt versioning, cost tracking — but creates platform dependency. If your organization requires portable observability through OpenTelemetry or vendor-neutral tracing, evaluate whether LangSmith's benefits justify the lock-in. The callback system does support custom tracers, but LangSmith-specific features won't translate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost awareness&lt;/strong&gt;: LangChain's abstraction layers add token overhead through system prompts and tool schemas. For &lt;a href="https://arxiv.org/pdf/2602.07359" rel="noopener noreferrer"&gt;high-volume workloads&lt;/a&gt;, measure actual token costs against direct API usage. The difference can be 15-25% depending on workflow complexity. This overhead buys development velocity and debugging capability, but the tradeoff should be conscious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team skill match&lt;/strong&gt;: LangGraph's graph-based mental model requires upfront learning investment. Teams without prior experience with state machines, workflow orchestration, or reactive systems may find &lt;a href="https://github.com/crewaiinc/crewai" rel="noopener noreferrer"&gt;CrewAI's declarative approach&lt;/a&gt; faster to adopt initially. However, the graph model provides better long-term maintainability for complex systems — it's a question of where you want to spend the learning time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production readiness checklist&lt;/strong&gt;: Before deploying LangChain 1.0 agents to production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable checkpointing — never run stateful graphs without persistence&lt;/li&gt;
&lt;li&gt;Configure connection pooling for database checkpointers (10-20 connections typical)&lt;/li&gt;
&lt;li&gt;Set up LangSmith tracing or equivalent observability before deployment&lt;/li&gt;
&lt;li&gt;Implement node-level timeouts to prevent runaway executions&lt;/li&gt;
&lt;li&gt;Add iteration guards in routing logic to catch infinite loops&lt;/li&gt;
&lt;li&gt;Test interrupt/resume flows if human-in-the-loop is required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to Build This Week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project: Document QA Agent with Citation Tracking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a research agent that answers questions about a document corpus while maintaining explicit citation chains. This exercises the 1.0 patterns — typed state with document references, conditional routing between retrieval and synthesis, checkpointing for long-running analysis sessions — while solving a practical problem: knowing exactly which documents supported which claims.&lt;/p&gt;

&lt;p&gt;The state schema should include &lt;code&gt;citations: list[Citation]&lt;/code&gt; where &lt;code&gt;Citation&lt;/code&gt; is a &lt;code&gt;TypedDict&lt;/code&gt; with &lt;code&gt;document_id&lt;/code&gt;, &lt;code&gt;chunk_text&lt;/code&gt;, and &lt;code&gt;relevance_score&lt;/code&gt; fields. Your routing logic should decide between "retrieve more documents", "validate existing citations", and "generate final answer with citations". The synthesis node should produce output that includes inline source references mapping to the citation state.&lt;/p&gt;

&lt;p&gt;Deploy with PostgresSaver checkpointing and LangSmith tracing, then test resumption: kill the process mid-execution, restart, and verify the agent continues from its last checkpoint without re-retrieving documents. This resumption capability is what separates demo code from production systems, and LangChain 1.0 makes it straightforward to implement correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalapplied.com/blog/langchain-1-deep-dive-agent-protocol-runtime-2026" rel="noopener noreferrer"&gt;LangChain 1 Deep Dive: Agent Protocol + Runtime 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;State of Agent Engineering - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/march-2026-langchain-newsletter" rel="noopener noreferrer"&gt;March 2026: LangChain Newsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;AI Agent Frameworks 2026: Production-Tested Ranking - Alice Labs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/blog/january-2026-langchain-newsletter" rel="noopener noreferrer"&gt;January 2026: LangChain Newsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@atnoforgenai/10-ai-agent-frameworks-you-should-know-in-2026-langgraph-crewai-autogen-more-2e0be4055556" rel="noopener noreferrer"&gt;10 AI Agent Frameworks You Should Know in 2026: LangGraph ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/autogen" rel="noopener noreferrer"&gt;GitHub - microsoft/autogen: A programming framework for agentic AI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/crewaiinc/crewai" rel="noopener noreferrer"&gt;GitHub - crewAIInc/crewAI: Framework for orchestrating role-playing ...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2605.10052v2" rel="noopener noreferrer"&gt;Swarm Skills: A Portable, Self-Evolving Multi-Agent System Specification for Coordination Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/autogen/discussions/7144" rel="noopener noreferrer"&gt;Handling shared state across multi-agent conversations in AutoGen · Discussion #7144&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;AI Agent Frameworks Comparison 2026: Complete Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/pdf/2602.07359" rel="noopener noreferrer"&gt;W&amp;amp;D: Scaling Parallel Tool Calling for Efficient Deep Research Agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://medium.com/@dewasheesh.rana/agentic-ai-design-patterns-2026-ed-e3a5125162c5" rel="noopener noreferrer"&gt;Agentic AI Design Patterns (2026 Edition)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of the **Agentic Engineering Weekly&lt;/em&gt;* series — a deep-dive every Monday into the frameworks,&lt;br&gt;
patterns, and techniques shaping the next generation of AI systems.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Building something agentic? Drop a comment — I'd love to feature reader projects.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI Weekly Digest: Memory Wars, Model Upgrades, and the Trading Benchmark That Humbled Five LLMs</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 01 Jun 2026 12:02:35 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-digest-memory-wars-model-upgrades-and-the-trading-benchmark-that-humbled-five-llms-2f66</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-digest-memory-wars-model-upgrades-and-the-trading-benchmark-that-humbled-five-llms-2f66</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly Digest: Memory Wars, Model Upgrades, and the Trading Benchmark That Humbled Five LLMs
&lt;/h1&gt;

&lt;p&gt;The week ending June 1, 2026 delivered a sharp reminder that raw compute isn't everything—and neither is language fluency. A $135M chip startup is betting AI's real constraint is memory, Anthropic shipped a model that actually catches its own coding mistakes, and a brutal new benchmark revealed that most frontier models can't beat the market even when they're confident they can. Meanwhile, the infrastructure buildout continues at staggering scale, and the backlash chorus is growing louder.&lt;/p&gt;




&lt;h2&gt;
  
  
  XCENA Raises $135M Betting AI's Real Bottleneck Is Memory, Not Compute
&lt;/h2&gt;

&lt;p&gt;Chip startup XCENA has &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;secured $135 million in funding&lt;/a&gt;, positioning itself against the dominant GPU-centric narrative that has made NVIDIA the undisputed king of AI infrastructure. The company's core thesis is provocative but increasingly resonant among systems architects: memory bandwidth and latency—not raw floating-point operations—are the true limiting factors for scaling AI workloads.&lt;/p&gt;

&lt;p&gt;The argument isn't new among researchers, but it's gaining commercial validation. Modern transformer inference spends enormous time waiting for weights to load from memory rather than actually computing. NVIDIA's H100 and H200 have addressed this partially with HBM3 and HBM3e, but XCENA claims their architecture delivers fundamentally different memory-compute ratios optimized specifically for inference rather than training.&lt;/p&gt;

&lt;p&gt;The implications for next-generation AI infrastructure are significant. If XCENA's bet pays off, we could see a bifurcation in the chip market: GPU clusters for training, memory-optimized silicon for serving. This would particularly benefit enterprises deploying large language models at scale, where inference costs dominate operational budgets. The $135M gives XCENA runway to tape out production chips, though they'll face the sobering reality that challenging NVIDIA's ecosystem moat requires more than better specs—it requires convincing hyperscalers to take a risk on unproven silicon.&lt;/p&gt;




&lt;h2&gt;
  
  
  Anthropic Releases Claude Opus 4.8 with Enhanced Code Self-Correction
&lt;/h2&gt;

&lt;p&gt;Anthropic &lt;a href="https://www.anthropic.com/news/claude-opus-4-8" rel="noopener noreferrer"&gt;released Claude Opus 4.8&lt;/a&gt; this week, with the headline improvement being a roughly 4x reduction in the rate at which the model lets code flaws pass unremarked compared to its predecessor, Opus 4.7. The model is available immediately via API as &lt;code&gt;claude-opus-4-8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This matters because self-correction capability is arguably the single most important trait for autonomous coding agents. A model that confidently ships buggy code creates technical debt at machine speed; one that catches its own mistakes before commit becomes genuinely useful for unsupervised work. Anthropic's internal evaluations show improvements across syntax errors, logic bugs, and security vulnerabilities, though the company notes the gains are most pronounced in languages with strong type systems.&lt;/p&gt;

&lt;p&gt;Perhaps more intriguing is the &lt;a href="https://www.anthropic.com/news/claude-opus-4-8" rel="noopener noreferrer"&gt;Project Glasswing preview&lt;/a&gt;, which enables select organizations to use Claude Mythos—Anthropic's specialized security-focused model—for cybersecurity work including vulnerability assessment and threat modeling. Access is restricted and requires application, suggesting Anthropic is being cautious about dual-use concerns. The combination signals Anthropic's broader strategic push: making Claude not just capable but &lt;em&gt;reliable&lt;/em&gt; enough for high-stakes autonomous deployment where errors have real consequences.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agentic Programming Updates
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;Microsoft Agent Framework&lt;/a&gt; is now officially positioned as the successor to AutoGen, consolidating async multi-agent patterns into a production-ready stack. The framework emphasizes typed message passing, structured agent lifecycles, and native Azure integration—Microsoft's clear bid to own enterprise agent infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Zijian-Ni/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;LlamaIndex shipped Google Agents API integration&lt;/a&gt; this week, including access to sandboxed Linux environments for agents that need to execute code safely. Alongside it, they released ParseBench, an OCR benchmark specifically designed for evaluating how well agents can extract structured data from documents—a capability that's increasingly critical for enterprise automation.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/topics/best-ai-tools-2026" rel="noopener noreferrer"&gt;Genkit middleware system&lt;/a&gt; arrived with composable hooks for retries, model fallbacks, tool approval gates, and skill injection. This middleware pattern—borrowed from web frameworks—lets developers declaratively specify policies rather than scattering retry logic throughout agent code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://huggingface.co/blog/daya-shankar/agentic-ai-trends-2026" rel="noopener noreferrer"&gt;MCP Apps are emerging as a 2026 pattern&lt;/a&gt;: tools that return rich interactive UIs (dashboards, forms, visualizations) directly within agent chat interfaces. This collapses the distinction between "agent gives you information" and "agent gives you an app."&lt;/p&gt;

&lt;p&gt;Finally, &lt;a href="https://aimultiple.com/agentic-ai-trends" rel="noopener noreferrer"&gt;multi-agent orchestration is shifting from experimental to enterprise mainstream&lt;/a&gt;, with UiPath and IBM both publishing formal guidance on deploying agent swarms in production. The era of single-agent demos is definitively over.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Copilot's New Token-Based Billing Sparks Developer Backlash
&lt;/h2&gt;

&lt;p&gt;GitHub's move to a &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;token-metered pricing model for Copilot&lt;/a&gt; has ignited significant developer frustration, with complaints centering on unpredictable costs and the cognitive overhead of monitoring usage. The shift away from flat monthly subscriptions—previously $10/month for individuals and $19/month for business—represents a fundamental change in how AI coding assistants are sold.&lt;/p&gt;

&lt;p&gt;The backlash is driven by practical concerns. Developers report that token consumption varies wildly based on coding style, project complexity, and how aggressively they use chat features versus inline completions. A heavy Copilot user might see bills 3-5x higher than the old flat rate, while occasional users could theoretically pay less. The uncertainty is the problem: engineers hate variable costs for tools they use continuously.&lt;/p&gt;

&lt;p&gt;Competing tools are positioning against the change. &lt;a href="https://github.com/orgs/community/discussions/187143" rel="noopener noreferrer"&gt;Cursor, Continue, and Roo Code&lt;/a&gt; are all emphasizing their pricing models—some flat-rate, some with generous free tiers, some offering local-model options that eliminate API costs entirely. The strategic question for GitHub is whether enterprise procurement departments, who value predictable budgets, will push back hard enough to force a reversal. Microsoft has historically been flexible when enterprise customers revolt, but they also have revenue targets that flat subscriptions weren't meeting.&lt;/p&gt;




&lt;h2&gt;
  
  
  SoftBank Commits €75 Billion for French AI Data Center Infrastructure
&lt;/h2&gt;

&lt;p&gt;SoftBank &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;announced a €75 billion commitment&lt;/a&gt; to build AI data center infrastructure in France, part of a broader European AI buildout that's accelerating across the continent. The investment will span multiple facilities optimized for both training and inference workloads, with construction expected to begin in 2027.&lt;/p&gt;

&lt;p&gt;The deal follows a pattern of Big Tech infrastructure investments targeting an estimated &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;110 GW of power for AI workloads&lt;/a&gt; globally by 2030—roughly equivalent to adding another Germany to global electricity demand. Nuclear power agreements have become the preferred mechanism for securing clean baseload, with Microsoft, Google, and Amazon all signing deals in the past year.&lt;/p&gt;

&lt;p&gt;Environmental activist &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Erin Brockovich has raised concerns&lt;/a&gt; about data center secrecy and environmental impact, particularly around water usage for cooling and the gap between companies' renewable energy claims and actual grid impact. France's relatively clean nuclear-heavy grid makes it attractive for AI workloads that need to claim low carbon intensity, but local communities are increasingly questioning whether they want these massive facilities in their regions. The €75 billion figure is eye-catching, but the real story is infrastructure: AI capability is increasingly constrained by physical buildout, not algorithmic progress.&lt;/p&gt;




&lt;h2&gt;
  
  
  PolyBench Reveals Only 2 of 7 Top LLMs Can Actually Make Money Trading
&lt;/h2&gt;

&lt;p&gt;A new benchmark called &lt;a href="https://arxiv.org/html/2604.14199v1" rel="noopener noreferrer"&gt;PolyBench&lt;/a&gt; has delivered a humbling result for large language models: when tested against live Polymarket prediction data spanning 38,666 markets, only two of seven state-of-the-art models actually made money. The rest lost despite expressing high confidence in their predictions.&lt;/p&gt;

&lt;p&gt;MiMo-V2-Flash achieved a 17.6% cumulative weighted return, while Gemini-3-Flash managed 6.2%. The remaining five models—including several frontier systems with strong performance on standard benchmarks—ended in the red. What makes this particularly striking is that the losing models often exhibited high stated confidence; they weren't uncertain, they were confidently wrong.&lt;/p&gt;

&lt;p&gt;The benchmark exposes a crucial gap between language fluency and genuine probabilistic reasoning under uncertainty. Prediction markets are adversarial environments where being calibrated matters more than being articulate. The PolyBench paper argues that most LLM evaluation frameworks test whether models can generate plausible text, not whether they can make accurate bets. This has direct implications for financial applications, autonomous agents that need to reason about uncertain outcomes, and any domain where overconfidence is costly. The results suggest we may need fundamentally different training approaches—or at minimum, different fine-tuning objectives—to produce models that know what they don't know.&lt;/p&gt;




&lt;h2&gt;
  
  
  Meta Reportedly Developing AI Pendant Wearable
&lt;/h2&gt;

&lt;p&gt;Meta is &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;exploring an AI-powered pendant device&lt;/a&gt;, according to reports this week, joining a heating wearable AI race that Google intensified with &lt;a href="https://www.wired.com/story/everything-google-announced-at-google-io-2026" rel="noopener noreferrer"&gt;Android smart glasses demos at I/O 2026&lt;/a&gt;. The pendant form factor—a microphone-equipped device worn around the neck or clipped to clothing—represents a different bet than glasses: less obtrusive, no camera concerns, but also less capable for visual AI features.&lt;/p&gt;

&lt;p&gt;The strategic logic for Meta is unclear given that Meta AI is already deeply integrated into WhatsApp, Messenger, and Instagram. A pendant would need to offer something those apps can't: always-listening ambient awareness, perhaps, or faster access than pulling out a phone. The privacy implications are immediately obvious, and Meta's brand isn't exactly associated with trust in that domain.&lt;/p&gt;

&lt;p&gt;Google's approach at I/O emphasized glasses with real-time translation, visual search, and navigation overlays—capabilities that genuinely require a camera. A pendant can transcribe and respond to voice but can't see. The question is whether voice-only ambient AI is compelling enough to wear a dedicated device, or whether AirPods and existing smartphone assistants already serve that need. The pendant category has seen multiple high-profile failures; Meta will need to explain what's different this time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pope Leo XIV Joins Growing Chorus Warning About AI Dangers
&lt;/h2&gt;

&lt;p&gt;The Vatican this week &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;issued formal warnings about artificial intelligence risks&lt;/a&gt;, with Pope Leo XIV joining university graduates and industry voices in what Reuters characterized as an &lt;a href="https://www.reuters.com/commentary/breakingviews/global-markets-breakingviews-2026-05-31" rel="noopener noreferrer"&gt;"AI backlash arrives"&lt;/a&gt; moment. The Vatican's statement emphasized concerns about human dignity, labor displacement, and autonomous systems making consequential decisions without meaningful human oversight.&lt;/p&gt;

&lt;p&gt;The timing is notable. While OpenAI's Sam Altman has &lt;a href="https://www.reuters.com/world/asia-pacific/openais-altman-says-ai-unlikely-lead-jobs-apocalypse-2026-05-26" rel="noopener noreferrer"&gt;maintained that AI is unlikely to lead to a "jobs apocalypse"&lt;/a&gt;, the accumulation of warnings from religious leaders, academics, and affected workers is creating political pressure that wasn't present even a year ago. Governance frameworks remain fragmented; the EU AI Act is still ramping up enforcement, and the US approach remains sector-specific and reactive.&lt;/p&gt;

&lt;p&gt;For practitioners, the most actionable concern is agent accountability. When an autonomous agent takes an action with real-world consequences—makes a trade, sends an email, files a document—who is responsible when it goes wrong? Current legal frameworks have no good answer. The Vatican's intervention won't change that directly, but it signals that the window for self-regulation by the industry is narrowing. Those building agent systems should be thinking about audit trails, human-in-the-loop checkpoints, and interpretable decision logs before regulators mandate them.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Watch
&lt;/h2&gt;

&lt;p&gt;Next week brings the expected public preview of Microsoft Agent Framework as enterprises begin piloting multi-agent systems in production. The PolyBench results may accelerate research into calibration-focused training—watch for papers on that front at ICML. And the infrastructure story isn't slowing: SoftBank's €75 billion is just one of several massive deals in negotiation, with Japan and Saudi Arabia both reportedly in advanced talks for similar-scale investments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;AI News &amp;amp; Artificial Intelligence | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wired.com/story/everything-google-announced-at-google-io-2026" rel="noopener noreferrer"&gt;Everything Announced at Google I/O 2026: Gemini, Search, Smart Glasses | WIRED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;Artificial Intelligence - AI News - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/commentary/breakingviews/global-markets-breakingviews-2026-05-31" rel="noopener noreferrer"&gt;The Week in Breakingviews: The AI backlash arrives - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/world/asia-pacific/openais-altman-says-ai-unlikely-lead-jobs-apocalypse-2026-05-26" rel="noopener noreferrer"&gt;OpenAI's Altman says AI unlikely to lead to 'jobs apocalypse' | Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;Multi-Agent AI Systems 2026: Frameworks Compared - Future AGI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Zijian-Ni/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;GitHub - Zijian-Ni/awesome-ai-agents-2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aimultiple.com/agentic-ai-trends" rel="noopener noreferrer"&gt;10+ Agentic AI Trends and Examples for 2026 - AIMultiple&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/blog/daya-shankar/agentic-ai-trends-2026" rel="noopener noreferrer"&gt;Latest Agentic AI Trends to Watch in 2026 - Hugging Face&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/topics/best-ai-tools-2026" rel="noopener noreferrer"&gt;best-ai-tools-2026 · GitHub Topics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2604.14199v1" rel="noopener noreferrer"&gt;PolyBench: Benchmarking LLM Forecasting and Trading - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/news/claude-opus-4-8" rel="noopener noreferrer"&gt;Introducing Claude Opus 4.8 - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://github.com/orgs/community/discussions/187143" rel="noopener noreferrer"&gt;Best AI Tools for Developers in 2026 - GitHub Community&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Enjoyed this briefing? Follow this series for a fresh AI update every week, written for engineers who want to stay ahead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow this publication on Dev.to to get notified of every new article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a story tip or correction? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>technology</category>
    </item>
    <item>
      <title>Primitive Shifts: Workflow Persistence as a First-Class Primitive</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 01 Jun 2026 12:02:24 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/primitive-shifts-workflow-persistence-as-a-first-class-primitive-15c9</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/primitive-shifts-workflow-persistence-as-a-first-class-primitive-15c9</guid>
      <description>&lt;h1&gt;
  
  
  Primitive Shifts: Workflow Persistence as a First-Class Primitive
&lt;/h1&gt;

&lt;p&gt;Every few months, the baseline of how AI systems work quietly moves. Engineers who noticed early weren't smarter — they were just paying attention to the right signals. Last year it was tool-use standardization. The year before, it was context window management. This month, the shift is less visible but arguably more consequential: the execution trace of an agent is becoming the artifact, not the output it produces.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is It?
&lt;/h2&gt;

&lt;p&gt;Workflow persistence is the capability to capture, store, version, and replay complete agent execution traces — including tool calls, intermediate states, decision branches, and recovery checkpoints — as durable, portable artifacts. If that sounds like "just better logging," you're missing the architectural shift.&lt;/p&gt;

&lt;p&gt;The difference is categorical. Traditional agent systems treat execution as ephemeral: you prompt, the agent runs, you get output, the intermediate state evaporates. Workflow persistence inverts this. The agent doesn't just execute tasks — it produces a &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;reusable workflow definition&lt;/a&gt; that can be audited, forked, versioned, and re-executed against different inputs or different models.&lt;/p&gt;

&lt;p&gt;This mirrors a transition we've seen before: the shift from imperative scripts to declarative infrastructure-as-code. Except now it's agent-behavior-as-code, with the agent generating its own specification through execution. Your agent's decision to call a search tool, filter results, then invoke a code interpreter isn't just logged — it becomes a deployable object.&lt;/p&gt;

&lt;p&gt;The convergence is happening across multiple frameworks simultaneously. LangGraph 2.0's checkpoint-resume architecture treats persistence as the &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;default foundation, not an opt-in feature&lt;/a&gt;. Anthropic's Managed Agents Memory (currently in public beta) builds persistent cross-session memory directly into the hosted runtime. Research from multiple institutions explicitly frames this as the &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;"AI Workflow Store" concept&lt;/a&gt; — arguing that on-the-fly agents without workflow persistence are architecturally unsound for production use.&lt;/p&gt;

&lt;p&gt;Key properties being standardized: deterministic replay from any checkpoint, branch-aware versioning for what-if exploration, cost and latency attribution per workflow step, and provenance chains linking outputs to specific tool invocations. These aren't nice-to-haves. They're the primitives that make agent systems auditable, debuggable, and reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It's Flying Under the Radar
&lt;/h2&gt;

&lt;p&gt;Most teams still treat agent runs as ephemeral. You prompt, the agent acts, you get output — the execution trace is debugging information, discarded once the task completes. This mental model was inherited from the era of one-shot LLM calls, and it persists even as agents become multi-step, multi-tool, multi-session systems.&lt;/p&gt;

&lt;p&gt;The tooling fragmentation obscures the pattern. LangGraph calls it "persistence layer." Anthropic calls it "managed memory." The research literature calls it &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;"AI Workflow Store"&lt;/a&gt;. Framework comparison guides list "checkpoint-resume recovery" and &lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;"state management between runs"&lt;/a&gt; as selection criteria — these weren't even categories twelve months ago. Same primitive, different names, no unified vocabulary for engineers to recognize the convergence.&lt;/p&gt;

&lt;p&gt;Meanwhile, current pain is attributed to wrong causes. Teams blame model inconsistency for irreproducible agent behavior, then spend weeks on prompt engineering when the actual gap is lack of workflow versioning and deterministic replay. The &lt;a href="https://github.com/vectara/awesome-agent-failures" rel="noopener noreferrer"&gt;documented failure patterns&lt;/a&gt; repeatedly show incidents — database wipes, cascading outages, unrecoverable state corruption — where workflow checkpointing would have turned catastrophic failures into recoverable interruptions.&lt;/p&gt;

&lt;p&gt;The "on-the-fly agent" paradigm — synthesize and execute per-prompt — is still the dominant mental model. &lt;a href="https://arxiv.org/html/2605.29442v1" rel="noopener noreferrer"&gt;Recent research on coding agent failures&lt;/a&gt; shows that context poisoning and prompt variations cause unpredictable divergence in agent behavior. Engineers optimize prompts when they should be versioning workflows. The orchestration layer is becoming the durable artifact, not the model outputs — but you can't see this if you're focused on model selection and prompt tuning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-On: Try It Today
&lt;/h2&gt;

&lt;p&gt;Let's make this concrete. The following example demonstrates a minimal workflow persistence layer using LangGraph's checkpoint architecture. This isn't production code — it's structured to show you the primitives so you can recognize them in your own stack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# workflow_persistence_demo.py
# Requires: pip install langgraph&amp;gt;=2.0.0 langchain-core&amp;gt;=0.2.0
# Demonstrates: checkpoint-resume, workflow serialization, replay-from-state
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.checkpoint.memory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MemorySaver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.messages&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AIMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="c1"&gt;# Define the state schema — this is what gets persisted at each checkpoint
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Conversation history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Recorded tool invocations with metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;step_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;branch_point&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# For what-if exploration
&lt;/span&gt;
&lt;span class="c1"&gt;# Simulated tools — in production, these would be your actual integrations
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Simulates a search API call with cost/latency tracking.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Results for: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;code_interpreter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Simulates code execution with full provenance.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code_interpreter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Execution result: success&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;340&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Workflow nodes — each node modifies state and creates a checkpoint
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;First step: analyze the incoming request and decide on tools.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyzing request, will need search and code execution.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute search tool and record the invocation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workflow persistence patterns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provenance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;  &lt;span class="c1"&gt;# Full provenance chain attached
&lt;/span&gt;    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Execute code and record with input hash for reproducibility.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;code_interpreter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;print(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;analyzing search results&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;branch_point&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;post-code-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Mark branch point
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;synthesize_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Final synthesis step — this is where audit trails matter most.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Final output synthesized from tool results.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;step_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_provenance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_hash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
                           &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="c1"&gt;# Build the graph with persistence enabled
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_persistent_workflow&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Constructs workflow graph with checkpoint-resume architecture.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Add nodes
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;analyze_request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;execute_search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;execute_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;synthesize_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Define edges — this is the workflow "spec" that gets versioned
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthesize&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Enable persistence — this is the key primitive
&lt;/span&gt;    &lt;span class="n"&gt;checkpointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MemorySaver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;checkpointer&lt;/span&gt;

&lt;span class="c1"&gt;# Demonstration: run, checkpoint, serialize, replay
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checkpointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_persistent_workflow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Initial state
&lt;/span&gt;    &lt;span class="n"&gt;initial_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WorkflowState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze workflow patterns&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="n"&gt;step_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;workflow_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wf-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;branch_point&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Run with thread_id for checkpoint tracking
&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configurable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;demo-thread-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="c1"&gt;# Execute workflow — each node creates a checkpoint
&lt;/span&gt;    &lt;span class="n"&gt;final_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Checkpoint: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;final_state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;

    &lt;span class="c1"&gt;# Export workflow trace as portable artifact
&lt;/span&gt;    &lt;span class="n"&gt;workflow_artifact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workflow_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workflow_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_cost_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; 
                                 &lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; 
                                &lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exportable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  &lt;span class="c1"&gt;# This artifact can be stored, versioned, replayed
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;--- Workflow Artifact (portable, versionable) ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_artifact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight isn't the code itself — it's what the code eliminates. Every &lt;code&gt;tool_calls&lt;/code&gt; entry carries provenance. Every step creates a checkpoint. The workflow artifact at the end isn't a log; it's a deployable object that can be stored in a workflow store, versioned like code, and replayed against different models to verify consistency. The &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;&lt;code&gt;branch_point&lt;/code&gt; field&lt;/a&gt; enables what-if exploration: clone this workflow, modify the decision at step 3, replay against identical inputs.&lt;/p&gt;

&lt;p&gt;For teams using Claude Code, examine the &lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;five-stage progressive compaction system&lt;/a&gt; — budget reduction, snip, microcompact, context collapse, auto-compact. This is workflow state management in disguise, determining which historical context survives as the agent continues execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Your Stack
&lt;/h2&gt;

&lt;p&gt;The architectural implications are substantial, and they cut across concerns that currently live in different parts of your codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit and compliance become tractable.&lt;/strong&gt; Every agent decision has a provenance chain. For teams in regulated industries — finance, healthcare, legal — this is transformational. &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;Demonstrating exactly how an output was produced&lt;/a&gt;, which tools were consulted, what data influenced each step: these go from "reconstructed after the fact from scattered logs" to "queryable from the workflow artifact." The compliance team's question "why did the system recommend X?" becomes a database lookup, not a forensic investigation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent reliability shifts from model tuning to workflow engineering.&lt;/strong&gt; Instead of hoping the model behaves consistently across prompts, you define and version the workflow, then swap models underneath. The workflow is the contract. &lt;a href="https://arxiv.org/html/2604.10599v1" rel="noopener noreferrer"&gt;Recent analysis of agentic systems&lt;/a&gt; emphasizes that this decoupling — stable workflow interface, replaceable model implementation — is what enables genuine production reliability. You're no longer debugging "why did GPT-4 do something different this time?" You're debugging "which version of the workflow was deployed?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost attribution becomes granular.&lt;/strong&gt; Each workflow step carries its own token, time, and cost metadata. Teams can &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;optimize specific bottlenecks&lt;/a&gt; rather than treating agent runs as opaque cost centers. "The agent costs $0.47 per run" becomes "the search-result-filtering step costs $0.23, the synthesis step costs $0.08, the tool-selection step costs $0.16." That granularity enables targeted optimization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The debugging experience transforms.&lt;/strong&gt; "Why did the agent do X?" becomes a query against a workflow trace, not a reconstruction from scattered logs. Deterministic replay lets you step through agent reasoning like a debugger — not just logging what happened, but re-executing the exact sequence to reproduce the behavior. The &lt;a href="https://github.com/vectara/awesome-agent-failures" rel="noopener noreferrer"&gt;failure pattern documentation&lt;/a&gt; consistently shows that teams with checkpoint-resume can recover from errors that would be catastrophic for teams without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Infrastructure Signal
&lt;/h2&gt;

&lt;p&gt;Watch what the frameworks are building into their foundations, not what they're marketing. The signal here is unambiguous.&lt;/p&gt;

&lt;p&gt;LangGraph 2.0 codifies &lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;"unified agent primitives (Router, Supervisor, Subagent)"&lt;/a&gt; with persistence as the default. This isn't an opt-in feature — it's the architectural foundation. The framework assumes you want checkpoints; you have to actively disable them. That default tells you what the LangChain team expects production systems to need.&lt;/p&gt;

&lt;p&gt;Anthropic is building persistent cross-session memory directly into the hosted agent runtime. The &lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;Claude Managed Agents Memory&lt;/a&gt; public beta treats the workflow trace as a platform service. You don't implement persistence; the platform provides it. That's the kind of infrastructure investment companies make when they expect a primitive to become mandatory.&lt;/p&gt;

&lt;p&gt;The research convergence is explicit. &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;"Engineering Robustness into Personal Agents with the AI Workflow Store"&lt;/a&gt; argues directly that on-the-fly agents without workflow persistence are architecturally unsound for production. The paper isn't hedging — it's stating a position based on observed failure patterns.&lt;/p&gt;

&lt;p&gt;The failure evidence supports the claim. &lt;a href="https://github.com/vectara/awesome-agent-failures" rel="noopener noreferrer"&gt;Documentation of agent failures&lt;/a&gt; repeatedly shows incidents where lack of workflow checkpointing turned recoverable errors into catastrophic ones. Database wipes. Cascading outages. State corruption that couldn't be unwound. These aren't theoretical concerns; they're documented production incidents.&lt;/p&gt;

&lt;p&gt;Framework comparison guides now list &lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;"checkpoint-resume recovery" and "state management between runs"&lt;/a&gt; as selection criteria. Twelve months ago, these categories didn't exist in framework comparisons. The fact that they're now standard evaluation criteria tells you where the industry expects the baseline to move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shift Rating
&lt;/h2&gt;

&lt;p&gt;🟢 &lt;strong&gt;Adopt Now&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Teams without workflow persistence are accumulating invisible technical debt. Every "it worked yesterday, why doesn't it work today?" debugging session. Every compliance question that requires manual trace reconstruction. Every agent failure that cascades because there's no checkpoint to recover from. Every cost optimization that's impossible because you can't attribute expense to specific steps.&lt;/p&gt;

&lt;p&gt;The primitives exist in production-ready frameworks today. LangGraph 2.0 is stable. The architectural patterns are &lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;documented&lt;/a&gt; and &lt;a href="https://github.com/vectara/awesome-agent-failures" rel="noopener noreferrer"&gt;validated against failure cases&lt;/a&gt;. The question isn't whether this becomes the standard — the question is how much technical debt you accumulate before adopting it.&lt;/p&gt;

&lt;p&gt;The floor has already moved. The question is whether your agents are standing on it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2605.10907v1" rel="noopener noreferrer"&gt;Engineering Robustness into Personal Agents with the AI Workflow Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.langchain.com/state-of-agent-engineering" rel="noopener noreferrer"&gt;State of Agent Engineering - LangChain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;2026 Agentic Coding Trends Report - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;AI Agent Frameworks Comparison 2026: Complete Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vectara/awesome-agent-failures" rel="noopener noreferrer"&gt;GitHub - vectara/awesome-agent-failures: A community curated collection of AI agent failure modes and battle-tested solutions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2605.29442v1" rel="noopener noreferrer"&gt;How Coding Agents Fail Their Users: A Large-Scale Analysis - arXiv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://arxiv.org/html/2604.10599v1" rel="noopener noreferrer"&gt;Rethinking Software Engineering for Agentic AI Systems - arXiv&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is part of **Primitive Shifts&lt;/em&gt;* — a monthly series tracking when new AI building blocks&lt;br&gt;
move from novel experiments to infrastructure you'll be expected to know.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the Next MCP Watch series on Dev.to to catch every edition.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Spotted a shift happening in your stack? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>agents</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
