Skip to content

Add agent-adk: a Google ADK conversational agent template#246

Open
andrew-fleischer-databricks wants to merge 1 commit into
databricks:mainfrom
andrew-fleischer-databricks:agent-adk
Open

Add agent-adk: a Google ADK conversational agent template#246
andrew-fleischer-databricks wants to merge 1 commit into
databricks:mainfrom
andrew-fleischer-databricks:agent-adk

Conversation

@andrew-fleischer-databricks

Copy link
Copy Markdown

Summary

Adds agent-adk, a new Python starter template built on Google's Agent Development Kit (ADK v2.x). It mirrors the functionality of the existing agent-langgraph / agent-openai-agents-sdk templates — a conversational agent implementing the MLflow Responses API with the shared chat UI, MLflow tracing, and Databricks Asset Bundle deployment — while conforming to the repo's Python template conventions (real mlflow.genai.agent_server @invoke()/@stream() handlers, not a hand-rolled server).

Why add an ADK agent template?

Databricks Apps intentionally ships agent starter templates across several frameworks — LangGraph, the OpenAI Agents SDK, and a TypeScript LangChain variant — so developers can start from the framework they already know rather than being forced onto one. Google's Agent Development Kit (ADK) is a notable gap: it has real developer and customer traction, and its absence meant ADK users had no on-ramp to building agents on Databricks Apps. agent-adk closes that gap while conforming to the exact same contract as the other templates — the MLflow Responses API via @invoke()/@stream() handlers, the shared chat UI, MLflow tracing, and DAB deployment — so framework choice never changes the deployment story.

  • Framework parity and ecosystem completeness. Adds a first-class Google ADK option alongside the existing LangGraph and OpenAI Agents SDK templates, so ADK is a supported, equal-footing choice rather than a missing one.
  • Any Databricks endpoint, no lock-in. ADK reaches model serving through LiteLLM (LiteLlm(model="openai/<endpoint>", api_base="{host}/serving-endpoints")), so the agent can target any Databricks or Foundation Model API endpoint by name; the default is databricks-claude-sonnet-4-5.
  • ADK's native agent/tool/session model. Uses ADK's LlmAgent, Runner, and session services directly. The base template is stateless — it replays client-carried history into an InMemorySessionService per request — with a documented path to a Lakebase DatabaseSessionService or managed memory.
  • MCP tool support. Databricks-hosted MCP tools (UC functions, Genie, Vector Search, the built-in code interpreter) plug in via ADK's MCPToolset, matching the tool story of the other templates.
  • Integrated tracing. mlflow.litellm.autolog() captures every model call as a span, giving the same end-to-end observability as the LangGraph and OpenAI variants.
  • Audience. Teams that prefer or standardize on Google ADK, and anyone wanting to evaluate agent frameworks side-by-side on Databricks under one consistent deployment model.

What an engineer needs to know

  • Auth to the model. build_model() builds a LiteLlm per request with a bearer token pulled from the SDK credential chain (WorkspaceClient.config.authenticate()). Resolved per request, so it refreshes naturally and works for local CLI profiles and the deployed App service principal alike. This is more explicit than the LangChain/OpenAI clients only because LiteLLM needs a concrete api_key.
  • Statelessness / session model. No server-side state. Each request builds a fresh InMemorySessionService; seed_session_history() replays prior user/assistant text turns (system + tool turns intentionally dropped) and hands ADK the latest user turn. Durable memory is a documented add-on (Lakebase DatabaseSessionService via lakebase-setup, or managed-memory), not shipped in the base.
  • Tracing is a third autolog pattern. LangGraph→langchain, OpenAI→openai, ADK→mlflow.litellm.autolog(), because ADK routes all model calls through LiteLLM. Documented in .claude/AGENTS.md.
  • Tool-output shape. ADK wraps a tool's scalar return as {"result": <value>}. process_adk_events unwraps the single-key form so outputs are bare strings, matching the other templates (and the shared e2e validate_time assertion).
  • Dependency floor. google-adk>=2.0.0,<3 — the code targets the 2.x API (RunConfig/StreamingMode.SSE, current LiteLlm/MCPToolset import paths).
  • Serving-endpoint access. No serving-endpoint resource grant in databricks.yml (relies on Foundation Model API default access, matching agent-langgraph). Pointing the template at a custom/provisioned endpoint requires adding a grant — see the add-tools skill / examples/serving-endpoint.yaml.
  • MCP is opt-in. Commented out by default; enabling it needs uv add "google-adk[extensions]" (the mcp extra is not a base dependency).
  • Skills/app.yaml. Ships add-tools/modify-agent (from new source skills add-tools-adk/modify-adk-agent), plus app.yaml + manifest.yaml so it's UI-creatable like the other base templates. lakebase-setup and managed-memory are synced; there is no ADK-specific memory template (base is stateless by design).

Testing

Ran the repo e2e suite against a live workspace: uv run pytest test_e2e.py --template agent-adk (full local and deploy).

  • Local phase — pass. All six endpoint paths: /responses and /invocations, each JSON + SSE streaming, plus OpenAI-SDK non-streaming and streaming. get_current_time tool call validated (validate_time).
  • Deploy phase — pass. Full DAB deployrun → app reached RUNNING → /agent/info 200 → all six endpoint checks green on the real deployed Databricks App → bundle destroy. The tool-output-shape fix is confirmed on the deployed app, not just locally.
  • agent-evaluate — not validated in this run. It failed on a Databricks CLI U2M OAuth token-cache concurrency race (exit status 45), triggered by MLflow's ConversationSimulator doing concurrent SDK token force-refreshes. This is environmental and reproduces independent of the template (it will affect any template's evaluate step under a U2M profile); it should pass under CI / a PAT or service-principal profile. Flagging for the e2e-suite maintainers as non-adk-specific.
  • Deterministic ADK→Responses adapter unit test passes; build_templates() registry cross-check passes; uv sync resolves cleanly.

Notes / follow-ups

  • Re-running both sync scripts is idempotent and leaves the tree clean.
  • Minor doc polish deferred (non-blocking): lakebase-setup's shared body still frames agent memory only for the LangGraph/OpenAI advanced templates, and the MCP error-handling snippet in add-tools-adk shows a timeout example rather than the try/except it describes.

This pull request and its description were written by Isaac.

New Python agent template built on Google's Agent Development Kit (ADK
v2.x), mirroring the agent-langgraph / agent-openai-agents-sdk
conventions: MLflow Responses API via @invoke()/@stream() handlers, the
shared chat UI, MLflow tracing, and DAB deployment to Databricks Apps.

Design:
- Model access via LiteLLM (openai/<endpoint> against
  {host}/serving-endpoints), so any Databricks / Foundation Model API
  endpoint works by name; per-request bearer token from the SDK
  credential chain. Default endpoint: databricks-claude-sonnet-4-5.
- Stateless base: client-carried history is replayed into a per-request
  InMemorySessionService (seed_session_history); ADK Events are adapted
  to Responses stream events (process_adk_events).
- Tracing via mlflow.litellm.autolog() (ADK routes model calls through
  LiteLLM), nested under the @invoke()/@stream() request trace.
- MCP tools (UC functions, Genie, Vector Search, code interpreter) via
  ADK MCPToolset, commented out by default (needs google-adk[extensions]).
- Pinned google-adk>=2.0.0,<3 (targets the 2.x API surface).

process_adk_events unwraps ADK's {"result": <value>} tool-response
wrapping so tool outputs are a bare string, matching the other templates
and the shared e2e validate_time contract.

Repo wiring:
- Register agent-adk (sdk="adk") in .scripts/templates.py; add e2e entry
  in template_config.py; new source skills add-tools-adk and
  modify-adk-agent; .gitignore skill allowlist; README and
  .claude/AGENTS.md conventions (autolog, MCP, session/memory, app.yaml).
- Synced shared scripts and skills via sync-scripts.py / sync-skills.py.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant