<?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: Julio Quinteros P.</title>
    <description>The latest articles on DEV Community by Julio Quinteros P. (@julio_quinterosp_d203b6).</description>
    <link>https://dev.to/julio_quinterosp_d203b6</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%2F3288414%2F7509d247-caf0-4422-9175-7eb0b83e3f86.jpg</url>
      <title>DEV Community: Julio Quinteros P.</title>
      <link>https://dev.to/julio_quinterosp_d203b6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/julio_quinterosp_d203b6"/>
    <language>en</language>
    <item>
      <title>Comparing Orchestration Patterns in Google ADK: Multi-Agent vs. Workflow-Based Loops</title>
      <dc:creator>Julio Quinteros P.</dc:creator>
      <pubDate>Tue, 28 Jul 2026 22:55:41 +0000</pubDate>
      <link>https://dev.to/julio_quinterosp_d203b6/comparing-orchestration-patterns-in-google-adk-multi-agent-vs-workflow-based-loops-1e5f</link>
      <guid>https://dev.to/julio_quinterosp_d203b6/comparing-orchestration-patterns-in-google-adk-multi-agent-vs-workflow-based-loops-1e5f</guid>
      <description>&lt;p&gt;A practical study on structured vs. dynamic agent routing, based on Google Skills Lab GENAI106.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As agentic AI matures, developers face a critical design decision: &lt;strong&gt;How should agents orchestrate tasks?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In this article, we explore the two primary orchestration architectures provided by the &lt;strong&gt;Google Agent Development Kit (ADK)&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Multi-Agent Routing:&lt;/strong&gt; A hierarchical setup where LLM agents dynamically decide who to transfer control to using injected tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequential Workflow Loops (&lt;code&gt;LoopAgent&lt;/code&gt;):&lt;/strong&gt; A structured setup where execution flows in a pre-defined sequence of nodes using a shared session state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To compare these patterns, we built a mathematical expression parser. Solving an expression like &lt;code&gt;((12 + 8) * 5) - (10 / 2) + (4 * 6) - (50 / 5)&lt;/code&gt; requires coordinating four specialists: &lt;code&gt;adder&lt;/code&gt;, &lt;code&gt;substracter&lt;/code&gt;, &lt;code&gt;multiplier&lt;/code&gt;, and &lt;code&gt;divider&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This study is adapted and extended from the code lab **GENAI106: Build Multi-Agent Systems with ADK&lt;/em&gt;* on the &lt;a href="https://www.skills.google/catalog?keywords=GENAI106" rel="noopener noreferrer"&gt;skills.google&lt;/a&gt; platform.*&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture 1: Dynamic Multi-Agent Routing (&lt;code&gt;parent_and_subagents&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;In the dynamic multi-agent pattern, a central &lt;strong&gt;&lt;code&gt;steering&lt;/code&gt;&lt;/strong&gt; coordinator receives the user input and delegates operations to specialist sub-agents based on mathematical precedence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6vctq5jf345sw1fp7uxd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6vctq5jf345sw1fp7uxd.jpg" alt="Multi-agent architecture diagram" width="799" height="290"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    User([User Expression]) --&amp;gt; Steering[steering coordinator]
    Steering --&amp;gt;|transfer_to_agent| Adder[adder specialist]
    Steering --&amp;gt;|transfer_to_agent| Substracter[substracter specialist]
    Steering --&amp;gt;|transfer_to_agent| Multiplier[multiplier specialist]
    Steering --&amp;gt;|transfer_to_agent| Divider[divider specialist]

    Adder --&amp;gt;|transfer_to_agent| Steering
    Substracter --&amp;gt;|transfer_to_agent| Steering
    Multiplier --&amp;gt;|transfer_to_agent| Steering
    Divider --&amp;gt;|transfer_to_agent| Steering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Control Transfer Flow
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When &lt;code&gt;steering&lt;/code&gt; routes an expression to a specialist (e.g., &lt;code&gt;adder&lt;/code&gt;), control is transferred.&lt;/li&gt;
&lt;li&gt;When the specialist finishes simplifying its part of the expression, it transfers control back to its parent:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# adk_multiagent_systems/parent_and_subagents/agent.py
&lt;/span&gt;  &lt;span class="c1"&gt;# adder instruction:
&lt;/span&gt;  &lt;span class="c1"&gt;# "Once you have performed the additions, transfer control back to the 'steering' agent using the 'transfer_to_agent' tool."
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Highly flexible. The LLM dynamically decides the best path and delegates recursively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; High latency due to constant peer-to-peer routing calls.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Architecture 2: Structured Workflow Loops (&lt;code&gt;workflow_agents&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;In the workflow pattern, a &lt;strong&gt;&lt;code&gt;LoopAgent&lt;/code&gt;&lt;/strong&gt; coordinates execution sequentially in a fixed, predefined loop (&lt;code&gt;adder&lt;/code&gt; ➔ &lt;code&gt;substracter&lt;/code&gt; ➔ &lt;code&gt;multiplier&lt;/code&gt; ➔ &lt;code&gt;divider&lt;/code&gt;), passing state updates via a shared key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6vjt9gs1g2777yapkk5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh6vjt9gs1g2777yapkk5.jpg" alt="Workflow-agent architecture diagram" width="800" height="372"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    User([User Expression]) --&amp;gt; WSteering[workflow_steering coordinator]
    WSteering --&amp;gt;|transfer_to_agent| Loop[calculator_loop LoopAgent]

    subgraph calculator_loop
        Adder[adder] --&amp;gt; Substracter[substracter]
        Substracter --&amp;gt; Multiplier[multiplier]
        Multiplier --&amp;gt; Divider[divider]
        Divider --&amp;gt;|Loops back| Adder
    end

    calculator_loop -.-&amp;gt;|exit_loop| WSteering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Shared Session State
&lt;/h3&gt;

&lt;p&gt;Instead of returning values directly, the workflow agents read and update a shared key (&lt;code&gt;expression&lt;/code&gt;) in the session state using a custom tool:&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;update_expression&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ToolContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expression&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;tool_context&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;expression&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;expression&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;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;success&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 Loop terminates when a specialist detects that the expression has been reduced to a single number and calls the ADK built-in tool &lt;code&gt;exit_loop&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Challenges &amp;amp; Hard-Won Lessons
&lt;/h2&gt;

&lt;p&gt;When transitioning the calculator to a &lt;code&gt;LoopAgent&lt;/code&gt; workflow, we encountered three main challenges:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Tool Loop Recurrence Issue
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; LLM agents generate tool calls in a loop within a single turn until they output text. Because the system instruction containing &lt;code&gt;{ expression? }&lt;/code&gt; is static for the duration of the turn, the LLM kept calling &lt;code&gt;update_expression&lt;/code&gt; recursively with the same values.&lt;br&gt;
&lt;strong&gt;The Solution:&lt;/strong&gt; We modified the instructions to enforce turn termination immediately after updating the state:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"- After calling the 'update_expression' tool, output the updated expression as text and end your turn. Do NOT call the tool again."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  2. Operator Precedence in Fixed Sequences
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; A loop agent runs specialists in a strict order. If &lt;code&gt;adder&lt;/code&gt; runs before &lt;code&gt;substracter&lt;/code&gt;, an expression like &lt;code&gt;100 - 5 + 24 - 10&lt;/code&gt; would incorrectly evaluate &lt;code&gt;5 + 24 = 29&lt;/code&gt; first, leading to &lt;code&gt;100 - 29 - 10 = 61&lt;/code&gt; (instead of &lt;code&gt;109&lt;/code&gt;).&lt;br&gt;
&lt;strong&gt;The Solution:&lt;/strong&gt; We instructed &lt;code&gt;adder&lt;/code&gt; to respect order of operations:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"- Do NOT perform additions if they are immediately preceded by a subtraction (e.g., in '100 - 5 + 24', you must NOT add 5 + 24 because the minus sign belongs to 5)."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  3. Graceful Loop Termination
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Calling &lt;code&gt;exit_loop()&lt;/code&gt; sets &lt;code&gt;skip_summarization = True&lt;/code&gt;, terminating the run immediately. If the agent doesn't print the result first, the session closes silently.&lt;br&gt;
&lt;strong&gt;The Solution:&lt;/strong&gt; Instruct the resolving agent to output the final result &lt;em&gt;before&lt;/em&gt; calling &lt;code&gt;exit_loop&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"- If the expression is reduced to a single number, output the final result clearly (e.g. 'El resultado es X') and call the 'exit_loop' tool."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Showcasing Hierarchical Nested Sub-Agents: &lt;code&gt;zero_division_guard&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;To demonstrate deep agent hierarchies and error boundary handling, we added a nested validation guard (&lt;code&gt;zero_division_guard&lt;/code&gt;) under the &lt;code&gt;divider&lt;/code&gt; specialist. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5gmb4zg2e43qt7wjssru.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5gmb4zg2e43qt7wjssru.jpg" alt="A use case: the almighty division by zero" width="800" height="903"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    Divider[divider] --&amp;gt;|transfer_to_agent| Guard[zero_division_guard]
    Guard --&amp;gt;|Validation Failed| Error[Abort &amp;amp; Exit]
    Guard --&amp;gt;|Validation Passed| Divider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before performing any division, &lt;code&gt;divider&lt;/code&gt; delegates to &lt;code&gt;zero_division_guard&lt;/code&gt; using &lt;code&gt;transfer_to_agent&lt;/code&gt;. The guard checks the divisor (denominator):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the divisor evaluates to zero (e.g., &lt;code&gt;10 / 0&lt;/code&gt;), it aborts execution and outputs a warning.&lt;/li&gt;
&lt;li&gt;If it is safe, it transfers control back to &lt;code&gt;divider&lt;/code&gt; to complete the calculation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Integration Test Trace (Multi-Agent):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running: .venv/bin/adk run adk_multiagent_systems/parent_and_subagents "Please evaluate 10 / 0"
[zero_division_guard]: Error: Division by zero detected. Operation cancelled.
[divider]: Error: Division by zero detected. Operation cancelled.
[steering]: Error: Division by zero detected. Operation cancelled.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integration Test Trace (Workflow):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running: .venv/bin/adk run adk_multiagent_systems/workflow_agents "Please evaluate 10 / 0"
[zero_division_guard]: Error: Division by zero detected. Operation cancelled.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Google ADK provides powerful primitives for both dynamic multi-agent architectures and deterministic workflow sequences. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Multi-Agent Routing&lt;/strong&gt; when tasks are highly dynamic, branch unpredictably, and benefit from conversational flexibility.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Workflow Loops&lt;/strong&gt; when you have a structured, multi-step pipeline where reliability, fixed sequencing, and state-based progression are paramount.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>adk</category>
      <category>ai</category>
      <category>googlecloud</category>
      <category>gcp</category>
    </item>
  </channel>
</rss>
