Back to handbooks index
FIELD HANDBOOK
v1.0 Beta Python · TS · Go · Java adk.dev
Developer Reference · 2025

Agent
Dev Kit

Build · Evaluate · Deploy

Google's open-source framework for building production-grade AI agents and multi-agent pipelines. Supports Python, TypeScript, Go, and Java with first-class Gemini integration and pluggable model backends.

LLM Agents Multi-Agent Function Tools MCP / A2A Streaming NIST SP 800-207
🧭

Overview

// WHAT ADK IS AND HOW IT WORKS

Agent Development Kit (ADK) is Google's open-source framework designed to help developers quickly build, manage, evaluate, and deploy AI-powered agents. It treats agents as code — composable, testable, and version-controlled. ADK is model-agnostic but optimized for Google's Gemini family, and it natively supports the A2A (Agent-to-Agent) communication protocol.

Agent-as-Code

Agents are defined in code — not drag-and-drop UIs. Every component (identity, tools, instructions, memory) is explicit, version-controlled, and composable.

Multi-Language

First-class SDKs for Python, TypeScript, Go, and Java. Core concepts are identical across languages. Python 2.0 Beta introduces graph-based workflows and agent teams.

Production-Ready

Built-in evaluation, observability (logging, metrics, traces), deployment targets (Cloud Run, GKE, Agent Runtime), and safety guardrails make ADK enterprise-ready.

🔵
ADK 2.0 Beta (Python): Introduces graph-based workflows with typed data flow, collaborative agent teams, dynamic workflow composition, and human-in-the-loop support. ADK TypeScript 1.0 is now stable. See adk.dev/2.0 for details.

Core Architecture

User / App
Input Message
Runner
Session + Routing
Agent
LLM + Policy
Tool / Sub-Agent
Execute Action
Response
Event Stream
📦

Installation

// REQUIREMENTS & SETUP
Requirements
  • Python: 3.10 or later + pip
  • TypeScript: Node.js 18+ + npm
  • Go: 1.21+
  • Java: JDK 17+ + Maven or Gradle
  • API Key: Gemini API key from Google AI Studio
Supported Models
  • Gemini 2.0 Flash / Pro (default, recommended)
  • Anthropic Claude (via LiteLLM or direct)
  • Ollama / vLLM (local/self-hosted)
  • Any OpenAI-compatible endpoint via LiteLLM
  • Google Agent Platform hosted models
Shell — Install by language
# Python (recommended) pip install google-adk # Recommended: create a virtual environment first python3 -m venv .venv source .venv/bin/activate # macOS / Linux # .venv\Scripts\activate.bat # Windows CMD # .venv\Scripts\Activate.ps1 # Windows PowerShell # TypeScript npm install @google/adk # Java (Maven) # Add to pom.xml: <dependency> <groupId>com.google.adk</groupId> <artifactId>google-adk</artifactId> <version>0.1.0</version> </dependency> # Go go get google.golang.org/adk

Quickstart

// YOUR FIRST AGENT IN MINUTES

The fastest path to a running agent uses the adk create command — it scaffolds the project, wires up the boilerplate, and drops you directly into writing agent logic.

1

Create a project

Run adk create my_agent to scaffold a new agent directory with agent.py, .env, and __init__.py.

2

Set your API key

Add GOOGLE_API_KEY="YOUR_KEY" to my_agent/.env. Get a key at aistudio.google.com/app/apikey.

3

Define your agent

Edit agent.py to define root_agent with a model, name, description, and optional tools.

4

Run it

Use adk run my_agent for CLI interaction or adk web for the browser dev UI (development only).

Python — agent.py minimal example
from google.adk.agents import Agent # Define a tool — plain Python function def get_current_time(city: str) -> dict: """Returns the current time in a specified city.""" return {"status": "success", "city": city, "time": "10:30 AM"} # root_agent is the required entry point root_agent = Agent( model='gemini-2.0-flash', name='root_agent', description="Tells the current time in a specified city.", instruction="""You are a helpful assistant that tells the current time. Use the 'get_current_time' tool when asked about time in a city.""", tools=[get_current_time], )
Shell — run commands
# CLI interactive mode adk run my_agent # Web dev UI (localhost:8000) — run from PARENT directory of my_agent/ adk web --port 8000 # Expose as API server adk api_server --port 8080
⚠️
adk web is development-only. The web interface is intended for local testing and debugging. Do not expose it in production deployments. Use Cloud Run, GKE, or Agent Runtime for production.
🗂️

Project Structure

// ANATOMY OF AN ADK PROJECT
File layout — single agent
my_agent/ ├── agent.py # Main agent definition — must contain root_agent ├── .env # API keys / config (not committed to git) ├── __init__.py # Makes it a Python package └── tools/ └── my_tools.py # Custom tool implementations (optional)
File layout — multi-agent project
agents/ ├── coordinator/ │ ├── agent.py # root_agent = orchestrator LLM agent │ └── .env ├── research_agent/ │ └── agent.py # specialist sub-agent ├── writer_agent/ │ └── agent.py # specialist sub-agent └── shared_tools.py # tools shared across agents
File / FieldRequired?Purpose
root_agentYESThe ADK entry-point. The runner looks for this variable name in agent.py.
.envRecommendedStores GOOGLE_API_KEY and other secrets. Never commit to source control.
__init__.pyYES (Python)Required for Python packaging; the adk CLI discovers agents through packages.
agent.nameYESUnique string identifier. Used for routing in multi-agent systems. Avoid "user".
agent.modelYESLLM identifier string e.g. "gemini-2.0-flash" or "claude-3-5-sonnet".
agent.instructionRecommendedSystem prompt. Defines persona, task, constraints, and tool usage guidance.
agent.descriptionRecommendedUsed by parent agents / routers to decide when to delegate to this agent.
🤖

LLM Agents

// THE THINKING CORE OF ADK

The LlmAgent (aliased as Agent) is the primary building block. It uses a Large Language Model for reasoning, natural language understanding, decision-making, and tool invocation. Unlike workflow agents, its behavior is non-deterministic — it interprets context and decides dynamically how to proceed.

Key Parameters

ParameterTypeRequiredDescription
namestrYESUnique identifier for the agent. Used internally for delegation and routing.
modelstrYESLLM identifier: "gemini-2.0-flash", "gemini-flash-latest", etc.
instructionstr | fnRecommendedSystem prompt. Can be a static string or a function returning a string (supports {state_var} templates).
descriptionstrMulti-agentSummary of capabilities — used by orchestrator agents for routing decisions.
toolslistOptionalList of callables, BaseTool instances, or other agents (as AgentTool).
output_schemaPydantic / SchemaOptionalEnforces structured JSON output. Cannot be combined with tools on most models.
output_keystrOptionalAuto-saves final response text to session.state[output_key].
input_schemaPydantic / SchemaOptionalValidates that incoming message is a JSON string conforming to this schema.
include_contents"default" | "none"OptionalControls whether conversation history is passed to the LLM. 'none' = stateless.
generate_content_configGenContentConfigOptionalFine-tune LLM: temperature, max_output_tokens, safety settings, top_p, top_k.
plannerBasePlannerOptionalBuiltInPlanner (Gemini thinking) or PlanReActPlanner (for non-thinking models).
code_executorBaseCodeExecutorOptionalAllows agent to execute code blocks. Use BuiltInCodeExecutor.

Instruction Templating

State Variables

Use {var} syntax to inject session state into instructions. Use {var?} to silently skip if the variable doesn't exist. Use {artifact.var} to inject artifact text content.

Function Instructions

Pass a callable as instruction to dynamically compute it per-request. The function receives the ReadonlyContext and returns a string — ideal for personalization or conditional prompts.

Python — LlmAgent with all key features
from google.adk.agents import LlmAgent from google.genai import types from pydantic import BaseModel, Field # Tool definition — docstring becomes the tool's description for the LLM def get_capital_city(country: str) -> str: """Retrieves the capital city for a given country.""" capitals = {"france": "Paris", "japan": "Tokyo", "canada": "Ottawa"} return capitals.get(country.lower(), f"Unknown: {country}") # Structured output schema (Pydantic) class CapitalOutput(BaseModel): capital: str = Field(description="The capital city.") # Full agent definition agent = LlmAgent( model="gemini-2.0-flash", name="capital_agent", description="Answers questions about capital cities of countries.", instruction="""You provide capital city information. When asked, use get_capital_city tool. Current user: {user_name?}""", tools=[get_capital_city], output_key="last_capital", # saves to session state generate_content_config=types.GenerateContentConfig( temperature=0.1, # deterministic max_output_tokens=500, ), )
🔀

Workflow Agents

// DETERMINISTIC ORCHESTRATION

Workflow agents provide deterministic execution — they follow predefined paths rather than using an LLM to decide what to do next. Three built-in types cover the most common orchestration patterns. They are ideal as orchestrators that coordinate specialist LLM sub-agents.

➡️
SequentialAgent
Runs sub-agents in a fixed linear order. Output of each step can be passed to the next via shared session state.
// Pipeline · ETL · Step-by-step workflows
🔁
LoopAgent
Repeats a sub-agent (or sequence) until a condition is met or a maximum iteration count is reached.
// Retry logic · Iterative refinement
ParallelAgent
Runs multiple sub-agents concurrently. Useful for independent tasks where latency matters — results are gathered after all complete.
// Fan-out · Parallel research · Batch
Python — Sequential pipeline example
from google.adk.agents import LlmAgent, SequentialAgent research_agent = LlmAgent( name="researcher", model="gemini-2.0-flash", instruction="Research the topic and summarize key findings.", output_key="research_summary", # saved to state for next step ) writer_agent = LlmAgent( name="writer", model="gemini-2.0-flash", instruction="""Write a blog post based on this research: {research_summary}""", # reads from state set by previous agent output_key="final_post", ) # SequentialAgent runs researcher → writer in order root_agent = SequentialAgent( name="content_pipeline", sub_agents=[research_agent, writer_agent], )
🕸️

Multi-Agent Systems

// COMPOSING AGENT HIERARCHIES

ADK supports multi-agent composition through three communication mechanisms. Agents can be organized into hierarchies where a parent/orchestrator delegates work to specialist sub-agents. This enables separation of concerns, reusability, and parallelism.

Communication Mechanisms

Shared Session State

Agents read and write to session.state — a dict shared within a session. Use output_key to write; use {key} in instructions to read. Simple, explicit, synchronous.

LLM-Driven Transfer

The orchestrator LLM autonomously decides to transfer control to a sub-agent based on its description. Sub-agents listed in sub_agents are presented as options to the parent LLM.

AgentTool

Wrap any agent as a tool using AgentTool(agent). The parent LLM explicitly calls it like a function tool — provides more predictable delegation than implicit transfer.

Python — Coordinator / Dispatcher pattern
from google.adk.agents import LlmAgent from google.adk.tools import AgentTool billing_agent = LlmAgent( name="billing_agent", model="gemini-2.0-flash", description="Handles billing questions, invoice lookups, and payment issues.", instruction="You are a billing specialist. Help with invoices and payments.", ) support_agent = LlmAgent( name="support_agent", model="gemini-2.0-flash", description="Handles technical support, bug reports, and how-to questions.", instruction="You are a technical support specialist.", ) # Coordinator — LLM decides which specialist to call root_agent = LlmAgent( name="coordinator", model="gemini-2.0-flash", instruction="""You are a customer service router. Delegate to billing_agent for billing questions. Delegate to support_agent for technical questions. Handle general greetings yourself.""", tools=[ AgentTool(billing_agent), # explicit invocation AgentTool(support_agent), ], )

Common Multi-Agent Patterns

PatternStructureWhen to use
Coordinator / DispatcherLLM root → specialist sub-agents via AgentToolCustomer service routing, intent classification
Sequential PipelineSequentialAgent → [step1, step2, step3]ETL, content generation, multi-step analysis
Parallel Fan-OutParallelAgent → [agentA, agentB, agentC]Independent research tasks, latency optimization
Generator–Criticwriter agent → reviewer agent (LoopAgent)Document drafting with quality gates
Hierarchical DecompositionRoot → managers → workers (nested)Complex tasks requiring specialization at multiple levels
Human-in-the-LoopAgent raises interrupt → human input → resumeApproval workflows, sensitive actions
🛠️

Custom Tools

// GIVING AGENTS REAL-WORLD CAPABILITIES

Tools extend an agent's capabilities beyond built-in LLM knowledge. The LLM uses the tool's name, docstring, and parameter types to decide when and how to call it. Write clear, descriptive docstrings — they are the tool's "contract" with the LLM.

Function Tools (Python)

In Python, any regular function passed to tools=[] is automatically wrapped as a FunctionTool. ADK extracts the schema from type hints and the docstring.

Python — Function tool patterns
from google.adk.tools import ToolContext # optional context injection # Simple synchronous tool def lookup_user(user_id: str) -> dict: """Looks up a user by their ID and returns their profile information. Args: user_id: The unique identifier for the user. Returns: dict with keys: name, email, plan, created_at """ # call your DB / API here return {"name": "Alice", "email": "alice@example.com", "plan": "pro"} # Async tool async def search_web(query: str) -> str: """Searches the web and returns a summary of results for the given query.""" # await your async HTTP call return "Web search results for: " + query # Tool with context access (read/write session state, artifacts) def save_note(note: str, tool_context: ToolContext) -> dict: """Saves a note to the user's session.""" tool_context.state["last_note"] = note # writes to session state return {"status": "saved"} # Agent usage agent = LlmAgent( name="assistant", model="gemini-2.0-flash", tools=[lookup_user, search_web, save_note], )

Tool Types Summary

Tool TypeHow to defineBest for
Function ToolPlain Python/TS/Go/Java functionCustom business logic, API calls, DB queries
MCP ToolMCPToolset connecting to MCP serverReusing ecosystem tools (filesystem, GitHub, etc.)
OpenAPI ToolOpenAPIToolset from OpenAPI spec URL/fileAuto-generating tools from REST API specs
AgentToolAgentTool(another_agent)Delegation to specialist agents as callable tools
Built-in ToolsGoogle Search, Code Execution, Vertex SearchWeb grounding, code running, enterprise search
Tool design best practices: Return dict objects with a consistent structure (include a "status" key). Keep tools focused on one capability. Avoid side-effectful tools without confirmation (use the action confirmation pattern for irreversible operations). Keep parameter names and types clear — they form the JSON schema the LLM sees.
🔌

MCP Tools

// MODEL CONTEXT PROTOCOL INTEGRATION

ADK natively supports the Model Context Protocol (MCP) — an open standard for connecting AI agents to external tools and data sources. You can consume MCP servers as tools, or expose your ADK agents as MCP-compatible servers.

Consuming MCP Servers

Use MCPToolset to connect to any MCP server. ADK automatically discovers available tools and exposes them to your agent's LLM.

Exposing as MCP Server

Any ADK agent can be wrapped and exposed as an MCP server, making it consumable by other agents, Claude, or any MCP-compatible client.

Python — Connecting to an MCP server
from google.adk.tools.mcp_tool import MCPToolset from mcp import StdioServerParameters # Connect to a local MCP server (e.g. filesystem server via stdio) mcp_tools, exit_stack = await MCPToolset.from_server( connection_params=StdioServerParameters( command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"], ) ) agent = LlmAgent( name="file_agent", model="gemini-2.0-flash", tools=mcp_tools, # all tools from MCP server auto-discovered instruction="You can read and write files in the allowed directory.", )
💡

Supported Models

// MODEL BACKENDS & CONFIGURATION
Model / BackendIdentifier / ConfigNotes
Gemini 2.0 Flash "gemini-2.0-flash" Recommended default. Fast, multimodal, tool-use optimized.
Gemini 2.5 Pro "gemini-2.5-pro-preview-03-25" Best reasoning. Use with BuiltInPlanner for thinking mode.
Gemini Flash Latest "gemini-flash-latest" Tracks latest flash release automatically.
Anthropic Claude Via LiteLLM: "claude-3-5-sonnet" Requires ANTHROPIC_API_KEY. Use LiteLLM integration.
Ollama (local) OllamaModel("llama3.2") Runs fully local. Requires Ollama installed and model pulled.
LiteLLM LiteLlm("openai/gpt-4o") Proxy to any OpenAI-compatible API. Supports 100+ models.
vLLM VLLMModel(...) For self-hosted GPU inference. OpenAI-compatible endpoint.
Gemma 2/3 (local) Via LiteRT-LM or Ollama On-device inference via LiteRT-LM for edge deployments.
ℹ️
Model routing: ADK supports dynamic model routing — different agents in a system can use different models. A cheap/fast model handles routing and triage; expensive/capable models handle complex reasoning. Use ModelRouter for runtime routing based on task characteristics.
💾

Sessions & State

// PERSISTENCE & CONTEXT ACROSS TURNS

Every agent interaction happens within a session. Sessions store conversation history and a mutable state dictionary. State is the primary communication channel between agents in a pipeline — write with output_key, read with {state_var} in instructions.

Session Services
  • InMemorySessionService — development / testing. No persistence.
  • DatabaseSessionService — SQL-backed, production-ready.
  • VertexAISessionService — managed, Vertex AI Agent Engine.
  • Custom implementations via BaseSessionService interface.
State Scopes
  • Session state (session.state) — scoped to current conversation.
  • User state (user: prefix) — persists across sessions for a user.
  • App state (app: prefix) — shared across all users of the app.
  • Temp state (temp: prefix) — current turn only, not persisted.
Python — Session and Runner setup
from google.adk.sessions import InMemorySessionService from google.adk.runners import Runner from google.genai import types APP_NAME = "my_app" USER_ID = "user_123" SESSION_ID = "session_abc" # Set up session service and create a session session_service = InMemorySessionService() session = await session_service.create_session( app_name=APP_NAME, user_id=USER_ID, session_id=SESSION_ID, state={"user_name": "Alice"}, # pre-populate state ) # Create runner — bridges the agent and session service runner = Runner(agent=root_agent, app_name=APP_NAME, session_service=session_service) # Run the agent user_msg = types.Content(role="user", parts=[types.Part(text="Hello!")]) async for event in runner.run_async( user_id=USER_ID, session_id=SESSION_ID, new_message=user_msg ): if event.is_final_response() and event.content: print(event.content.parts[0].text)
🧠

Memory

// LONG-TERM & CROSS-SESSION KNOWLEDGE
In-Session Memory

Conversation history is managed automatically within a session. Use context_caching to cache large static contexts (system prompts, documents) and reduce latency + cost. Use context_compaction for long conversations that would exceed the context window.

Long-Term Memory

Implement BaseMemoryService to persist and retrieve facts across sessions. Vertex AI Agent Engine provides a managed memory service. Use the load_memory tool to inject relevant memories into context on each turn.

Context management strategy: For large knowledge bases, use Grounding with Vertex AI Search or Google Search rather than stuffing content into context. Context caching (via CachingConfig) can cut costs by 75%+ on repeated large prompts like extensive system instructions or reference documents.
↩️

Callbacks

// HOOKS INTO AGENT LIFECYCLE

Callbacks let you intercept and observe — or modify — the agent execution lifecycle without subclassing. They are the recommended way to add logging, guardrails, caching, and custom behavior.

CallbackFires whenCan override?
before_agent_callbackBefore any agent starts executingYes — return early to skip execution
after_agent_callbackAfter an agent finishes executingYes — modify the response
before_model_callbackBefore LLM is called (has the LLM request)Yes — short-circuit with cached response
after_model_callbackAfter LLM returns (has the LLM response)Yes — modify response, add guardrails
before_tool_callbackBefore a tool is executedYes — modify args, skip, or mock
after_tool_callbackAfter a tool returnsYes — modify tool result
Python — Guardrail with before_model_callback
from google.adk.agents.callback_context import CallbackContext from google.adk.models import LlmRequest, LlmResponse from google.genai import types def block_inappropriate_content( callback_context: CallbackContext, llm_request: LlmRequest ) -> LlmResponse | None: """Block requests containing banned keywords before hitting the LLM.""" banned = ["hack", "exploit"] last_msg = llm_request.contents[-1].parts[0].text.lower() if any(word in last_msg for word in banned): # Returning a response short-circuits the LLM call return LlmResponse( content=types.Content( parts=[types.Part(text="I can't help with that.")] ) ) return None # None = proceed normally agent = LlmAgent( name="safe_agent", model="gemini-2.0-flash", before_model_callback=block_inappropriate_content, )
▶️

Runtime & Interfaces

// RUNNING YOUR AGENT
💻
CLI
Interactive terminal session. Type messages and see responses. Best for rapid iteration during development.
adk run my_agent
🌐
Web UI
Browser-based chat interface with full event inspection and state visualization. Dev mode only.
adk web --port 8000
🔌
API Server
FastAPI-based HTTP server with REST endpoints. Suitable for integration testing and simple deployments.
adk api_server
📡
Ambient
Event-driven, always-on agents triggered by external events (emails, webhooks, schedules) rather than user input.
// Proactive agents
⏸️
Resume / Cancel
Long-running agents can be suspended (e.g. waiting for human approval) and resumed or cancelled later.
// Human-in-the-loop
Shell — all CLI commands
# Create a new agent project adk create <agent_name> # Interactive CLI run adk run <agent_name_or_path> # Web dev UI (run from parent dir of agent folder) adk web [--port 8000] # REST API server adk api_server [--port 8080] [--host 0.0.0.0] # Evaluate agent against test cases adk eval <agent_path> <eval_set.json> # Deploy to Agent Runtime agents deploy <agent_path> # Run with RunConfig overrides adk run <agent> --run_config '{"max_llm_calls": 10}'
📡

Streaming

// GEMINI LIVE API & REAL-TIME AGENTS

ADK supports bidirectional streaming via the Gemini Live API through the Gemini Live API Toolkit. This enables real-time voice and video agents with low-latency responses. Streaming agents handle audio input, image frames, and text simultaneously.

Standard Streaming

The run_async method yields events as they arrive — text is streamed token by token in the event stream. Works with all ADK agents out of the box.

Gemini Live API

For voice/video: uses the LiveRequestQueue and websocket transport. Supports audio input/output, video frames, and real-time interruption. Requires Gemini models with Live API support.

ℹ️
Streaming tools: ADK supports a special Streaming Tools pattern where a tool itself can stream incremental updates back to the user (e.g., showing intermediate steps of a long computation). Tools declare themselves as streaming via is_long_running=True.
🚀

Deployment

// TAKING AGENTS TO PRODUCTION
TargetBest forCommand / Notes
Agent Runtime Managed, Vertex AI-integrated, sessions + memory included agents deploy <path> via agents-cli
Cloud Run Serverless HTTP, auto-scaling, simple containerized agents Dockerfile + gcloud run deploy; ADK docs provide templates
GKE High-traffic, custom networking, GPU workloads, fine control Kubernetes deployment manifest; use Workload Identity for secrets
Dockerfile — Cloud Run deployment
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY my_agent/ ./my_agent/ # Expose agent as FastAPI server CMD ["adk", "api_server", "--host", "0.0.0.0", "--port", "8080", "my_agent"]
Deployment Checklist Before Ship
  • Never commit .env or API keys — use Secret Manager
  • Set GOOGLE_CLOUD_PROJECT for Vertex AI authentication
  • Run adk eval against your test set before deploying
  • Configure logging to Cloud Logging (structured JSON format)
  • Set max_llm_calls in RunConfig to prevent runaway loops
  • Use DatabaseSessionService — not InMemory — in production
Observability Stack Recommended
  • Logs: Cloud Logging + structured ADK event logs
  • Traces: Cloud Trace via OpenTelemetry integration
  • Metrics: LLM call count, tool call rate, latency P95
  • Eval: Automated eval runs in CI/CD pipeline
  • Alerts: Error rate > 1%, P95 latency > 10s
📊

Evaluation

// MEASURING & IMPROVING AGENT QUALITY

ADK has first-class evaluation support. Before deploying, run structured evaluations to measure whether your agent achieves its intended goals, handles edge cases, and uses tools correctly.

Trajectory Eval

Checks that the agent followed the right sequence of steps — correct tool calls in the right order. Deterministic pass/fail.

Response Quality

LLM-judged evaluation of final response quality against reference answers. Configurable rubrics and scoring criteria.

User Simulation

A "user simulator" LLM plays the user role, driving multi-turn conversations automatically. Useful for testing conversation flows.

JSON — eval set format
[ { "query": "What is the capital of France?", "expected_tool_use": [ { "tool_name": "get_capital_city", "tool_input": { "country": "France" } } ], "reference": "The capital of France is Paris.", "criteria": { "response_match_score": 0.8 } // threshold 0-1 }, { "query": "What time is it in Tokyo?", "expected_tool_use": [ { "tool_name": "get_current_time", "tool_input": { "city": "Tokyo" } } ], "reference": "The current time in Tokyo is..." } ]
🔗

A2A Protocol

// AGENT-TO-AGENT COMMUNICATION STANDARD

The Agent-to-Agent (A2A) Protocol is an open standard that enables interoperability between AI agents built on different frameworks. An ADK agent can both expose itself as an A2A server and consume other A2A agents as tools — enabling cross-framework multi-agent systems.

Exposing (Server)

Wrap any ADK agent with A2AServer to make it discoverable and callable by any A2A-compatible client (ADK, LangChain, custom). Publishes an agent.json capability descriptor.

Consuming (Client)

Use A2AClient to call remote A2A agents from within an ADK agent. The remote agent appears as a regular tool. Works across networks, clouds, and frameworks.

Python — expose an ADK agent via A2A
from google.adk.a2a.server import A2AServer # my_agent.py already defines root_agent server = A2AServer(agent=root_agent, host="0.0.0.0", port=8080) await server.start() # Agent is now available at http://localhost:8080/.well-known/agent.json
A2A is framework-agnostic. An ADK agent can delegate work to a LangGraph agent or a custom A2A server without knowing the implementation. This makes A2A ideal for enterprise multi-team agent ecosystems where different teams own different agents built in different frameworks.