> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://respan.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://respan.ai/_mcp/server.

# Google ADK (tracing)

> Trace Google ADK agent workflows with Respan.

[Google Agent Development Kit (ADK)](https://google.github.io/adk-docs/) is a framework for building agents with tools and multi-agent workflows. Respan captures ADK runner, agent, LLM, and tool spans, then exports them through the Respan tracing pipeline.

This tracing setup uses your Google model credentials directly through ADK. To route model calls through Respan instead, use the [Google ADK gateway setup](/docs/gateway/google-adk).

#### Set up Respan

Create an account at [platform.respan.ai](https://platform.respan.ai) and grab an [API key](https://platform.respan.ai/platform/api/api-keys).

Run `npx @respan/cli setup` to set up with your coding agent.

#### Use Respan Gateway

See [Google ADK gateway setup](/docs/gateway/google-adk) to route model calls through the Respan gateway.

#### Example projects

* [Python examples](https://github.com/respanai/respan-example-projects/tree/main/python/tracing/google-adk)

## Setup

#### Install packages

```bash Python
pip install respan-ai respan-instrumentation-google-adk "google-adk[extensions]"
```

```bash TypeScript
npm install @respan/respan @respan/instrumentation-google-adk @google/adk
```

#### Set environment variables

```bash
export GOOGLE_API_KEY="YOUR_GOOGLE_API_KEY"
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
```

`GOOGLE_API_KEY` is used by ADK for direct model requests. `RESPAN_API_KEY` exports traces to Respan.

#### Initialize and run

```python Python
import asyncio

from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
from respan import Respan
from respan_instrumentation_google_adk import GoogleADKInstrumentor

respan = Respan(instrumentations=[GoogleADKInstrumentor()])

agent = Agent(
    name="assistant",
    model="gemini-2.0-flash",
    instruction="You are a concise assistant.",
)

async def main():
    session_service = InMemorySessionService()
    session = await session_service.create_session(
        app_name="google-adk-demo",
        user_id="user_1",
    )
    runner = Runner(
        agent=agent,
        app_name="google-adk-demo",
        session_service=session_service,
    )
    message = types.Content(
        role="user",
        parts=[types.Part(text="Say hello in one sentence.")],
    )

    async for event in runner.run_async(
        user_id="user_1",
        session_id=session.id,
        new_message=message,
    ):
        if event.is_final_response():
            print(event.content.parts[0].text)

    respan.shutdown()

asyncio.run(main())
```

```typescript TypeScript
import { Respan } from "@respan/respan";
import { GoogleADKInstrumentor } from "@respan/instrumentation-google-adk";

const respan = new Respan({
  apiKey: process.env.RESPAN_API_KEY,
  baseURL: process.env.RESPAN_BASE_URL,
  instrumentations: [new GoogleADKInstrumentor()],
});
await respan.initialize();

// Import ADK after Respan initializes so ADK uses the active OpenTelemetry provider.
const { InMemoryRunner, LlmAgent } = await import("@google/adk");

const agent = new LlmAgent({
  name: "weather_agent",
  model: "gemini-2.5-flash",
  instruction: "Answer weather questions concisely.",
});

const runner = new InMemoryRunner({
  appName: "google-adk-demo",
  agent,
});

for await (const event of runner.runEphemeral({
  userId: "demo-user",
  newMessage: {
    role: "user",
    parts: [{ text: "What is the weather in Tokyo?" }],
  },
})) {
  console.log(event.content?.parts?.map((part) => part.text).join(""));
}

```

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) to see ADK runner, agent, model, and tool spans.

## Configuration

| Parameter              | Type                                  | Default           | Description                                                                                        |
| ---------------------- | ------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------- |
| `api_key` / `apiKey`   | `str \| None` / `string \| undefined` | `RESPAN_API_KEY`  | Respan API key used to export traces.                                                              |
| `base_url` / `baseURL` | `str \| None` / `string \| undefined` | `RESPAN_BASE_URL` | Optional Respan trace export API URL.                                                              |
| `instrumentations`     | `list` / `RespanInstrumentation[]`    | `[]`              | Include `GoogleADKInstrumentor()` or `new GoogleADKInstrumentor()` to activate Google ADK tracing. |

## Attributes

### In Respan()

Set defaults at initialization. These apply to all spans from the instrumented ADK run.

```python Python
from respan import Respan
from respan_instrumentation_google_adk import GoogleADKInstrumentor

respan = Respan(
    instrumentations=[GoogleADKInstrumentor()],
    customer_identifier="user_123",
    metadata={"service": "adk-api", "version": "1.0.0"},
)
```

```typescript TypeScript
import { Respan } from "@respan/respan";
import { GoogleADKInstrumentor } from "@respan/instrumentation-google-adk";

// Note: default attributes are set via propagateAttributes() in TypeScript.
const respan = new Respan({
  instrumentations: [new GoogleADKInstrumentor()],
});
```

### With propagate\_attributes

Override per-request attributes using a context scope.

```python Python
from respan import Respan, propagate_attributes
from respan_instrumentation_google_adk import GoogleADKInstrumentor

respan = Respan(instrumentations=[GoogleADKInstrumentor()])

async def handle_request(user_id: str, message: str):
    with propagate_attributes(
        customer_identifier=user_id,
        thread_identifier="conv_abc_123",
        metadata={"plan": "pro"},
    ):
        output = await run_agent_once(message)
        return output
```

```typescript TypeScript
import { Respan } from "@respan/respan";
import { GoogleADKInstrumentor } from "@respan/instrumentation-google-adk";

const respan = new Respan({
  instrumentations: [new GoogleADKInstrumentor()],
});
await respan.initialize();

async function handleRequest(userId: string, message: string) {
  await respan.propagateAttributes(
    {
      customer_identifier: userId,
      thread_identifier: "conv_abc_123",
      metadata: { plan: "pro" },
    },
    async () => {
      await runAgentOnce(message);
    }
  );
}
```

| Attribute             | Type                               | Description                                  |
| --------------------- | ---------------------------------- | -------------------------------------------- |
| `customer_identifier` | `str` / `string`                   | Identifies the end user in Respan analytics. |
| `thread_identifier`   | `str` / `string`                   | Groups related messages into a conversation. |
| `metadata`            | `dict` / `Record<string, unknown>` | Custom key-value pairs.                      |

## Captured spans

* ADK runner invocations as workflow spans
* Agent invocations as agent spans
* Model calls as chat spans with prompts, completions, tool definitions, and token fields
* Tool executions as tool spans with normalized input and output