← Back to list

Should We Use Google ADK for Agentic Solutions?

My journey into exploring Agentic AI began where most developers start today, learning about agentic designs and stateful orchestration…

Mirco Fernando · 2026-05-30 14:54 · 15 claps · 7.3 min read
#google-adk #large-language-models #agentic-ai #langgraph-agents
Open on Medium ↗
Wiki topics: AGT · AI Agents EDU · Education & Learning

Should We Use Google ADK for Agentic Solutions?

My journey into exploring Agentic AI began where most developers start today, learning about agentic designs and stateful orchestration patterns using the framework everyone is hyped about which is LangGraph. The Framework’s ability to model complex behaviours as Directed Acyclic Graphs (DAG)s makes it a fascinating tool for structured pipelines. However, while I was exploring about these technologies, I kept noticing the quiet but steady rise of Google’s Agent Development Kit (ADK), increasingly appearing in enterprise AI solutions

I wanted to find out why engineering teams were turning to ADK. Instead of just reading documentation and watching introductory videos. I got the curiosity try it out myself.

So, I built an identical Multi-Agent Prompt Optimisation Engine using both LangGraph and Google’s Agent Development Kit (ADK). No RAG or External Actions just pure framework primitives. This isolation allowed me to benchmark how these frameworks handle pure orchestration, state management, and agent transitions, The experience and outcome was quite surprising.

The System Design: Reflection Pattern

To push both frameworks to their structural limits, I designed this using the Agentic Reflection design pattern that illustrates a prompt optimising loop. Because reflection loops depend on constant feedback cycles, they are computationally complex and slow to respond. A user’s initial inquiry initiates a sequential waterfall of agent-to-agent completing across four specialised runtime nodes rather than a single call-and-response.

  • The Generator Node: Takes raw user intent and drafts a comprehensive, highly optimised system prompt.
  • The Critic Node: Evaluates the draft against strict rubrics, checking for edge cases, formatting boundaries, and token constraints.
  • The Assessor Node: Acts as the gatekeeper, inspecting the critic’s feedback to determine if the prompt meets a defined sufficiency threshold.
  • The Reviser Node: Executes updates to the draft if the Assessor signals that a revision cycle is required.

System Design Diagram utilising the Reflection Pattern for both Frameworks

System Design Diagram utilising the Reflection Pattern for both Frameworks

As for the LLM models i used gemini for ADK since its the native model for the framework and OpenAI for LangGraph.

Any framework-level overhead increases significantly with each turn since these four nodes must operate sequentially across several iterations to complete a single prompt. The architectural differences between ADK’s native, imperative loops and LangGraph’s immutable state graphs were clear right away in this isolated instance.

Now lets get to the real talk, Discussing about the differences I observed during my development.

Structure & Control Flow: Graph vs. Imperative Loop

This is the most obvious difference when you can see looking at the framework implementations of both LangGraph and ADK. It highlights the significant differences of initiating this design pattern.

1. LangGraph (The Structured Graph):

In LangGraph, You have to explicitly define your nodes as standalone functions, initiate them into a StateGraph(ReflectionState), define exact directional edges (e.g., builder.add_edge("draft", "critic")), and code conditional routing edges with router functions. The framework acts as a strict compiler that builds a virtual roadmap before running. Increases the learning curve to adapt to this framework. This framework makes it highly restrictive if an enterprise backend relies on other software stacks.

class ReflectionState(TypedDict):
    query: str
    current_draft: str
    critique: str
    revision_history: Annotated[list, operator.add]  # appends each revised draft
    messages: Annotated[list, add_messages]  # accumulates all messages for context
    is_sufficient: bool
    iteration: int
    max_iterations: int
    total_tokens: int
    input_tokens: int
    output_tokens: int

async def draft_node(state: ReflectionState):
    """Generate initial draft response."""
    response = llm.generate(
        prompt=f"Query: {state['query']}\n\nPrevious Chats: {state['revision_history']}", # Pass both the original query and the revision history for context
        system_prompt=(
            "You are an Expert AI Prompt Engineer specializing in designing production-ready system prompts for Large Language Models." 
            "Your task is to take a user's rough idea OR a Critic's feedback, and transform it into a highly structured, rigorous system prompt."
            "A perfect system prompt must contain the following sections:"
            "1. ROLE & PERSONA: Who the AI is acting as (e.g., You are a senior DevOps engineer...)."
            "2. CONTEXT: The background information the AI needs to understand the environment."
            "3. CORE TASK: The exact action the AI must perform."
            "4. STRICT CONSTRAINTS: What the AI must NEVER do (e.g., tone limits, forbidden external libraries, length boundaries)."
            "5. OUTPUT FORMAT: Exactly how the final response should be structured (e.g., JSON schema, bullet points, Markdown)."

            "RULES FOR YOUR OUTPUT:"
            "- Incorporate all feedback provided by the Critic if this is a subsequent iteration."
            "- Output ONLY the optimized prompt text. "
            "- Do not include conversational filler like Here is your prompt or I have optimized this."
            "-Do not provide harmful, unethical, or biased content. Always adhere to ethical guidelines. "
            "- Do not wrap the output in markdown code blocks (```) unless the prompt itself requires them."
        ),

..............
Other Agents

# Initiating the Graph
workflow = StateGraph(ReflectionState)
workflow.add_node("Draft", draft_node)
workflow.add_node("Critic", critic_node)
workflow.add_node("Assess", assessment_node)
workflow.add_node("Revise", revise_node)

workflow.add_edge(START, "Draft")
workflow.add_edge("Draft", "Critic")
workflow.add_edge("Critic", "Assess")

# Conditional routing using router functions
workflow.add_conditional_edges("Assess", should_continue, {
    "sufficient" : END,
    "needs_improvement" : "Revise"
})

2. Google ADK (The Imperative Flow):

In ADK, you define your specialised Agent instances independently with their instructions. The control flow is written in native, standard Python code (like an asynchronous while loop). The framework doesn't force a strict graph roadmap it works with a standard language(supports other languages) and control primitives (if/else, break) to route data between agents on the fly. And ADK relies on traditional, idiomatic software engineering practices that any backend developer already knows. If you know how to write basic object-oriented backend code, you already know how to use ADK.

# Define Agents
draft_agent = Agent(name="Generator", 
                    model="gemini-2.5-flash-lite", 
                    description="You are a helpful assistant that optimizes user prompts for better AI responses. Your task is to iteratively improve the given prompt based on feedback until it is deemed sufficient.",
                    instruction="You are an Expert AI Prompt Engineer specializing in designing production-ready system prompts for Large Language Models." 
            "Your task is to take a user's rough idea OR a Critic's feedback, and transform it into a highly structured, rigorous system prompt."
            "A perfect system prompt must contain the following sections:"
            "1. ROLE & PERSONA: Who the AI is acting as (e.g., You are a senior DevOps engineer...)."
            "2. CONTEXT: The background information the AI needs to understand the environment."
            "3. CORE TASK: The exact action the AI must perform."
            "4. STRICT CONSTRAINTS: What the AI must NEVER do (e.g., tone limits, forbidden external libraries, length boundaries)."
            "5. OUTPUT FORMAT: Exactly how the final response should be structured (e.g., JSON schema, bullet points, Markdown)."

            "RULES FOR YOUR OUTPUT:"
            "- Incorporate all feedback provided by the Critic if this is a subsequent iteration."
            "- Output ONLY the optimized prompt text. "
            "- Do not include conversational filler like Here is your prompt or I have optimized this."
            "-Do not provide harmful, unethical, or biased content. Always adhere to ethical guidelines. "
            "- Do not wrap the output in markdown code blocks (```) unless the prompt itself requires them.",
            )

...............
Other Agents

# The ADK Imperative Advantage
while iterations < max_iterations:
    assessment = await call_agent_async(assessor, current_draft)
    if "SUFFICIENT: YES" in assessment:
        break

    # Instant, zero-overhead routing
    current_draft = await call_agent_async(reviser, current_draft)

State & Memory Management (Why ADK is Faster)

This might be a hidden reason behind better optimisation. It’s all about what happens to data in the memory as the agents talk to each other.

1. LangGraph’ Memory:

LangGraph enforces an immutable state model. When data moves from the critic_node to the assessor_node, LangGraph doesn't just pass the string. It freezes the current state, creates a complete deep copy/snapshot of the state dictionary (TypedDict) the AgentState. In reflection-heavy workflows, this overhead appeared measurable in my benchmark. If a reflection loop iterates 3 or 4 times, process happens repeatedly, may resulting high latency.

2. ADK’s Mutable Memory

ADK decouples agent data. It uses a Runner to execute tasks, passing data directly into an active, mutable Session workspace (session.state or in-memory message stacks). Modifying the prompt or changing an iteration counter happens instantly in local memory, ADK appears to minimize orchestration-layer state transformations compared to LangGraph.

Performance Benchmarks: Framework Comparison

Now comes the real deal. To establish a clear baseline, both frameworks were subjected to an identical multi-turn task taking the same user input, generating a detailed system prompt, and running the agentic reflection loop to implement strict formatting and edge-case criteria.

This benchmark focuses primarily on orchestration simplicity and runtime behaviour in a reflection-based workflow. It does not evaluate other areas where LangGraph is commonly adopted, such as durable execution, checkpointing, human-in-the-loop workflows, and graph observability.

The differences in execution overhead, token usage, and latency are summarized below:


{
  "initial_prompt": "make a portfolio website, its for an AI engineer",
  "max_iterations": 3,
  "session_id": "1"
}

--- Demo Metrics (LangGraph) ---

Input Tokens:  3102

Output Tokens: 1648

Revision Count: 3

Latency (s):    32.52

--------------------

--- Demo Metrics (ADK) ---

Input Tokens:  961

Output Tokens: 971

Revision Count: 1

Latency (s):    8.42

--------------------

As you can observe from these printed metrics the significant gap in return time — 32.52 seconds on LangGraph versus 8.42 seconds on Google ADK — reveals a hidden cost that comes with graph-based orchestration. Why is that? LangGraph converts applications into state machines and compiles workflows into Directed Acyclic Graphs (DAGs). Every time data is transferred between agents, LangGraph’s state-centric execution model introduces additional orchestration and state-management overhead compared to ADK’s session-based approach. Google ADK approaches orchestration differently by relying on native control-flow constructs rather than an explicitly defined workflow graph, As we discussed earlier. It groups agent transitions into a regular, native Python asynchronous while loop. By routing data using simple, native if/else logic handled quickly by the CPU, ADK reduces framework overhead.

And each framework manages short-term memory context across multiple iterations further affects the performance gap. We discussed earlier how both frameworks manage memory. After multiple conversations LangGraph seems to be slowing down since the context is getting proportionally higher but ADK manages it efficiently managing to reduce overhead.

One observation worth noting is that the revision count differed significantly between implementations. ADK completed the workflow in a single revision cycle, while LangGraph required three. This likely contributed substantially to the latency gap and highlights that workflow outcomes can be influenced not only by orchestration overhead, but also by model behaviour and context management.

Final Verdict

After building the same multi-agent reflection system in both LangGraph and Google’s Agent Development Kit (ADK), my biggest takeaway is that neither framework is objectively better they simply solve different problems. ADK stood out for its simplicity, flexibility, and familiar programming model, making it easy to prototype and iterate quickly. In my benchmark, it also delivered lower end-to-end latency, making it an attractive option for teams that value rapid development and a more traditional backend engineering experience.

LangGraph, however, brings strengths that become increasingly important in larger and more complex systems, including structured workflow orchestration, explicit state management, durable execution, and greater observability. It’s also important to note that benchmark results alone should not be treated as proof that one framework universally outperforms the other, as factors such as model choice, prompt design, and workflow architecture heavily influence performance. Ultimately, the best framework depends on your requirements ADK may be ideal for speed and flexibility, while LangGraph excels when reliability, control, and production-grade orchestration are the priority.


메타데이터
post_id
d659d710beb0
slug
should-we-use-google-adk-for-agentic-solutions-d659d710beb0
url
https://medium.com/@mircofdo/should-we-use-google-adk-for-agentic-solutions-d659d710beb0
canonical_url
https://medium.com/@mircofdo/should-we-use-google-adk-for-agentic-solutions-d659d710beb0
author_url
https://medium.com/@mircofdo
status
ok
fetched_at
2026-06-23 03:48:11