> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-5e9cc07a-preview-lsapi-1779323176-451247e.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Google ADK agents

> Deploy Google Agent Development Kit (ADK) agents to LangSmith Agent Server using the deployments-wrap-sdk package.

This guide shows you how to deploy a [Google Agent Development Kit (ADK)](https://github.com/google/adk-python) agent on [LangSmith Agent Server](/langsmith/agent-server) using the [`deployments-wrap-sdk`](https://pypi.org/project/deployments-wrap-sdk/) package.

`deployments-wrap-sdk` provides a thin wrapper that turns a configured ADK `Runner` into a LangGraph-compatible graph, so you can deploy ADK agents without writing the [Functional API](/oss/python/langgraph/functional-api) glue yourself. The wrapper:

* Bridges ADK sessions to Agent Server's [checkpoint persistence](/langsmith/agent-server#persistence), so session state survives restarts and resumes across runs.
* Forwards ADK token events through LangGraph's streaming pipeline, so partial tokens show up in [`stream_mode="messages"`](/langsmith/streaming) and in [LangSmith Studio](/langsmith/studio).
* Automatically enables [LangSmith tracing](/langsmith/trace-with-google-adk) for ADK when `LANGSMITH_TRACING` is set.

## Prerequisites

* Python 3.11+
* [LangGraph CLI](/langsmith/cli) for local dev and deployment
* A LangSmith API key, refer to [Create an account and API key](https://docs.langchain.com/langsmith/create-account-api-key)
* A Google AI API key if you use Gemini models, refer to [Google AI Studio](https://aistudio.google.com/api-keys)

## Installation

Install the package with the `google-adk` extra. The extra pulls in `google-adk` and other dependencies needed for the wrapper:

```bash theme={null}
pip install "deployments-wrap-sdk[google-adk]"
```

<Note>
  The PyPI distribution name is `deployments-wrap-sdk`, but the Python import path is `saf_sdk`. Both refer to the same package.
</Note>

## Quickstart

This minimal example builds an agent that returns the input as its response and does not require a model API key. The agent bypasses the LLM call so you can verify that the deployment works correctly before connecting a real model.

Create `agent.py`:

```python agent.py theme={null}
from google.adk.agents import Agent
from google.adk.models.llm_response import LlmResponse
from google.adk.runners import Runner
from google.genai.types import Content, Part
from saf_sdk.adk import LangsmithSessionService, wrap


def echo_callback(callback_context, llm_request):
    """Return the user's message instead of calling a real model."""
    user_text = ""
    if callback_context.user_content and callback_context.user_content.parts:
        for part in callback_context.user_content.parts:
            if part.text:
                user_text += part.text
    return LlmResponse(
        content=Content(role="model", parts=[Part(text=f"echo: {user_text}")])
    )


agent = wrap(
    Runner(
        agent=Agent(
            name="echo_agent",
            model="gemini-2.0-flash",
            instruction="Echo the user message.",
            before_model_callback=echo_callback,
        ),
        app_name="adk_echo",
        session_service=LangsmithSessionService(),
    )
)
```

Two things are essential:

1. **Pass `LangsmithSessionService()`** as the runner's `session_service`. `wrap()` raises a `TypeError` if you forget. Agent Server needs this hook to load and save ADK session state through its checkpointer.
2. **Export the wrapped `agent`** as a module-level variable. Agent Server imports this symbol when serving the graph.

For a real agent, drop the `before_model_callback` and configure a model directly. For example, use Gemini by setting `model="gemini-2.0-flash"` with `GOOGLE_API_KEY` set, or use Claude/OpenAI via ADK's LiteLLM adapter (`google.adk.models.lite_llm.LiteLlm`, available through `google-adk[extensions]`).

## Project layout

A deployable project needs three files:

```
my-adk-agent/
├── agent.py              # exports the wrapped agent
├── langgraph.json        # Agent Server config
└── pyproject.toml        # Python dependencies
```

[`langgraph.json`](/langsmith/application-structure#configuration-file-concepts) points Agent Server at the exported symbol:

```json langgraph.json theme={null}
{
  "$schema": "https://langgra.ph/schema.json",
  "dependencies": ["."],
  "graphs": {
    "adk_echo": "./agent.py:agent"
  },
  "env": ".env"
}
```

`pyproject.toml` declares dependencies:

```toml pyproject.toml theme={null}
[project]
name = "my-adk-agent"
version = "0.0.1"
requires-python = ">=3.11"
dependencies = [
    "deployments-wrap-sdk[google-adk]>=0.0.1",
]
```

## Install dependencies

```bash theme={null}
pip install -e .
```

## Run locally

Start the local Agent Server with the [LangGraph CLI](/langsmith/cli):

```bash theme={null}
langgraph dev
```

This serves the agent at `http://127.0.0.1:2024` and opens [LangSmith Studio](/langsmith/studio) so you can chat with the agent. Send a request directly with `curl`:

```bash theme={null}
# Create a thread
THREAD=$(curl -s -X POST http://127.0.0.1:2024/threads \
  -H "Content-Type: application/json" -d '{}' | python -c "import sys, json; print(json.load(sys.stdin)['thread_id'])")

# Run the agent and wait for the final response
curl -s -X POST "http://127.0.0.1:2024/threads/$THREAD/runs/wait" \
  -H "Content-Type: application/json" \
  -d '{
    "assistant_id": "adk_echo",
    "input": {"messages": [{"type": "human", "content": "Hello"}]}
  }'
```

## Deploy to LangSmith

Once the agent runs locally, deploy it to LangSmith with `langgraph deploy`:

```bash theme={null}
langgraph deploy --name my-adk-agent
```

For environment configuration, deployment types, and revision management, refer to [Deploy to cloud](/langsmith/deploy-to-cloud). For self-hosted setups, refer to [Self-hosted deployments](/langsmith/self-hosted).

## Enable tracing

`wrap()` calls `langsmith.integrations.google_adk.configure_google_adk()` automatically whenever LangSmith tracing is enabled, so all you need to do is set the environment variables on the deployment:

```bash .env theme={null}
LANGSMITH_API_KEY=your-langsmith-api-key
LANGSMITH_TRACING=true
LANGSMITH_PROJECT=my-adk-agent     # optional
GOOGLE_API_KEY=your-google-api-key
```

[Traces](/langsmith/observability) show agent invocations, tool calls, and LLM interactions in the [LangSmith UI](https://smith.langchain.com?utm_source=docs\&utm_medium=cta\&utm_campaign=langsmith-signup\&utm_content=langsmith-deploy-google-adk). For more on the underlying tracing integration, see [Trace Google ADK applications](/langsmith/trace-with-google-adk).

## API reference

### `wrap(runner)`

Wraps a configured `google.adk.runners.Runner` and returns a LangGraph `Pregel` graph that can be exported from your module and served by Agent Server.

| Argument | Type                        | Description                                                                             |
| -------- | --------------------------- | --------------------------------------------------------------------------------------- |
| `runner` | `google.adk.runners.Runner` | A configured ADK Runner. Its `session_service` **must** be a `LangsmithSessionService`. |

**Returns:** A `Pregel` graph whose name is `runner.app_name`.

**Raises:** `TypeError` if `runner.session_service` is not a `LangsmithSessionService`.

If `runner.agent` defines an `output_key`, that key's value is also exposed on the graph's output, in addition to `messages`. This is what makes ADK structured-output agents (`output_schema=...`, `output_key=...`) work with Studio and the `/runs/wait` response.

### `LangsmithSessionService`

A `google.adk.sessions.BaseSessionService` implementation backed by Agent Server's checkpoint store. The wrapper manages session lifecycle automatically. It creates a session on the first turn of a thread, loads it from the checkpoint on subsequent turns, and writes the updated session back when the run completes.

Use a fresh instance per `Runner`:

```python theme={null}
session_service = LangsmithSessionService()
```

You should not need to call its methods directly; `wrap()` drives them through ADK's normal session lifecycle.

### `ADKInput`

The default input schema for a wrapped agent.

| Field         | Type                     | Description                                                                                                           |
| ------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `messages`    | `list[AnyMessage]`       | (Required) Conversation messages; the wrapper sends `messages[-1].content` to the ADK runner as the new user message. |
| `state_delta` | `dict[str, Any] \| None` | (Optional) Passed through to `runner.run_async(state_delta=...)` to mutate ADK session state for this turn.           |

### `ADKOutput`

The default output schema for a wrapped agent.

| Field      | Type               | Description                                                                                   |
| ---------- | ------------------ | --------------------------------------------------------------------------------------------- |
| `messages` | `list[AnyMessage]` | The agent's response messages, appended to the thread via LangGraph's `add_messages` reducer. |

Exposing `messages` as a typed field (rather than a plain `dict`) is what lets Studio detect the graph as chat-compatible and enable the chat-mode toggle.

## How it works

When a run arrives:

1. The wrapped graph reads `thread_id` from the run config and uses it as the ADK `session_id`. If [authentication](/langsmith/auth) is enabled, the authenticated user's id becomes the ADK `user_id`; otherwise the user id is `"anonymous"`.
2. The wrapper loads the previous session (if any) from the LangGraph checkpoint into `LangsmithSessionService`, then asks the runner to handle the latest message.
3. The runner emits ADK events. The wrapper forwards partial-token events through LangGraph's async callback manager so they stream out via `stream_mode="messages"`, and collects final text for the response message.
4. When the run finishes, the wrapper serializes the ADK session and saves it to the checkpoint via `entrypoint.final(save=...)`. The next run on the same thread resumes from that state.

This means ADK's own session/state semantics are preserved end-to-end while the deployment gets the standard Agent Server features: durable runs, streaming, multi-thread persistence, and tracing.

***

<div className="source-links">
  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>

  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/langsmith/deploy-google-adk.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>
</div>
