Back to Devoured - October 16, 2026
DEVOURED
One Agent Development Kit, Five Languages

One Agent Development Kit, Five Languages

DevOps Google Cloud
Google's Agent Development Kit (ADK) now supports five languages, allowing interoperability across diverse agent runtimes using MCP and A2A protocols.
What: Karl Weinmeister announced ADK support for Python, Go, TypeScript, Java, and Kotlin. All versions share a unified architecture utilizing the Model Context Protocol (MCP) and Agent2Agent (A2A) for cross-service communication.
Why it matters: By providing native SDKs across languages, Google aims to standardize agent orchestration for backend production environments rather than forcing a Python-only architecture.
Takeaway: If you are building production-grade agents in Go or Java, explore the ADK scaffolds to leverage built-in A2A protocols and Kubernetes deployment configurations.
Deep dive
  • Python acts as the reference implementation with broad library support.
  • Go targets backend performance, utilizing compiled binaries, static base images, and efficient concurrency.
  • TypeScript utilizes Zod for type-safe schema generation.
  • Java integrates with Spring Boot and Maven/Gradle workflows.
  • Kotlin features zero-reflection design via KSP for Android and high-performance server environments.
  • ADK 2.0 introduces graph-based workflow orchestration with conditional routing.
Decoder
  • MCP (Model Context Protocol): An open standard for connecting AI assistants to external systems, data, and tools.
  • A2A (Agent2Agent Protocol): A protocol enabling direct communication between agents over HTTP.
  • Distroless: Minimalist container images that contain only the application and its runtime dependencies, excluding shells and package managers to reduce attack surface.
Original article

One Agent Development Kit, five languages

When we talk about agents, that doesn't necessarily mean we're talking about Python. In today's modern ecosystem, an agent might run as a high-concurrency Go microservice on Cloud Run, or live inside a browser tab calling Chrome's on-device model. Yet many agent frameworks assume a Python-only stack. That assumption forces teams to either spin up a Python service just for their agent workloads, or to build agent orchestration logic from scratch in their own language.

Google's Agent Development Kit (ADK) removes that trade-off with coverage for Python, Go, TypeScript, Java, and Kotlin. Each version of the ADK is built from the ground up for its own runtime and type system, while sharing a unified architecture with interoperability through open protocols.

A shared foundation

Picking a language doesn't lock in your architecture: all five support the same open protocols. ADK includes a Model Context Protocol client in every language, so a custom tool exposed as an MCP server can be called from any of them immediately.

For multi-agent systems, ADK supports the Agent2Agent (A2A) protocol, allowing an agent to communicate with a remote agent over HTTP. Through A2A, agents written in different languages or frameworks are interoperable.

Starting agent-first

To get started, run the one-time setup command to check your Google Cloud authentication, install the CLI, and then set up first-party ADK skills in coding agents like Antigravity, Claude Code, or Codex:

uvx google-agents-cli setup

Then, run the scaffold command to generate a working project with A2A endpoints and deployment config for Cloud Run, Gemini Enterprise Agent Runtime, or Google Kubernetes Engine (GKE):

# Scaffold an ADK project (use --agent adk for Python or --agent adk_go for Go) 
agents-cli scaffold create my-go-agent \ 
  --agent adk_go \ 
  --deployment-target cloud_run \ 
  --region us-central1

Both the ADK for Python and ADK for Kotlin repositories also ship agent builder skills in their source trees, and the adk.dev/llms.txt resource gives any coding agent on-demand API documentation across all five languages.

Coding-agent skills scaffold your project while MCP and A2A connect all five language runtimes.

Hands-on view of each ADK

The clearest way to feel the difference between the five languages is to define the same weather tool in each one and see how its design fits the runtime.

Python

In ADK for Python, you don't need a decorator or a schema builder class. You pass a plain Python function into the tools parameter, and ADK inspects its signature, type hints, and docstring at startup to automatically construct the tool declaration and Pydantic parameter schema:

from google.adk.agents.llm_agent import Agent

def get_weather(city: str) -> dict:
    """Retrieves the current weather report for a specified city.
    Args:
        city (str): The name of the city for which to retrieve the weather report.
    """
    return {"status": "success", "report": f"Sunny and 72F in {city}."}

root_agent = Agent(
    name="weather_agent",
    model="gemini-3.8-flash",
    instruction="Answer questions about the weather in a city.",
    tools=[get_weather],
)

Beyond fast prototyping, Python is ADK's reference implementation, shipping the broadest set of Google Cloud integrations (BigQuery, Spanner, Bigtable) and model adapters (Gemini, Anthropic, OpenAI, LiteLLM). Paired with the adk eval or agents-cli eval run commands, its evaluation tooling scores agent trajectories against golden datasets in continuous integration (CI) to test the whole system end to end, even when your production service runs in another language.

Go

While Python leads in experimentation and evaluation, ADK for Go hits the sweet spot for production backend engineering.

A Go tool function takes the agent.Context configuration and a strongly typed input struct. The functiontool.New function uses Go generics to infer both the input and output schemas from your struct tags:

type GetWeatherArgs struct {
    City string `json:"city" jsonschema:"The city to look up weather for."`
}
type GetWeatherResult struct {
    Report string `json:"report"`
}

func getWeather(_ agent.Context, args GetWeatherArgs) (GetWeatherResult, error) {
    return GetWeatherResult{Report: "Sunny and 72F in " + args.City}, nil
}

weatherTool, err := functiontool.New(functiontool.Config{
    Name:        "get_weather",
    Description: "Retrieves the current weather report for a city.",
}, getWeather)

Because the functiontool.New function is generic over your handler's signature, the Go compiler verifies that your function matches the expected contract before your binary ever runs.

Go was also the first language after Python to ship the ADK 2.0 Graph Workflow runtime. When you need deterministic control flow alongside LLM reasoning, the workflow.New function wires agents and plain Go functions into a directed graph with conditional routing and parallel steps:

ag, err := workflowagent.New("order_pipeline", []workflow.Edge{
    {From: workflow.Start, To: triageNode},
    {From: triageNode, To: fulfillNode, Route: workflow.StringRoute("fulfill")},
    {From: fulfillNode, To: notifyNode},
})

Where Go really stands out is in production on Cloud Run and GKE. A compiled Go agent packages onto a roughly 2 MiB Google distroless static base image, with no language VM or heavy dependency tree. A static Go binary binds to its port as soon as the container starts, skipping the module imports of dynamic languages and the JAR unpacking and JIT warmup of JVM services.

After it's running, Go's concurrency model fits agent workloads naturally. Each goroutine starts with a 2 KB stack and minimal scheduling overhead, so a single instance can multiplex thousands of concurrent streaming requests and tool calls. ADK for Go also includes built-in A2A server handlers and OpenTelemetry tracing out of the box.

TypeScript

TypeScript erases type annotations when compiling to JavaScript, so runtime reflection isn't an option. Instead, ADK for TypeScript pairs with Zod. You pass a z.object(...) schema to the FunctionTool function, and TypeScript statically infers the parameter types of your execute callback from that single declaration:

import { FunctionTool, LlmAgent } from "@google/adk";
import { z } from "zod";

const getWeatherTool = new FunctionTool({
  name: "get_weather",
  description: "Retrieves the current weather report for a city.",
  parameters: z.object({
    city: z.string().describe("The name of the city."),
  }),
  execute: async ({ city }) => {
    return { status: "success", report: `Sunny and 72F in ${city}.` };
  },
});

export const rootAgent = new LlmAgent({
  name: "weather_agent",
  model: "gemini-3.8-flash",
  instruction: "Answer questions about the weather in a city.",
  tools: [getWeatherTool],
});

Your runtime input validation, the JSON Schema sent to the model, and your IDE autocomplete inside the execute callback all flow from one source of truth.

TypeScript also runs on the ADK 2.0 Graph Workflow engine and ships a standalone browser bundle. Beyond Node.js services, you can run an ADK agent directly in a browser tab using WebMCP for page-level tools and Chrome's on-device Prompt API.

Java

ADK for Java snaps right in for teams who have standardized on Maven, Gradle, and Spring Boot. You add @Schema annotations to method parameters and assemble agents by using a fluent LlmAgent.builder() API:

public class WeatherTools {
    public static Map<String, String> getWeather(
        @Schema(name = "city", description = "The name of the city") String city) {
        return Map.of("status", "success", "report", "Sunny and 72F in " + city);
    }
}

LlmAgent agent = LlmAgent.builder()
    .name("weather_agent")
    .model("gemini-3.8-flash")
    .instruction("Answer questions about the weather in a city.")
    .tools(FunctionTool.create(WeatherTools.class, "getWeather"))
    .build();

At runtime, the runner streams agent events reactively through RxJava. For local testing and existing JVM apps, ADK for Java ships a Maven Dev UI plugin alongside first-party bridges for Spring AI and LangChain4j.

Kotlin

ADK for Kotlin takes a strong stance on build-time safety. Its Kotlin Symbol Processing (KSP) compiler plugin reads @Tool and @Param annotations at build time and emits the tool schema directly into bytecode:

class WeatherTools {
    @Tool(
        name = "get_weather",
        description = "Retrieves the current weather report for a city.",
    )
    suspend fun getWeather(
        @Param("The name of the city.") city: String
    ): Map<String, String> = mapOf("status" to "success", "report" to "Sunny and 72F in $city")
}

val agent = LlmAgent(
    model = Gemini("gemini-3.8-flash"),
    name = "weather_agent",
    instruction = Instruction("Answer questions about the weather in a city."),
    tools = WeatherTools().generatedTools(),
)

If a tool signature uses an unsupported type or declares a default value on a non-nullable parameter, your Gradle build fails immediately instead of breaking in production. Because the .generatedTools() function uses zero runtime reflection, it survives Android R8 shrinking.

That zero-reflection design makes it possible to run the entire agent loop locally on Android. It offers JVM server support, including a Spring AI bridge and experimental ADK 2.0 graph workflows. On-device, ADK for Kotlin integrates with LiteRT-LM for tool calling and ML Kit (Gemini Nano) for text generation. It also works with Room and AppSearch for local state, and Android AppFunctions for OS-level actions, all without requiring a network connection.

Choice without compromise

Having five native languages in ADK means you don't have to pick a single runtime for your entire organization. Because every version of ADK speaks MCP and A2A, each component of your system can use the language that fits it best.

What languages have you used to build agents with Google's ADK? Let me know what stack you're running on X, LinkedIn, or Bluesky.

Explore all 51 articles in today's digest

Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi