AI agents are good at deciding what to do next, but that does not mean every workflow should be controlled entirely by an AI model.

In a production application, some steps are predictable.

A request may need to go through validation, data retrieval, policy checks, approval, and notification. Some of those steps can run in parallel. Others must happen in a specific order. Some decisions should be made by code rather than a language model.

This is where graph-based workflows become useful.

Google's Agent Development Kit, commonly called ADK, now provides workflow capabilities for building explicit execution paths using nodes, edges, routing, parallel execution, joins, and human-in-the-loop steps. ADK is designed to support everything from simple agents to more structured multi-agent workflows.

The important question is not whether graph workflows are powerful.

It is:

When should an AI application use a graph instead of letting an agent decide the entire workflow?

What Is a Graph Workflow?

A graph workflow represents an application process as a collection of steps connected by defined paths.

A simplified workflow might look like this:

Code
START
  |
  v
Validate Request
  |
  v
Fetch Data
  |
  v
Analyze
  |
  v
Decision
  |
  +----------+
  |          |
  v          v
Approve    Review
  |          |
  +----+-----+
       |
       v
    Response
       |
       v
      END

Each box represents work.

The connections represent what can happen next.

This is different from giving an agent a large instruction such as:

Code
"Handle this request and do whatever is necessary."

With a graph, the developer explicitly defines important parts of the execution model.

ADK's workflow capabilities support patterns such as sequential execution, parallel work, routing, joining results, human review, and dynamic orchestration.

Why Use a Graph for an AI Agent?

A language model is useful when the problem involves interpretation.

For example:

Code
"What is the customer actually asking for?"

A model can classify the intent.

But consider this rule:

Code
If order age > 30 days:
    deny refund

There is little reason to ask an LLM to make that decision.

A better architecture is:

Code
LLM
 |
 +-- Understand customer request
 |
 v
Application Code
 |
 +-- Apply refund policy
 |
 v
LLM
 |
 +-- Explain decision

This separates probabilistic reasoning from deterministic business logic.

That separation is one of the strongest reasons to consider a graph workflow.

Agent vs Graph Workflow

A single agent can be enough for simple tasks.

Code
User
 |
 v
Agent
 |
 +-- Tool
 +-- Tool
 +-- Tool
 |
 v
Response

The model decides which tool to use and when.

A graph provides more control:

Code
User
 |
 v
Router
 |
 +-------> Agent A
 |
 +-------> Agent B
 |
 +-------> Human Review
 |
 v
Final Response

The difference is not simply visual.

It changes who controls execution.

Approach

Main Decision Maker

Best For

Single agent

Model

Open-ended tasks

Sequential workflow

Workflow

Predictable pipelines

Parallel workflow

Workflow

Independent tasks

Deterministic router

Code

Explicit business rules

Agent router

Model

Semantic classification

Dynamic workflow

Application code

Runtime-generated work

Human-in-the-loop

Person

Sensitive decisions

ADK supports these different orchestration patterns rather than forcing every problem into one agent model.

Start With the Simplest Possible Architecture

A common mistake in agent engineering is introducing a graph too early.

Suppose your application does this:

Code
User Question
     |
     v
Agent
     |
     +-- Search Tool
     |
     +-- Calculator Tool
     |
     +-- Database Tool
     |
     v
Answer

You may not need a graph.

The agent can select the appropriate tool based on the user's request.

Graph orchestration becomes more useful when the process has explicit structure.

For example:

Code
Receive Request
      |
      v
Validate Identity
      |
      v
Fetch Account
      |
      +------+
      |      |
      v      v
Billing  Activity
      |      |
      +------+
         |
         v
      Policy
         |
    +----+----+
    |         |
    v         v
Approve    Human Review

Now the workflow itself is meaningful.

Sequential Workflows

The simplest graph pattern is sequential execution.

Code
A
|
v
B
|
v
C
|
v
D

Each step depends on the previous step.

For example, a document-processing system might use:

Code
Upload Document
       |
       v
Extract Text
       |
       v
Classify Document
       |
       v
Extract Fields
       |
       v
Validate Fields
       |
       v
Store Result

There is no reason to execute the validation before field extraction.

The dependency is explicit.

When Sequential Execution Makes Sense

Use sequential execution when:

  • Step B requires the result of step A.

  • The order is part of the business process.

  • Each stage transforms the previous stage's output.

  • You want predictable execution.

It is especially useful when debugging because you can identify exactly which stage failed.

Parallel Workflows

Not every operation needs to wait for another.

Imagine a support request that requires:

Code
Order History
Payment History
Customer History

All three can use the same customer or order identifier.

There is no reason to execute them one after another.

Instead:

Code
             +--> Order History
             |
Request -----+--> Payment History
             |
             +--> Customer History
                     |
                     v
                  Combine
                     |
                     v
                   Decide

This is commonly called fan-out and fan-in.

ADK's graph workflow model supports parallel execution followed by a join operation that waits for the required results.

Why Parallelism Matters

Suppose three services each take approximately one second.

Sequential execution:

Code
1s + 1s + 1s = approximately 3s

Parallel execution:

Code
max(1s, 1s, 1s) = approximately 1s

These are simplified examples rather than production benchmarks.

The real benefit depends on network latency, service behavior, concurrency limits, and workload characteristics.

The architectural point is more important:

If independent operations do not need to wait for each other, a workflow should not necessarily serialize them.

Fan-In With a Join

Parallel execution creates another problem.

Once the three operations finish, something needs to combine their results.

Code
Order --------+
              |
Payment ------+----> Join ----> Decision
              |
Customer -----+

A join node provides a clear synchronization point.

For example:

Code
results = {
    "order": order_result,
    "payment": payment_result,
    "customer": customer_result
}

The decision stage can then consume the combined data.

This is much easier to reason about than having several agents independently update shared state.

Deterministic Routing

Some decisions should be made using normal application code.

Consider:

Code
Refund Amount < $50
AND
No Chargeback
AND
Refund Count < 3

This is a business rule.

A simple function is appropriate:

Python
def refund_policy(amount, chargeback_open, previous_refunds):
    if chargeback_open:
        return "DENY"

    if amount < 50 and previous_refunds < 3:
        return "AUTO_APPROVE"

    return "MANUAL_REVIEW"

The output can determine the next graph path.

Code
                 Policy
                    |
          +---------+---------+
          |         |         |
          v         v         v
       Approve     Deny     Review

This approach has several advantages.

The rule is:

  • Testable

  • Reviewable

  • Deterministic

  • Version controlled

  • Easy to audit

You do not need an LLM to determine whether amount < 50.

Agent-Based Routing

Other routing problems are semantic.

Suppose a support system receives:

Code
"My shoes are too small. Can you send me another pair?"

The application needs to understand that this is probably an exchange request.

Another user may say:

Code
"I don't want the shoes anymore. Please give me my money back."

That is likely a refund request.

A model can classify these requests.

Code
Customer Message
       |
       v
Intent Agent
       |
 +-----+------+-------+
 |            |       |
 v            v       v
Refund      Exchange  Clarify

The important distinction is:

The model chooses the meaning. The graph defines the possible destinations.

ADK's current workflow guidance explicitly distinguishes deterministic routers from agent routers for this reason.

Human-in-the-Loop

Some decisions should not be fully automated.

For example:

Code
Fraud detected
      |
      v
Risk analysis
      |
      v
Human review
      |
      v
Approve or reject

A graph makes this pause explicit.

The workflow can stop at a human-review node and continue after the human provides an input.

This is useful for:

  • High-value transactions

  • Security incidents

  • Financial decisions

  • Sensitive customer actions

  • Exceptions to business policy

  • Operations requiring approval

Human involvement should be treated as part of the workflow rather than as an unexpected failure state.

Parallel Workers

Another useful pattern appears when the same operation needs to run across multiple items.

Imagine processing 100 documents:

Code
100 Documents
      |
      v
Parallel Workers
      |
      +--> Document 1
      +--> Document 2
      +--> Document 3
      +--> ...
      +--> Document 100
      |
      v
Results

Instead of designing 100 separate graph branches, the workflow can represent the repeated operation as a parallel worker pattern.

This is useful for:

  • Document processing

  • Product classification

  • Batch analysis

  • Data enrichment

  • Evaluation tasks

The important engineering question is whether the work is independent enough to run concurrently.

Static Graph vs Dynamic Workflow

This is one of the most important decisions when designing an ADK workflow.

A static graph might look like:

Code
A
|
v
B
|
+--> C
|
+--> D

The possible paths are known when you design the application.

A dynamic workflow is different.

The next operation may depend on information discovered during execution.

For example:

Code
Start
 |
 v
Investigate
 |
 +--> Found transaction
 |        |
 |        v
 |     Investigate transaction
 |
 +--> Found account issue
          |
          v
       Investigate account

The application determines what work needs to happen next.

ADK's recent graph workflow guidance recommends using explicit graph edges when the possible workflow can be described ahead of time, while dynamic orchestration is useful when runtime results determine what work should happen next.

A Practical Example: Customer Refund

Consider a refund system.

The customer requests a refund.

Step 1: Gather Data

Run these operations in parallel:

Code
            +--> Order
            |
Request ----+--> Payment
            |
            +--> Refund History

Step 2: Combine Results

Code
Order
Payment
Refund History
      |
      v
    Join

Step 3: Apply Policy

Code
              Policy
                |
       +--------+---------+
       |        |         |
       v        v         v
    Approve    Deny     Review

Step 4: Generate Response

The model can write a natural-language explanation.

Code
Decision
   |
   v
Response Agent
   |
   v
Customer

Notice the division of responsibility:

Code
Graph      -> Controls execution
Code       -> Applies business policy
Tools      -> Retrieve data
Human      -> Handles exceptions
LLM        -> Understands language and generates explanations

This is a much stronger architecture than asking one model to perform everything.

Example ADK Workflow Structure

A simplified Python design could look like:

JavaScript
from google.adk import Workflow

workflow = Workflow(
    name="refund_workflow",
    edges=[
        ("START", "fetch_data"),
        ("fetch_data", "evaluate_policy"),
        ("evaluate_policy", "AUTO_APPROVE"),
        ("evaluate_policy", "DENY"),
        ("evaluate_policy", "MANUAL_REVIEW"),
    ],
)

The exact API structure should follow the ADK version used by your project, but the architectural idea is stable:

Code
Nodes = Work

Edges = Possible transitions

Router = Chooses a path

Join = Synchronizes parallel work

ADK is available as an open-source framework and currently supports Python, TypeScript, Go, and Java.

Graph Workflow vs LangGraph

Developers familiar with LangGraph may immediately notice similarities.

Both approaches use graph concepts for agent orchestration.

The choice should not be based only on the word "graph."

Consider the broader platform:

Area

ADK

LangGraph

Graph-based orchestration

Yes

Yes

Multi-agent workflows

Yes

Yes

Tool integration

Yes

Yes

Human-in-the-loop

Supported

Strong support

Dynamic orchestration

Supported

Supported

Google Agent Platform integration

Native ecosystem

Supported

Best fit

Google-oriented agent stack and ADK workflows

Graph-centric agent applications across supported ecosystems

Google's current Agent Platform documentation positions ADK as a code-first framework for complex multi-agent orchestration, while also supporting other frameworks such as LangGraph.

The right choice depends on the rest of your application rather than the graph abstraction itself.

When You Should Use a Graph

A graph is a strong candidate when:

The Process Has Known Stages

Code
Validate
  |
Retrieve
  |
Analyze
  |
Approve

Several Operations Can Run in Parallel

Code
A + B + C
    |
  Join
    |
    D

Business Rules Need Deterministic Execution

Code
Input
 |
 v
Rules
 |
 +--> Path A
 +--> Path B

Human Approval Is Required

Code
AI
 |
 v
Human
 |
 v
Continue

Multiple Specialized Agents Have Clear Responsibilities

Code
Planner
   |
   +--> Research Agent
   +--> Data Agent
   +--> Review Agent
   |
   v
Final Agent

When You Should Not Use a Graph

A graph may be unnecessary when the application is simply:

Code
Question
   |
   v
Agent
   |
   v
Tool
   |
   v
Answer

It may also be unnecessary when the workflow is highly open-ended and difficult to describe ahead of time.

For example:

Code
"Research this topic and decide what you need to investigate next."

A dynamic agent may be a better fit.

Do not create a 30-node graph simply because the framework allows it.

Complexity has a cost.

Common Mistakes

Putting Every LLM Call in a Graph

A graph does not automatically make an AI system better.

Use normal functions for deterministic work.

Asking an LLM to Apply Exact Business Rules

If the rule can be expressed clearly in code, code is usually easier to test.

Creating Too Many Nodes

A graph with dozens of tiny nodes can become difficult to maintain.

Group logically related work.

Using Sequential Execution Everywhere

Independent tasks should be considered for parallel execution.

Hiding Important Logic Inside Prompts

Business-critical rules should not exist only in an instruction string.

Ignoring Failure Paths

Every production workflow needs to answer:

Code
What happens if a node fails?
What happens if a tool times out?
What happens if the model returns invalid data?
What happens if the human does not respond?

Testing Graph Workflows

One of the strongest benefits of explicit workflows is that individual paths can be tested.

For example:

Code
Test Case 1
Refund < $50
No chargeback
Previous refunds < 3
Expected: AUTO_APPROVE

Another:

Code
Test Case 2
Refund > $50
Expected: MANUAL_REVIEW

And:

Code
Test Case 3
Chargeback exists
Expected: DENY

You can also test the graph itself:

Code
START
  |
  v
Fetch
  |
  v
Policy
  |
  +--> Approve
  +--> Deny
  +--> Review

Every valid input should produce a valid path.

Observability Matters

As agent workflows become more complex, knowing the final answer is not enough.

You need to know:

Code
Which node ran?
Which tool was called?
What route was selected?
How long did each step take?
Where did the workflow fail?
What state was available?

Google's Agent Platform supports agent observability and can expose traces, events, state, and sessions for deployed agents when configured appropriately.

A graph gives observability systems a useful structure because execution already has explicit stages.

Best Practices

  1. Start with one agent when one agent is enough.

  2. Use graphs when execution order or branching is important.

  3. Keep deterministic business rules in code.

  4. Use models for semantic decisions that genuinely require language understanding.

  5. Run independent operations in parallel where appropriate.

  6. Use joins when multiple branches must finish before the workflow continues.

  7. Keep human approval as an explicit workflow stage.

  8. Prefer static graphs when the possible paths are known ahead of time.

  9. Use dynamic orchestration when runtime results determine the next work.

  10. Test every important route independently.

  11. Instrument workflow execution so failures can be traced to a specific node.

  12. Avoid creating nodes simply to make the architecture look more sophisticated.

A Practical Decision Framework

Before creating an ADK graph, ask these questions:

Code
Can the task be handled by one agent?
        |
       Yes
        |
        v
Use the simpler design.

       No
        |
        v
Are the workflow stages predictable?
        |
   +----+----+
   |         |
  Yes        No
   |         |
   v         v
Graph       Dynamic
Workflow    orchestration
   |
   v
Are there independent operations?
   |
  Yes
   |
   v
Consider parallel execution.

Then ask one final question:

Which decisions should belong to the model, and which should belong to application code?

That question often determines the architecture.

Summary

Google ADK graph workflows are useful when an AI application needs more control than a single autonomous agent can provide.

Use them when you need:

  • Predictable workflow stages

  • Explicit routing

  • Parallel execution

  • Fan-out and fan-in

  • Deterministic business rules

  • Human approval

  • Multiple specialized agents

  • Better workflow observability

Use a simple agent when the task is open-ended and does not benefit from explicit orchestration.

Use dynamic orchestration when the next step cannot be fully known before execution.

The core design principle is simple:

Let the model handle the parts that require reasoning and language understanding. Let code handle deterministic rules. Let the workflow control how the pieces connect.

That separation is what makes graph-based agent systems useful in production rather than just interesting in a demo.