<?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>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>
    <item>
      <title>AI Agent Skills: The Emerging Architecture for Composable, Evolvable Agent Capabilities</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 25 May 2026 12:06:27 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-agent-skills-the-emerging-architecture-for-composable-evolvable-agent-capabilities-23ao</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-agent-skills-the-emerging-architecture-for-composable-evolvable-agent-capabilities-23ao</guid>
      <description>&lt;h1&gt;
  
  
  AI Agent Skills: The Emerging Architecture for Composable, Evolvable Agent Capabilities
&lt;/h1&gt;

&lt;p&gt;The tools abstraction that powered the first wave of production agents is hitting its ceiling. When your agent needs to "review code," it doesn't just call a function—it reads previous review comments from memory, applies learned heuristics about the codebase, adapts its critique style to the author, and improves its approach based on whether past suggestions were accepted. This isn't a stateless function call. It's a &lt;em&gt;skill&lt;/em&gt;. And in the past four months, the entire agent framework ecosystem has converged on this distinction with remarkable speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: From Tools to Skills — A Paradigm Shift in Agent Design
&lt;/h2&gt;

&lt;p&gt;The research community's pivot to skills has been dramatic. Since February 2026, we've seen over 20 papers explicitly addressing skill architectures, skill learning, and skill evaluation—a signal that the field has identified a fundamental gap in how we build agents. The &lt;a href="https://arxiv.org/html/2601.12560v1" rel="noopener noreferrer"&gt;agentic AI architectures survey&lt;/a&gt; published in January laid the theoretical groundwork, distinguishing between "reactive tool use" and "proactive capability development." By March, the major frameworks had taken notice.&lt;/p&gt;

&lt;p&gt;The distinction between tools and skills is more than semantic. Tools are stateless function calls: &lt;code&gt;search_web(query) → results&lt;/code&gt;. Skills are learned, versioned, composable capabilities with memory and context: a "web research" skill knows which sources proved reliable in past investigations, adapts search strategies based on domain, and can delegate to sub-skills for fact verification. &lt;a href="https://www.langchain.com/blog/march-2026-langchain-newsletter" rel="noopener noreferrer"&gt;LangChain's March 2026 newsletter&lt;/a&gt; announced their Deep Agents Skills system, explicitly framing it as "the next layer of abstraction above tools." CrewAI followed with self-healing skills in their &lt;a href="https://venturebeat.com/ai/crewai-launches-its-first-multi-agent-builder-speeding-the-way-to-agentic-ai" rel="noopener noreferrer"&gt;enterprise multi-agent builder&lt;/a&gt;. Microsoft Foundry introduced &lt;a href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/advanced-function-calling-and-multi-agent-systems-with-small-language-models-in-/4481180" rel="noopener noreferrer"&gt;skill primitives for multi-agent coordination&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why the sudden convergence? The emergence of reasoning models—o1, R1, Gemini 2.5—finally gave agents the cognitive horsepower for genuine skill acquisition and composition. Earlier models could &lt;em&gt;use&lt;/em&gt; tools when instructed; reasoning models can &lt;em&gt;learn&lt;/em&gt; when and how to combine capabilities, recognize when a skill is failing, and propose refinements. &lt;a href="https://github.com/weitianxin/Awesome-Agentic-Reasoning" rel="noopener noreferrer"&gt;Research on agentic reasoning&lt;/a&gt; shows these models achieving 40-60% better performance on multi-step tasks when given skill-level abstractions rather than raw tool access.&lt;/p&gt;

&lt;p&gt;My thesis: Skills represent the "package manager" moment for agentic AI. Just as npm made JavaScript code genuinely reusable and composable, skill architectures make agent capabilities genuinely shareable and evolvable. We're moving from "agents that can do things" to "agents that can learn to do things better."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Skill Architecture Stack: Anatomy of a Modern Agent Skill
&lt;/h2&gt;

&lt;p&gt;Understanding the skill architecture requires thinking in three layers: definition, runtime, and lifecycle. Each layer addresses a distinct concern that tools-based approaches left unresolved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill Definition&lt;/strong&gt; encompasses the schema and metadata that describe what a skill does, what it requires, and what it produces. Unlike tool schemas (which specify only function signatures), skill schemas include capability declarations, memory access patterns, and composition rules. &lt;a href="https://www.datatrainersllc.com/blog/langchain-vs-langgraph-agents" rel="noopener noreferrer"&gt;LangChain's approach&lt;/a&gt; defines skills as first-class graph nodes with typed state, while CrewAI binds skills to agent roles with explicit permission scopes. The emerging SkillNet interchange format (referenced in multiple &lt;a href="https://gist.github.com/manduks/bb0a93c1e0eb21bc718a78ffdcefdc95" rel="noopener noreferrer"&gt;2026 framework comparisons&lt;/a&gt;) aims to make skills portable across frameworks, though adoption remains early.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill Runtime&lt;/strong&gt; handles execution context and memory access. This is where the tools/skills distinction matters most. A skill runtime provides: (1) access to episodic memory for retrieving relevant past experiences, (2) working memory for multi-step reasoning within the skill, and (3) tool delegation for invoking lower-level capabilities. &lt;a href="https://github.com/microsoft/autogen/discussions/7144" rel="noopener noreferrer"&gt;AutoGen's shared state discussions&lt;/a&gt; reveal the complexity here—agents need fine-grained control over which memories a skill can read versus modify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill Lifecycle&lt;/strong&gt; manages versioning, evaluation, and deprecation. &lt;a href="https://arxiv.org/html/2601.07136v1" rel="noopener noreferrer"&gt;Research on multi-agent system development&lt;/a&gt; found that 34% of production agent failures traced to skill version mismatches or unevaluated skill changes. Modern skill architectures treat skills like software packages: semantic versioning, dependency declarations, and explicit deprecation policies.&lt;/p&gt;

&lt;p&gt;The capability declaration pattern deserves special attention. Drawing from &lt;a href="https://arxiv.org/html/2603.20953v1" rel="noopener noreferrer"&gt;deterministic pre-action authorization research&lt;/a&gt;, skills now declare required permissions upfront. A "code review" skill might declare: &lt;code&gt;requires: [read:repository, read:pull_request, write:comments]&lt;/code&gt;. The runtime enforces these boundaries, preventing skill drift into unauthorized behaviors. This least-privilege approach—termed SkillScope in the authorization literature—is essential for enterprise deployments where audit requirements are strict.&lt;/p&gt;

&lt;p&gt;Composition primitives enable skills to work together. Skill chaining sequences capabilities (research → summarize → cite). Skill delegation allows one skill to invoke another (a "write report" skill delegating to "generate chart" skill). Skill fallback hierarchies provide graceful degradation (try "semantic search" skill, fall back to "keyword search" skill). These patterns are now supported natively in &lt;a href="https://www.datatrainersllc.com/blog/langchain-vs-langgraph-agents" rel="noopener noreferrer"&gt;LangGraph's agent framework&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skill Acquisition: How Agents Learn New Capabilities
&lt;/h2&gt;

&lt;p&gt;The most profound shift isn't just &lt;em&gt;having&lt;/em&gt; skills—it's how agents &lt;em&gt;acquire&lt;/em&gt; them. Three distinct pathways have emerged in 2026 research, each with different tradeoffs for production systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human-authored skills&lt;/strong&gt; remain the foundation. A developer writes skill code, defines the schema, and registers it with the agent. This approach offers maximum control and reliability but scales poorly. &lt;a href="https://pub.towardsai.net/a-developers-guide-to-agentic-frameworks-in-2026-3f22a492dc3d" rel="noopener noreferrer"&gt;Framework comparison analyses&lt;/a&gt; note that human-authored skills typically require 2-4 hours of engineering time per skill, including testing and documentation. For core business logic, this investment makes sense. For long-tail capabilities, it's prohibitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demonstration-learned skills&lt;/strong&gt; represent the middle ground. The agent observes a human performing a task—watching tool invocations, reading decisions made, noting outcomes—and extracts a reusable skill representation. Research on &lt;a href="https://github.com/masamasa59/ai-agent-papers/blob/main/capability-papers/tool-use.md" rel="noopener noreferrer"&gt;tool use capabilities&lt;/a&gt; shows demonstration learning achieving 70-80% of human-authored skill quality with 10x less human effort. The key insight: demonstrations should capture not just &lt;em&gt;what&lt;/em&gt; was done, but &lt;em&gt;why&lt;/em&gt;—the decision points, the alternatives considered, the success criteria applied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-evolved skills&lt;/strong&gt; push further into autonomy. The agent generates skill candidates, tests them against task outcomes, and refines through reinforcement learning. &lt;a href="https://arxiv.org/html/2604.27859v3" rel="noopener noreferrer"&gt;Research on agentic reinforcement learning&lt;/a&gt; introduced GRPO (Group Relative Policy Optimization) for skill training, providing step-wise rewards for skill invocation decisions rather than just final task success. This enables agents to learn nuanced skill selection: when to use "precise search" vs. "exploratory search," when to delegate vs. handle directly.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://arxiv.org/html/2601.02749v1" rel="noopener noreferrer"&gt;challenges research&lt;/a&gt; on agentic AI's path forward emphasizes that self-evolved skills require robust evaluation infrastructure. Without it, agents can develop confidently wrong skills—capabilities that appear to work in training but fail catastrophically in production. The paper recommends a "skill quarantine" pattern: newly evolved skills run in shadow mode, their outputs logged but not acted upon, until evaluation metrics clear predetermined thresholds.&lt;/p&gt;

&lt;p&gt;A practical production pattern is emerging: start with human-authored core skills for critical paths, enable demonstration-learning for domain adaptation (letting power users teach the agent their workflows), and restrict self-evolution to well-bounded capability improvements. &lt;a href="https://arxiv.org/html/2512.17896v2" rel="noopener noreferrer"&gt;XAgen's explainability work&lt;/a&gt; provides tools for understanding &lt;em&gt;why&lt;/em&gt; a skill evolved in a particular direction, essential for maintaining trust in self-improving systems.&lt;/p&gt;

&lt;p&gt;The experience compression spectrum offers a useful mental model. Not every learning should become a skill. Some belong as episodic memories (specific instances to retrieve when relevant). Others crystallize into skills (reusable capabilities worth naming and versioning). A few should codify as rules (invariants that must always hold). The &lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;AI agent software architecture evolution&lt;/a&gt; paper provides decision heuristics: if you'd invoke the capability &amp;gt;100 times and it requires multi-step reasoning, it's a skill candidate.&lt;/p&gt;

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

&lt;p&gt;Let's build a skill-enabled research agent using current APIs. This example demonstrates the complete skill lifecycle: definition, registration, invocation, memory integration, and basic self-improvement.&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
Skill-enabled research agent using LangGraph and LangChain patterns.
Demonstrates: skill definition, composition, memory coupling, and evaluation.
Requires: langgraph&amp;gt;=0.5.0, langchain-core&amp;gt;=0.3.0, langchain-anthropic&amp;gt;=0.2.0
&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;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;Literal&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;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&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;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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&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;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;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="c1"&gt;# --- Skill Schema Definition ---
# Skills are more than tools: they declare capabilities, memory access, and composition rules
&lt;/span&gt;
&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SkillMetadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Metadata for skill versioning and governance.&lt;/span&gt;&lt;span class="sh"&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="n"&gt;version&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;# Semver: breaking changes in skills break agents
&lt;/span&gt;    &lt;span class="n"&gt;author&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;required_permissions&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;# SkillScope-style declarations
&lt;/span&gt;    &lt;span class="n"&gt;memory_access&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;none&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;read&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;read_write&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;delegatable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  &lt;span class="c1"&gt;# Can this skill invoke other skills?
&lt;/span&gt;
&lt;span class="nd"&gt;@dataclass&lt;/span&gt;  
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SkillExecutionContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Runtime context provided to skill during execution.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;episodic_memory&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;# Retrieved relevant past experiences
&lt;/span&gt;    &lt;span class="n"&gt;working_memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;  &lt;span class="c1"&gt;# Scratch space for multi-step reasoning
&lt;/span&gt;    &lt;span class="n"&gt;available_skills&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;# Skills this skill can delegate to
&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;# For evaluation and audit
&lt;/span&gt;
&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SkillResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Standardized skill output with provenance.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&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;sources_used&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="n"&gt;delegated_to&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 skills were invoked
&lt;/span&gt;    &lt;span class="n"&gt;memory_writes&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;# What should be persisted
&lt;/span&gt;    &lt;span class="n"&gt;execution_time_ms&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;tokens_used&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;# --- Concrete Skill Implementation ---
# A WebResearchSkill that demonstrates memory coupling and tool delegation
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WebResearchSkill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    A skill for conducting web research with memory and learning.
    Unlike a simple search tool, this skill:
    - Retrieves past research on similar topics from memory
    - Adapts search strategy based on what worked before
    - Persists successful research patterns for future use
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SkillMetadata&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;web_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;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;1.2.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;author&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_team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;required_permissions&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:web&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;read:memory&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;write:memory&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_access&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_write&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;delegatable&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="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;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ChatAnthropic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_tool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;callable&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;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&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;search_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;search_tool&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&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;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;depth&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;quick&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;standard&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;comprehensive&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;SkillExecutionContext&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;SkillResult&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 research with memory-informed strategy selection.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&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;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 1: Retrieve relevant past research from episodic memory
&lt;/span&gt;        &lt;span class="c1"&gt;# This is what distinguishes skills from tools
&lt;/span&gt;        &lt;span class="n"&gt;past_research&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="ow"&gt;in&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;episodic_memory&lt;/span&gt; 
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mem&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;skill&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;web_research&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; 
            &lt;span class="ow"&gt;and&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;_topic_similarity&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="n"&gt;mem&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="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.7&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 2: Adapt strategy based on past outcomes
&lt;/span&gt;        &lt;span class="c1"&gt;# If previous research on similar topics found certain sources reliable,
&lt;/span&gt;        &lt;span class="c1"&gt;# prioritize those sources
&lt;/span&gt;        &lt;span class="n"&gt;reliable_sources&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;_extract_reliable_sources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;past_research&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;search_strategy&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;_select_strategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reliable_sources&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 3: Execute search with adapted strategy
&lt;/span&gt;        &lt;span class="n"&gt;search_queries&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;_generate_queries&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="n"&gt;search_strategy&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="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sq&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;search_queries&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;self&lt;/span&gt;&lt;span class="p"&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="n"&gt;sq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reliable_sources&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="nf"&gt;extend&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;sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&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;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 4: Synthesize results using LLM
&lt;/span&gt;        &lt;span class="n"&gt;synthesis_prompt&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;_build_synthesis_prompt&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="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;past_research&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;self&lt;/span&gt;&lt;span class="p"&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;ainvoke&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="n"&gt;tokens&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="n"&gt;usage_metadata&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;total_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;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Step 5: Prepare memory writes for future skill invocations
&lt;/span&gt;        &lt;span class="c1"&gt;# This is skill learning: recording what worked for future use
&lt;/span&gt;        &lt;span class="n"&gt;memory_writes&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;skill&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;web_research&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="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;strategy_used&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;search_strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sources_found_useful&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;_identify_useful_sources&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="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;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;now&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcome_pending&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;# Will be updated based on user feedback
&lt;/span&gt;        &lt;span class="p"&gt;}]&lt;/span&gt;

        &lt;span class="n"&gt;execution_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&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;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;SkillResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;output&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;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;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;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;sources&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;confidence&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;_compute_confidence&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="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;sources_used&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;delegated_to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="n"&gt;memory_writes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;memory_writes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;execution_time_ms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;execution_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tokens_used&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tokens&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;_topic_similarity&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;q1&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;q2&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;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compute semantic similarity between queries. Simplified for example.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="c1"&gt;# In production: use embedding similarity
&lt;/span&gt;        &lt;span class="n"&gt;common_words&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;q1&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;q2&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;all_words&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;q1&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&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;q2&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;return&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;common_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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;all_words&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;all_words&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_extract_reliable_sources&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;past_research&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="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;Identify sources that proved useful in past research.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;source_scores&lt;/span&gt; &lt;span class="o"&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;research&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;past_research&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;source&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;research&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;sources_found_useful&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;source_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source_scores&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;source&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source_scores&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="n"&gt;key&lt;/span&gt;&lt;span class="o"&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="n"&gt;source_scores&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&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="mi"&gt;5&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;_select_strategy&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;depth&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;reliable_sources&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="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;Select search strategy based on depth and past learning.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;base_strategies&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;quick&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;max_queries&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&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_per_query&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&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;max_queries&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_results_per_query&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comprehensive&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;max_queries&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_results_per_query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_strategies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prioritized_sources&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;reliable_sources&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;

    &lt;span class="c1"&gt;# Additional helper methods omitted for brevity...
&lt;/span&gt;
&lt;span class="c1"&gt;# --- Skill Registration and Agent Assembly ---
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SkillRegistry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Registry for managing skill versions and dependencies.
    Implements the Fleet SkillAttachment pattern for version constraints.
    &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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_skills&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="nb"&gt;str&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;object&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="c1"&gt;# name -&amp;gt; version -&amp;gt; skill
&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;_active_versions&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="nb"&gt;str&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;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;  &lt;span class="c1"&gt;# name -&amp;gt; active version
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&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;skill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config_overrides&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;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="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Register a skill with optional configuration.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&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;_skills&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;_skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;meta&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="o"&gt;=&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;_skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;meta&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&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;skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;config_overrides&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;registered_at&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;now&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;# Set as active if no version active or this is newer
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&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;_active_versions&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;_active_versions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;meta&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_skill&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;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;version&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="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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;object&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 skill by name, optionally pinning version.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;target_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="ow"&gt;or&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;_active_versions&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;name&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;target_version&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;not&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;_skills&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;Skill &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; not 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;return&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;_skills&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;target_version&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# --- Skill-Based Agent State ---
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ResearchAgentState&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;State for the research agent with skill-aware fields.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;
    &lt;span class="n"&gt;current_task&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;skill_invocations&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;# Track which skills were used
&lt;/span&gt;    &lt;span class="n"&gt;episodic_memory&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;# Retrieved memories for context
&lt;/span&gt;    &lt;span class="n"&gt;pending_memory_writes&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;# Memories to persist after completion
&lt;/span&gt;
&lt;span class="c1"&gt;# --- Agent Construction ---
&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;skill_registry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SkillRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ChatAnthropic&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Build a LangGraph agent that selects and invokes skills.
    The agent decides WHICH skill to use; skills handle HOW to execute.
    &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;skill_selector&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;ResearchAgentState&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;ResearchAgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Agent decides which skill to invoke based on task and context.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

        &lt;span class="n"&gt;task&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_task&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_skills&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;web_research&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_analysis&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;summarization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# LLM decides which skill(s) to invoke
&lt;/span&gt;        &lt;span class="n"&gt;selection_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;Given this task: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Available skills: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;available_skills&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
Recent skill invocations: &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;skill_invocations&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;

Which skill should be invoked? Respond with JSON: {{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skill&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;name&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;params&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="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;llm&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="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;selection_prompt&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
        &lt;span class="n"&gt;selection&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="c1"&gt;# Get and execute the selected skill
&lt;/span&gt;        &lt;span class="n"&gt;skill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skill_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_skill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skill&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="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SkillExecutionContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;episodic_memory&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;episodic_memory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;working_memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
            &lt;span class="n"&gt;available_skills&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;available_skills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;trace_id&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;trace_&lt;/span&gt;&lt;span class="si"&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;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;timestamp&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;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;skill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&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="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="c1"&gt;# Update state with skill results
&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;skill_invocations&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;skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skill&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;params&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;params&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;result_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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokens&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="n"&gt;tokens_used&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;pending_memory_writes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;extend&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;memory_writes&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="nf"&gt;append&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="nf"&gt;str&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;output&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
&lt;/span&gt;    &lt;span class="n"&gt;workflow&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;ResearchAgentState&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="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;select_and_invoke_skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skill_selector&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="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;select_and_invoke_skill&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="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;select_and_invoke_skill&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="k"&gt;return&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;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code demonstrates several key patterns from the skill architecture: typed skill metadata with version and permission declarations, memory coupling where skills read from and write to episodic memory, and the separation between skill selection (agent's job) and skill execution (skill's job). The &lt;code&gt;SkillResult&lt;/code&gt; type ensures every skill invocation produces traceable, auditable output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluation and Governance: Making Skills Production-Ready
&lt;/h2&gt;

&lt;p&gt;Skills without evaluation are liabilities. The 2026 research landscape has produced several benchmarking frameworks that address different aspects of skill quality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;Framework evaluations&lt;/a&gt; have converged on five evaluation axes for production skills. &lt;strong&gt;Correctness&lt;/strong&gt; measures whether skill outputs meet acceptance criteria. &lt;strong&gt;Efficiency&lt;/strong&gt; tracks token and compute costs relative to output quality. &lt;strong&gt;Generalization&lt;/strong&gt; tests whether skills transfer to novel inputs within their intended domain. &lt;strong&gt;Composability&lt;/strong&gt; verifies that skills work correctly when chained with others. &lt;strong&gt;Safety&lt;/strong&gt; ensures skills operate within declared permission boundaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/html/2604.16646v1" rel="noopener noreferrer"&gt;Research on agentic frameworks&lt;/a&gt; introduced SkillGenBench, specifically measuring whether agents can create useful new skills. This matters for systems with self-evolution enabled: if your agent proposes skill refinements, you need automated evaluation of those proposals before promotion to production. SkillGenBench tests include held-out task sets, adversarial inputs designed to expose skill boundaries, and composition stress tests.&lt;/p&gt;

&lt;p&gt;For agents with continual learning, skill regression becomes a concern. &lt;a href="https://arxiv.org/html/2601.07136v1" rel="noopener noreferrer"&gt;Multi-agent system studies&lt;/a&gt; found that 23% of skill updates introduced regressions in other skills—a new research skill that searches more thoroughly might break a summarization skill's token budget assumptions. SkillLearnBench provides regression testing protocols: after any skill change, re-evaluate not just that skill but all skills that compose with it.&lt;/p&gt;

&lt;p&gt;Governance primitives are equally important for enterprise deployments. &lt;a href="https://arxiv.org/html/2512.17896v2" rel="noopener noreferrer"&gt;Research on explainability&lt;/a&gt; introduced Counterfactual Trace Auditing: given a skill execution trace, determine what would have happened with different inputs or different skill versions. This supports both debugging ("why did the research skill produce wrong results?") and compliance ("can we prove the skill never accessed unauthorized data?").&lt;/p&gt;

&lt;p&gt;The least-privilege enforcement pattern from &lt;a href="https://arxiv.org/html/2603.20953v1" rel="noopener noreferrer"&gt;authorization research&lt;/a&gt; deserves implementation from day one. Skills declare permissions; runtime enforces them. A skill claiming &lt;code&gt;read:memory&lt;/code&gt; cannot write to memory, even if it contains code attempting to do so. The enforcement layer intercepts all memory and tool access, checking against declared permissions. This prevents both accidental scope creep and adversarial prompt injection attacks that try to escalate skill privileges.&lt;/p&gt;

&lt;p&gt;Cost attribution often gets overlooked until bills arrive. Skills should report token usage, and the orchestration layer should aggregate costs per skill per task type. &lt;a href="https://www.langchain.com/blog/nvidia-enterprise" rel="noopener noreferrer"&gt;Enterprise platform discussions&lt;/a&gt; emphasize that skill-level cost visibility enables optimization: if your research skill costs 10x your analysis skill but delivers only 2x the value, that's actionable intelligence.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;If you're starting a new agent project&lt;/strong&gt;, choose a framework with first-class skill support. &lt;a href="https://www.langchain.com/blog/march-2026-langchain-newsletter" rel="noopener noreferrer"&gt;LangChain's Deep Agents&lt;/a&gt;, &lt;a href="https://venturebeat.com/ai/crewai-launches-its-first-multi-agent-builder-speeding-the-way-to-agentic-ai" rel="noopener noreferrer"&gt;CrewAI Enterprise&lt;/a&gt;, and &lt;a href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/advanced-function-calling-and-multi-agent-systems-with-small-language-models-in-/4481180" rel="noopener noreferrer"&gt;Microsoft Foundry&lt;/a&gt; all offer skill primitives. Retrofitting skill abstractions onto tool-based agents requires rearchitecting memory access patterns and state management—it's substantially harder than building with skills from the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have existing tool-based agents&lt;/strong&gt;, begin migrating high-value tool chains to skill abstractions incrementally. Start with tools that have implicit memory dependencies: anything that benefits from "remembering" past invocations. A search tool becomes a research skill when it tracks which sources proved reliable. A code generation tool becomes a coding skill when it learns from past review feedback. The &lt;a href="https://arxiv.org/html/2602.10479v1" rel="noopener noreferrer"&gt;evolution of agent architectures&lt;/a&gt; provides migration patterns for this transition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill versioning strategy&lt;/strong&gt; requires treating skills like npm packages. Use semantic versioning: patch versions for bug fixes, minor versions for backward-compatible capability additions, major versions for breaking changes. Maintain lockfiles that pin skill versions per deployment. Establish deprecation policies—how long do you support old skill versions? &lt;a href="https://alicelabs.ai/en/insights/best-ai-agent-frameworks-2026" rel="noopener noreferrer"&gt;Production rankings&lt;/a&gt; show that teams with explicit versioning policies experience 60% fewer production incidents from skill changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evaluation investment&lt;/strong&gt; scales with skill complexity. Skill-based agents require skill-level evaluation, not just end-to-end task success. If your research agent fails, you need to know whether the research skill failed, the synthesis skill failed, or the composition logic failed. Budget for evaluation infrastructure—expect 15-20% of agent development effort to go toward testing and benchmarking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security implications&lt;/strong&gt; are substantial. Skills with memory access and tool delegation are powerful attack surfaces. A compromised skill can exfiltrate data through memory writes, escalate privileges through delegation, or persist malicious patterns for future invocations. Implement permission enforcement from day one; adding it later requires auditing every existing skill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team structure&lt;/strong&gt; may need adjustment. Skills create natural ownership boundaries. Consider a skill ownership model similar to microservice ownership: designated maintainers, explicit SLOs, documented interfaces. &lt;a href="https://github.com/orgs/community/discussions/187143" rel="noopener noreferrer"&gt;Developer tool discussions&lt;/a&gt; suggest that teams with clear skill ownership see faster iteration and fewer cross-cutting bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline expectations&lt;/strong&gt;: Skill architectures are production-ready now, but expect significant API churn through 2026. Abstract your skill interfaces—depend on your own skill protocols, not framework-specific implementations directly. The SkillNet interchange format may stabilize by Q4 2026, at which point portability across frameworks becomes practical.&lt;/p&gt;

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

&lt;p&gt;Build a &lt;strong&gt;skill-enabled personal research assistant&lt;/strong&gt; that demonstrates the tools-to-skills evolution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with a basic research agent using standard tools (web search, document reading)&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;SkillRegistry&lt;/code&gt; and migrate web search to a &lt;code&gt;WebResearchSkill&lt;/code&gt; with memory coupling&lt;/li&gt;
&lt;li&gt;Implement episodic memory that tracks: which sources proved useful, which search strategies worked for different query types, which results the user marked as helpful&lt;/li&gt;
&lt;li&gt;Add skill-level evaluation: track correctness (did the user accept the research?), efficiency (tokens per useful result), and generalization (does the skill work on new topic domains?)&lt;/li&gt;
&lt;li&gt;Implement one round of demonstration learning: record yourself researching a topic, have the agent extract a skill refinement, evaluate whether the refinement improves outcomes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The complete implementation should take 8-12 hours. By the end, you'll have hands-on experience with skill schemas, memory coupling patterns, and the evaluation infrastructure that makes skills production-ready. More importantly, you'll understand &lt;em&gt;why&lt;/em&gt; the industry is converging on this abstraction—and be ready to apply it to your production systems.&lt;/p&gt;




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

&lt;ul&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://www.langchain.com/blog/nvidia-enterprise" rel="noopener noreferrer"&gt;LangChain Announces Enterprise Agentic AI Platform Built with NVIDIA&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://www.datatrainersllc.com/blog/langchain-vs-langgraph-agents" rel="noopener noreferrer"&gt;LangChain vs LangGraph 2026: Which AI Agent Framework?&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 by Alice Labs&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/microsoft/autogen/discussions/7144" rel="noopener noreferrer"&gt;Handling shared state across multi-agent conversations in AutoGen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://venturebeat.com/ai/crewai-launches-its-first-multi-agent-builder-speeding-the-way-to-agentic-ai" rel="noopener noreferrer"&gt;CrewAI now lets you build fleets of enterprise AI agents | VentureBeat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2512.17896v2" rel="noopener noreferrer"&gt;XAgen: An Explainability Tool for Identifying and Correcting Failures in Multi-Agent Workflows&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;li&gt;&lt;a href="https://arxiv.org/html/2603.20953v1" rel="noopener noreferrer"&gt;Deterministic Pre-Action Authorization for Autonomous AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcommunity.microsoft.com/blog/educatordeveloperblog/advanced-function-calling-and-multi-agent-systems-with-small-language-models-in-/4481180" rel="noopener noreferrer"&gt;Advanced Function Calling and Multi-Agent Systems with Small Language Models in Foundry Local&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 at main - 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&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/weitianxin/Awesome-Agentic-Reasoning" rel="noopener noreferrer"&gt;Awesome Agentic Reasoning Papers - GitHub&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&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2604.27859v3" rel="noopener noreferrer"&gt;Rethinking Agentic Reinforcement Learning In Large Language Models&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 Applications&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;/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: What Are Your Must-Have...&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 Roundup: Google Reimagines Search, OpenAI Ships Steerable Coding Agents, and Multi-Agent Systems Hit Production</title>
      <dc:creator>Richard Dillon</dc:creator>
      <pubDate>Mon, 25 May 2026 12:05:31 +0000</pubDate>
      <link>https://dev.to/richard_dillon_b9c238186e/ai-weekly-roundup-google-reimagines-search-openai-ships-steerable-coding-agents-and-multi-agent-319f</link>
      <guid>https://dev.to/richard_dillon_b9c238186e/ai-weekly-roundup-google-reimagines-search-openai-ships-steerable-coding-agents-and-multi-agent-319f</guid>
      <description>&lt;h1&gt;
  
  
  AI Weekly Roundup: Google Reimagines Search, OpenAI Ships Steerable Coding Agents, and Multi-Agent Systems Hit Production
&lt;/h1&gt;

&lt;p&gt;The week of May 25, 2026 marks an inflection point in how we interact with AI systems. Google's I/O announcements signal the death of the search box as we've known it for a quarter century, while OpenAI's GPT-5.3-Codex represents the maturation of coding assistants into genuine collaborative agents. Meanwhile, the enterprise world is getting real about what agentic AI means for workforces—and the answers aren't always comfortable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Rewrites the Search Playbook with AI Agents at I/O 2026
&lt;/h2&gt;

&lt;p&gt;Google unveiled its most significant Search transformation in over 25 years at I/O 2026, introducing &lt;a href="https://techcrunch.com/2026/05/19/how-to-use-googles-new-ai-agents-to-go-beyond-your-standard-searches" rel="noopener noreferrer"&gt;"information agents"&lt;/a&gt; that fundamentally change the relationship between users and information retrieval. These agents operate continuously in the background, monitoring topics of interest around the clock without requiring repeated manual searches—a shift from reactive querying to proactive intelligence gathering.&lt;/p&gt;

&lt;p&gt;The centerpiece is a redesigned "intelligent search box" that supports &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;longer conversational queries&lt;/a&gt; with an AI-powered suggestion system. Rather than optimizing for keywords, users can now express complex information needs in natural language, with the system understanding context and intent across multi-turn interactions.&lt;/p&gt;

&lt;p&gt;This represents Google's clearest articulation yet of the &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;agentic AI paradigm&lt;/a&gt;: systems that take initiative rather than passively waiting for prompts. The implications extend beyond convenience—information agents could reshape how professionals conduct research, how consumers make purchasing decisions, and how news consumption patterns evolve. Google is betting that users want AI systems working on their behalf even when they're not actively engaged, a significant assumption about user trust and privacy expectations that will face real-world testing in the months ahead.&lt;/p&gt;

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

&lt;p&gt;Multi-agent architectures have definitively moved from research curiosity to &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;production standard&lt;/a&gt;. The dominant pattern emerging involves orchestrator agents coordinating specialized sub-agents working in parallel, each operating within dedicated context windows optimized for their specific tasks. This hierarchical approach addresses the context length limitations and specialization tradeoffs that hampered earlier monolithic agent designs.&lt;/p&gt;

&lt;p&gt;Real-world results are validating the approach. Fountain achieved &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;50% faster screening&lt;/a&gt; and reduced fulfillment center staffing timelines from weeks to under 72 hours using hierarchical multi-agent orchestration. Perhaps more striking, Zapier deployed &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;over 800 AI agents internally&lt;/a&gt; with 89% AI adoption across the entire organization—demonstrating that agent proliferation can scale within a single enterprise.&lt;/p&gt;

&lt;p&gt;The framework landscape continues maturing with clearer differentiation: &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt; dominates graph-based orchestration, &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt; leads for role-based crew configurations, the &lt;a href="https://github.com/ARUNAGIRINATHAN-K/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;OpenAI Agents SDK&lt;/a&gt; has succeeded Swarm for OpenAI-native development, and &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;Microsoft Agent Framework&lt;/a&gt; merges Semantic Kernel and AutoGen capabilities.&lt;/p&gt;

&lt;p&gt;The AAAI 2026 Bridge Program on &lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;Advancing LLM-Based Multi-Agent Systems&lt;/a&gt; highlights critical infrastructure gaps: BDI (belief-desire-intention) architectures, standardized communication protocols, and mechanism design principles are essential to make agentic systems transparent and accountable as they move into high-stakes domains.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Launches GPT-5.3-Codex: From Code Generation to Steerable Coding Agent
&lt;/h2&gt;

&lt;p&gt;OpenAI's &lt;a href="https://help.openai.com/en/articles/9624314-model-release-notes" rel="noopener noreferrer"&gt;GPT-5.3-Codex release&lt;/a&gt; represents the first model to combine the Codex and GPT-5 training stacks, unifying specialized code generation capabilities with advanced reasoning and general-purpose intelligence. The result is approximately 25% faster than predecessors while achieving new benchmark highs across coding evaluations.&lt;/p&gt;

&lt;p&gt;The more significant shift is conceptual. OpenAI is positioning GPT-5.3-Codex not as a code completion tool but as a &lt;a href="https://developers.openai.com/blog/openai-for-developers-2025" rel="noopener noreferrer"&gt;"general-purpose coding agent you can actively steer while it works"&lt;/a&gt;. This framing reflects the broader industry transition from AI as autocomplete to AI as collaborator—systems that maintain context across sessions, understand project-level architecture, and can be directed mid-task without losing thread.&lt;/p&gt;

&lt;p&gt;The practical implications align with patterns documented in 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;: developers increasingly want AI that can handle multi-file refactoring, maintain consistency across codebases, and explain its reasoning when asked. OpenAI is also &lt;a href="https://help.openai.com/en/articles/9624314-model-release-notes" rel="noopener noreferrer"&gt;retiring GPT-4o and legacy models&lt;/a&gt; as of February 2026, forcing migration and signaling confidence in the new architecture. The deprecation timeline gives enterprises six months to adapt their integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jensen Huang Identifies $200 Billion "Brand New" Market for NVIDIA
&lt;/h2&gt;

&lt;p&gt;NVIDIA CEO Jensen Huang publicly announced the discovery of a substantial &lt;a href="https://www.bloomberg.com/news/videos/2026-05-21/the-next-phase-of-artificial-intelligence" rel="noopener noreferrer"&gt;new market opportunity&lt;/a&gt; valued at approximately $200 billion for the company. While Huang kept specific details characteristically vague, the announcement follows NVIDIA's established playbook of positioning itself at the center of emerging AI infrastructure buildout phases.&lt;/p&gt;

&lt;p&gt;Industry analysts speculate the opportunity relates to &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;agentic AI infrastructure&lt;/a&gt;—the compute, memory, and networking requirements to run persistent agent systems at scale differ substantially from the batch inference workloads that dominated earlier AI deployment. Continuous agent operation demands different latency profiles and memory persistence than traditional model serving.&lt;/p&gt;

&lt;p&gt;The timing coincides with surging demand for AI chips across the industry, with hyperscalers, enterprises, and sovereign AI initiatives all competing for supply. NVIDIA's GPU dominance faces increasing pressure from custom silicon (Google TPUs, Amazon Trainium, Microsoft Maia), but Huang's announcement suggests NVIDIA sees expansion opportunities beyond current competitive battlegrounds. Whether this represents a new hardware architecture, software platform play, or market adjacency remains unclear until the company's next formal disclosure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sam Altman Extends "Mic Drop" Offer to Every Y Combinator Startup
&lt;/h2&gt;

&lt;p&gt;OpenAI CEO Sam Altman made a significant &lt;a href="https://techcrunch.com/category/artificial-intelligence" rel="noopener noreferrer"&gt;blanket offer&lt;/a&gt; to all Y Combinator portfolio companies, positioning OpenAI as the default AI infrastructure provider for the startup ecosystem's most influential accelerator. The specifics involve substantial API credits and preferential pricing designed to capture developer mindshare at the earliest company stages.&lt;/p&gt;

&lt;p&gt;This represents a strategic play with long-term competitive implications. Startups that build on OpenAI APIs during their formative development create &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;switching costs&lt;/a&gt; that persist as they scale—prompt engineering, fine-tuning investments, and integration patterns all create lock-in. By subsidizing early adoption, OpenAI trades near-term revenue for future market position.&lt;/p&gt;

&lt;p&gt;The move could reshape competitive dynamics for AI API providers targeting emerging companies. Anthropic, Google, and open-source alternatives must now consider whether to match the offer or differentiate on technical merits alone. For YC companies, the offer removes one barrier to AI-native product development, though founders should consider the concentration risk of deep dependence on any single provider. The timing suggests OpenAI views the enterprise and startup channels as complementary growth vectors requiring distinct go-to-market approaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Launches Antigravity 2.0 with Desktop App and CLI at I/O 2026
&lt;/h2&gt;

&lt;p&gt;Google's &lt;a href="https://github.com/orgs/community/discussions/187143" rel="noopener noreferrer"&gt;Antigravity 2.0 release&lt;/a&gt; at I/O 2026 includes both a desktop application and command-line interface tool, expanding accessibility across different developer workflows. The update addresses feedback that the original web-only interface limited integration with existing development environments and automation pipelines.&lt;/p&gt;

&lt;p&gt;The CLI addition particularly matters for &lt;a href="https://github.com/ShaikhWarsi/free-ai-tools" rel="noopener noreferrer"&gt;developer tooling&lt;/a&gt; integration, enabling Antigravity capabilities within shell scripts, CI/CD pipelines, and editor extensions. This follows the pattern established by GitHub Copilot CLI and similar tools—meeting developers in their existing environments rather than requiring context switches to web interfaces.&lt;/p&gt;

&lt;p&gt;The desktop app provides offline capability and reduced latency for common operations, addressing reliability concerns for developers with inconsistent connectivity or privacy requirements for certain codebases. Combined with Google's agentic AI announcements, Antigravity 2.0 suggests a coherent strategy: intelligent agents for research and planning, practical developer tools for implementation. The framework landscape now includes &lt;a href="https://huggingface.co/blog/huggingface/state-of-os-hf-spring-2026" rel="noopener noreferrer"&gt;comprehensive options&lt;/a&gt; from every major AI provider, with Google's dual-interface approach attempting to minimize adoption friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  SoMe Benchmark: New Standard for Evaluating Social Media AI Agents
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/LivXue/SoMe" rel="noopener noreferrer"&gt;SoMe benchmark&lt;/a&gt; released at AAAI 2026 provides the first standardized framework for testing LLM-based agents in realistic social media scenarios. As social media automation becomes increasingly prevalent—for content moderation, engagement analysis, and yes, manipulation—the lack of evaluation standards has made comparing systems and identifying risks difficult.&lt;/p&gt;

&lt;p&gt;SoMe evaluates agents across &lt;a href="https://arxiv.org/list/cs.AI/new" rel="noopener noreferrer"&gt;eight key tasks&lt;/a&gt; covering diverse aspects of social media intelligence: content generation, engagement prediction, misinformation detection, sentiment analysis, trend identification, community modeling, influence measurement, and crisis response. The benchmark includes a diverse collection of test scenarios designed to stress-test agents across edge cases and adversarial conditions.&lt;/p&gt;

&lt;p&gt;The timing matters as &lt;a href="https://www.firecrawl.dev/blog/agentic-ai-trends" rel="noopener noreferrer"&gt;enterprises deploy&lt;/a&gt; social media agents for customer service, reputation management, and market intelligence. Without standardized evaluation, organizations have struggled to assess vendor claims or compare in-house solutions against commercial offerings. SoMe also provides researchers with common ground for publishing reproducible results, potentially accelerating progress while also surfacing capability limitations and failure modes that matter for responsible deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Banking Sector Confronts AI Workforce Transition
&lt;/h2&gt;

&lt;p&gt;The financial services sector emerged this week as an early battleground for AI-driven organizational restructuring, with two major banks publicly addressing workforce implications. HSBC CEO told staff &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;"don't fight AI"&lt;/a&gt; as the bank implements job cuts, while StanChart CEO apologized for "upset caused" amid similar changes.&lt;/p&gt;

&lt;p&gt;These announcements mark a shift from AI experimentation to &lt;a href="https://www.reuters.com/technology/artificial-intelligence" rel="noopener noreferrer"&gt;operational deployment&lt;/a&gt; with real workforce consequences. Banking offers a preview of broader enterprise patterns: highly compensated knowledge work, extensive documentation for training data, clear metrics for measuring productivity gains, and regulated environments that require careful change management.&lt;/p&gt;

&lt;p&gt;The executive messaging reveals corporate strategies for managing the transition: HSBC's directive frames resistance as futile while positioning adaptation as career protection, whereas StanChart's apology acknowledges the human cost while implying inevitability. Neither approach resolves underlying tensions about pace of change, retraining investments, or social contracts with existing employees.&lt;/p&gt;

&lt;p&gt;For the broader tech industry, banking's experience suggests that agentic AI deployment will require sophisticated organizational change management, not just technical implementation. The &lt;a href="https://futureagi.com/blog/multi-agent-systems-2025" rel="noopener noreferrer"&gt;multi-agent systems&lt;/a&gt; replacing human workflows require human oversight structures that most organizations haven't yet designed.&lt;/p&gt;

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

&lt;p&gt;Google's agent rollout will face its first real user feedback in coming weeks—watch for adoption metrics and privacy backlash indicators. OpenAI's legacy model deprecation timeline creates a forcing function for enterprise migration decisions, which could surface production dependencies that aren't yet visible. And as banking workforce impacts become quantified, expect regulatory attention to intensify around AI's labor market effects, potentially shaping how quickly other sectors proceed with similar transformations.&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://www.bloomberg.com/news/videos/2026-05-21/the-next-phase-of-artificial-intelligence" rel="noopener noreferrer"&gt;Watch The Next Phase of Artificial Intelligence - Bloomberg.com&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/2026/05/19/how-to-use-googles-new-ai-agents-to-go-beyond-your-standard-searches" rel="noopener noreferrer"&gt;How to use Google's new AI agents to go beyond your standard searches | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/list/cs.AI/new" rel="noopener noreferrer"&gt;Artificial Intelligence&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://resources.anthropic.com/hubfs/2026%20Agentic%20Coding%20Trends%20Report.pdf" rel="noopener noreferrer"&gt;[PDF] 2026 Agentic Coding Trends Report - Anthropic&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 11 Agentic AI Trends to Watch in 2026 - Firecrawl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ARUNAGIRINATHAN-K/awesome-ai-agents-2026" rel="noopener noreferrer"&gt;GitHub - ARUNAGIRINATHAN-K/awesome-ai-agents-2026: Awesome AI Agents for 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/html/2511.17332v2" rel="noopener noreferrer"&gt;AAAI 2026 Bridge Program on Advancing LLM-Based Multi-Agent Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/blog/huggingface/state-of-os-hf-spring-2026" rel="noopener noreferrer"&gt;State of Open Source on Hugging Face: Spring 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/LivXue/SoMe" rel="noopener noreferrer"&gt;GitHub - LivXue/SoMe: (AAAI 2026) SoMe: A Realistic Benchmark for LLM-based Social Media Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.openai.com/en/articles/9624314-model-release-notes" rel="noopener noreferrer"&gt;Model Release Notes | OpenAI Help Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/orgs/community/discussions/187143" rel="noopener noreferrer"&gt;Best AI Tools for Developers in 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ShaikhWarsi/free-ai-tools" rel="noopener noreferrer"&gt;GitHub - ShaikhWarsi/free-ai-tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://developers.openai.com/blog/openai-for-developers-2025" rel="noopener noreferrer"&gt;OpenAI for Developers in 2025&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>
  </channel>
</rss>
