# Quickstart: Consuming a remote agent via A2A

Supported in ADKKotlinExperimental

This quickstart covers the most common starting point for any developer: **"There is a remote agent, how do I let my ADK agent use it via A2A?"**. This is crucial for building complex multi-agent systems where different agents need to collaborate and interact.

## Overview

This sample demonstrates the **Agent2Agent (A2A)** architecture in the Agent Development Kit (ADK) for Kotlin, showing how a local agent delegates part of a task to an agent running elsewhere.

```text
┌─────────────────┐         ┌────────────────────────┐
│   Root Agent    │────────▶│   Remote Prime Agent   │
│   (Local)       │◀────────│   (localhost:9090)     │
└─────────────────┘         └────────────────────────┘
```

- **Root Agent** (`root_agent`): The local orchestrator that delegates to sub-agents
- **Prime Agent** (`prime_agent`): A remote A2A agent that checks whether a number is prime, running on a separate A2A server

## Add the A2A dependency

A2A support ships in a separate artifact. The A2A SDK client is needed on the compile classpath as well, because `A2AAgent`'s `httpClient` parameter defaults to `JdkA2AHttpClient()`:

build.gradle.kts

```kotlin
implementation("com.google.adk:google-adk-kotlin-a2a:0.7.0")
implementation("org.a2aproject.sdk:a2a-java-sdk-client:1.0.0.Final")
```

## Start a remote agent server

To consume a remote agent you first need one running. adk-kotlin cannot expose an agent over A2A yet, so the server has to come from elsewhere — A2A is a wire protocol, so any language will do.

The A2A protocol requires each agent to publish an **agent card** describing what it does, served at the well-known path:

```text
http://localhost:9090/.well-known/agent-card.json
```

The Kotlin client reads **A2A 1.0** cards, so the card must carry a `supportedInterfaces` array whose entries each have a `protocolBinding`. Cards written for A2A 0.3 omit it, and `A2AAgent` rejects them with `AgentCardResolutionError: Failed to parse agent card`. That includes the `a2a_server` sample in adk-java and the `remote_a2a` sample in adk-python as they stand today, so neither works as the server for this page yet.

A minimal card the client accepts looks like this:

.well-known/agent-card.json

```json
{
  "name": "check_prime_agent",
  "description": "Checks whether numbers are prime.",
  "version": "1.0.0",
  "url": "http://localhost:9090",
  "preferredTransport": "JSONRPC",
  "capabilities": { "streaming": true },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["application/json"],
  "skills": [],
  "supportedInterfaces": [
    { "protocolBinding": "JSONRPC", "url": "http://localhost:9090" }
  ]
}
```

Check the card is reachable before you continue:

```bash
curl http://localhost:9090/.well-known/agent-card.json
```

## Connect to the remote agent

`A2AAgent` fetches that card and reads the remote agent's description from it, along with whether the remote supports streaming. The `name` you pass is this agent's identifier in your own agent tree, independent of the name the card advertises. It is a suspending function, so call it from a coroutine:

A2AConsumer.kt

```kotlin
// A2AAgent is a suspending factory: it fetches the remote agent's card from
// <url>/.well-known/agent-card.json and takes the description and streaming
// capability from it. The name is yours -- it identifies this agent in your
// tree, independent of the name the card advertises. The constructor of the
// returned agent is internal, so this factory is the only way to build one.
val primeAgent =
    A2AAgent(
        name = "prime_agent",
        agentCardUrl = "http://localhost:9090",
    )
```

If you already hold an `AgentCard` — for example one you resolved yourself, or a static card checked into your configuration — there is a non-suspending overload that takes it directly, `A2AAgent(name = ..., agentCard = ...)`.

## Use it as a sub-agent

The returned agent is a `BaseAgent`, so it goes into `subAgents` exactly like a local one. ADK handles the A2A protocol over the wire:

A2AConsumer.kt

```kotlin
// The remote agent is a BaseAgent, so it goes in subAgents like any local one.
// ADK handles the A2A wire protocol from here.
val rootAgent =
    LlmAgent(
        name = "root_agent",
        model = Gemini(name = "gemini-flash-latest"),
        instruction =
            Instruction(
                "You are a helpful assistant that can check prime numbers " +
                    "by delegating to prime_agent.",
            ),
        subAgents = listOf(primeAgent),
    )
```

## Next Steps

Exposing a Kotlin agent over A2A is not yet supported; adk-kotlin currently provides the consuming side only. To expose an agent, see the quickstarts for the other languages:

- [**A2A Quickstart (Exposing) for Python**](https://adk.dev/a2a/quickstart-exposing/index.md)
- [**A2A Quickstart (Exposing) for Java**](https://adk.dev/a2a/quickstart-exposing-java/index.md)
