close

DEV Community

Cover image for The (no longer) missing multi-agent pattern: triggering dynamic workflows from an agent
Remigiusz Samborski for Google AI

Posted on • Originally published at x.com

The (no longer) missing multi-agent pattern: triggering dynamic workflows from an agent

When building multi-agent systems, rigid state graphs quickly fall apart in the face of dynamic user inputs. Imagine building a smart assistant: a user hands you a checklist of three household chores today, but tomorrow it might be a list of ten software debugging tasks. Because the number of tasks, their sequence, and their execution details are entirely runtime-dependent, you cannot hardcode this path at design time. Forcing dynamic lists of work into a static graph-based workflow can lead to fragile, over-engineered code. You need a workflow that adapts dynamically at runtime.

The Google Agent Development Kit (ADK) provides a flexible programming model to define dynamic workflows. With the release of ADK 2.4.0, triggering these workflows has become even more seamless: you can register a Workflow directly in an agent's tools list, allowing the coordinator agent to execute it automatically as a first-class tool.

In this article, you learn how to configure and trigger a dynamic workflow directly from a coordinator agent. This guide uses a task list coordination example, but you can adjust this pattern to other dynamic orchestration needs.

The architecture of a dynamic workflow

Static workflows define the execution path at design time. Dynamic workflows, however, allow agents to invoke tools, spawn other nodes, and schedule sub-agents conditionally at runtime.

The system consists of three main components:

  1. Root agent (root_agent): Gathers the list of tasks from the user, requests final approval, and directly calls the tasks_workflow tool.
  2. The workflow (tasks_workflow): A Workflow that iterates over the approved tasks.
  3. Sub-agent (task_explainer): An Agent tasked with generating a step-by-step execution plan for each task.

Here is the architectural diagram of the solution:

Architecture diagram showing user interaction with the root coordinator agent, which directly calls the dynamic tasks_workflow tool that schedules task_explainer sub-agents


Technical implementation

Let's break down how to implement this solution using the Google ADK library in Python. The complete code resides in the devrel-demos repository with core logic in the agent.py file.

1. Initialize the environment and model

First, import the required ADK modules and set up the Gemini model. This example uses gemini-3.5-flash with Gemini Enterprise Agent Platform APIs:

import os

import google.auth
from google.adk import Agent, Context, Event, Workflow
from google.adk.apps import App
from google.adk.models import Gemini
from google.adk.workflow import node
from google.genai import types

# ==============================================================================
# Initialize the environment
# ==============================================================================
_, project_id = google.auth.default()
if project_id:
    os.environ["GOOGLE_CLOUD_PROJECT"] = project_id
os.environ["GOOGLE_CLOUD_LOCATION"] = "global"
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "True"

# ==============================================================================
# Model Definition
# ==============================================================================
model = Gemini(
    model="gemini-3.5-flash",
    retry_options=types.HttpRetryOptions(attempts=3),
)
Enter fullscreen mode Exit fullscreen mode

2. Define the sub-agent

The sub-agent task_explainer takes a task description and writes a step-by-step execution plan:

task_explainer = Agent(
    name="task_explainer",
    model=model,
    instruction="""
    You are a task execution planner subagent.
    Given a task description, write a short, step-by-step execution plan
    explaining how you would perform the task. Be concise and clear.
    """,
)
Enter fullscreen mode Exit fullscreen mode

3. Implement the dynamic workflow node

To support dynamic execution, define two functions decorated with @node. First node accepts the parent context ctx and a list of task strings. This is the main node that iterates over the list of tasks and explains them:

@node(rerun_on_resume=True)
async def task_workflow_node(ctx: Context, node_input: list[str]):
    """Workflow that iterates over the list of tasks and explains them."""
    for task in node_input:
        # Yield progress update
        yield Event(message=f"⏳ Starting task: {task}...")  # type: ignore

        # Dynamically trigger subagent
        explanation = await ctx.run_node(task_explainer, node_input=task)
        explanation_content = getattr(explanation, "text", None) or str(explanation)

        # Mark as done
        yield Event(
            message=(
                f"✅ Task Done: {task}\n\n"
                f"**Execution Explanation:**\n{explanation_content}"
            )  # type: ignore
        )
Enter fullscreen mode Exit fullscreen mode

The second node is just returning a message that all tasks were completed. It’s used here to demonstrate a sequential workflow execution:

@node
async def task_workflow_end(ctx: Context):
    yield Event(message="🎉🚀 All tasks executed successfully! ✨")  # type: ignore
Enter fullscreen mode Exit fullscreen mode

4. Define the workflow

Next, define the Workflow object. A Workflow consists of nodes and directed edges between them. Since ADK 2.4.0, a Workflow can be registered directly as a first-class tool for an agent. To do so, make sure to define the name, description, and input_schema so the parent agent knows how to call it. Whereas edges describes the order of workflow steps execution:

tasks_workflow = Workflow(
    name="tasks_workflow",
    description="Iterates over the list of tasks and explains them.",
    input_schema=list[str],
    edges=[
        ("START", task_workflow_node, task_workflow_end),
    ],
)
Enter fullscreen mode Exit fullscreen mode

5. Define the root coordinator agent

Finally, the root_agent coordinator manages user interaction. The agent collects the list of tasks, asks for confirmation, and, once approved, executes the tasks_workflow directly. Notice how we pass tasks_workflow directly to the tools array:

root_agent = Agent(
    name="root_agent",
    model=model,
    instruction="""
    You are a task coordinator agent.
    Your goal is to gather a list of tasks that the user wants to execute.
    Talk to the user to gather the list of tasks.
    Once you have a list of tasks, present them clearly to the user and ask
    for their final approval to execute them.
    Do NOT execute anything until the user explicitly approves.
    Once the user approves the list of tasks, call the tool `tasks_workflow` with
    the list of tasks.
    """,
    tools=[tasks_workflow],
)
Enter fullscreen mode Exit fullscreen mode

Testing the flow locally

You can run and test this agent locally using the agents-cli playground.

  1. If you haven't already installed agents-cli and its skills, run the setup command:
   uvx google-agents-cli setup
Enter fullscreen mode Exit fullscreen mode
  1. Clone and enter the demo directory:
   npx -y giget@latest gh+git:google/adk-samples/python/agents/workflow-dynamic workflow-dynamic 
   cd workflow-dynamic
Enter fullscreen mode Exit fullscreen mode
  1. Install required packages::
   agents-cli install
Enter fullscreen mode Exit fullscreen mode
  1. Start the playground:
   agents-cli playground
Enter fullscreen mode Exit fullscreen mode
  1. Interact with the Agent:

    • Open http://localhost:8080 in your browser.
    • Select app from the dropdown list at the top.
    • Type a list of tasks in the chat box. For example:
     1. Empty the trash.
     2. Feed the dog.
     3. Do the laundry.
    
  • The coordinator agent lists the tasks and asks for your approval.
  • Once you reply with "Yes" or "Approved", the tasks_workflow tool fires.
  • The playground console streams live updates as tasks_workflow iterates through each task and returns plans generated by the task_explainer sub-agent.

Screencast demo

The following screencast demonstrates the working solution:

Summary

Dynamic workflows in Google ADK allow agents to perform complex, runtime-determined orchestrations. By leveraging Workflow and the @node decorator, you can build adaptable multi-agent applications that respond to dynamic requirements.

Continue exploring:

Thanks for reading

If you found this article helpful, please consider sharing it with your friends on socials.

I'm always eager to share my learnings or chat with fellow developers and AI enthusiasts, so feel free to follow me on LinkedIn, X or Bluesky.

Top comments (7)

Collapse
 
alexshev profile image
Alex Shev

Dynamic workflow triggering is the missing piece in a lot of multi-agent demos.

Static graphs are easy to reason about, but real work changes shape after the first tool result. The important part is making the handoff explicit enough that dynamic does not become improvised.

Collapse
 
rsamborski profile image
Remigiusz Samborski Google AI

What I usually see working well is adding information about tools to system instructions or skills. Relying purely on the tool name and description doesn't always work as expected.

Collapse
 
alexshev profile image
Alex Shev

Yes. Tool names and descriptions are often too thin for real selection. They tell the model what exists, but not the operating policy: when to use it, when to avoid it, what order to call things in, and what evidence counts as done. That is where skills or system-level workflow notes do better than a larger pile of tools.

Collapse
 
nova-agent profile image
Nova

Dynamic triggering is the glamorous half of multi-agent orchestration; the unglamorous half is knowing when a piece silently stopped working. On my fully local stack (Ollama, one 32B for reasoning plus separate 8Bs per auxiliary task), my worst failure wasn't orchestration logic — my long-term memory plugin died for two days after a dependency update, with zero errors in any log. So whatever framework triggers the workflows, I'd budget as much for error visibility as for the triggering pattern itself, especially self-hosted where no cloud monitoring catches it for you.

Collapse
 
rsamborski profile image
Remigiusz Samborski Google AI

Fair point. Observability is key, especially for long running, background tasks that you don't immediately notice failling.

Collapse
 
raju_dandigam profile image
Raju Dandigam

Registering the workflow itself as a first-class tool is a clean shift because it keeps the coordinator’s interface small while still letting the runtime fan out dynamically. That is usually where rigid graph definitions start to feel artificial: the control flow that matters is determined by the worklist at runtime, not by what looked neat in the design doc. The production question for me is less “can it fan out?” and more “can I reconstruct why it fanned out that way when something goes wrong?” Once sub-agents, tools, and approval steps start interleaving, inspectability becomes the real architecture. That is where agent-inspect-style execution traces are useful. Curious whether you’ve found teams adopting dynamic workflows first for throughput, or for debuggability once static graphs become too brittle.

Collapse
 
rsamborski profile image
Remigiusz Samborski Google AI

We've been using Google Cloud tracing capabilities to pin point issues and easier debugging.