adk-go-workflows
Requires `google.golang.org/adk/v2 >= v2.0.0`, which is where the `workflow` package and `agent/workflowagent` first ship.
Real-time voice and video agents built on ADK's **Gemini Live API Toolkit** (`Runner.run_live` + `LiveRequestQueue`). Use this for low-latency spoken conversation and interruption ("barge-in") — not for turn-based request/response agents (use a normal `Agent` with `run_async`
$ npx -y skills add google/agents-cli --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Real-time voice and video agents built on ADK's **Gemini Live API Toolkit** (`Runner.run_live` + `LiveRequestQueue`). Use this for low-latency spoken conversation and interruption ("barge-in") — not for turn-based request/response agents (use a normal `Agent` with `run_async`
Real-time voice and video agents built on ADK's **Gemini Live API Toolkit** (`Runner.run_live` + `LiveRequestQueue`). Use this for low-latency spoken conversation and interruption ("barge-in") — not for turn-based request/response agents (use a normal `Agent` with `run_async` for those).
**Official docs:** [ADK Live Docs](https://adk.dev/live/index.md) · [Configuration](https://adk.dev/live/configuration/index.md) · [Tools](https://adk.dev/live/tools/index.md) · [Get started](https://adk.dev/live/get-started/index.md)
---
| Use `run_live` (Live) | Use `run_async` (normal) | |-----------------------|--------------------------| | Voice/phone assistants, live captioning | Chatbots, tools, batch/RAG | | User can interrupt mid-response | One turn completes before the next | | Continuous audio/video input | Discrete text/multimodal messages | | Latency-critical spoken UX | Latency-tolerant |
> **Live agents can't be served over A2A, and can't be published to Gemini > Enterprise.** Both are request/response with no Live transport. This has > consequences for a scaffolded project beyond the model line — see > "Converting a scaffolded project to Live" next.
There is no Live scaffold template. Scaffold `adk` normally, then make these edits **together** — they are all consequences of one decision, and stopping after the first leaves a project whose `uv run pytest` fails.
| # | File | Edit | |---|------|------| | 1 | `app/agent.py` | Point `MODEL` at a Live model and, on Vertex, add `client_kwargs={"location": …}` to the `Gemini(...)` the scaffold already emits (see "Models"). No `.env` or Terraform change. | | 2 | `app/fast_api_app.py` | Delete the `attach_a2a_routes` call and its imports; delete `app/app_utils/a2a.py` and the `a2a-sdk` dependency. `/run_live` comes from `get_fast_api_app` and is untouched. | | 3 | `tests/integration/test_agent.py` | Rewrite onto `run_live` (below). | | 4 | `tests/integration/test_server_e2e.py` | Repoint the readiness probe, drop the A2A and SSE tests, add a `/run_live` test (below). | | 5 | — | Drop `agents-cli publish gemini-enterprise` from the plan; Gemini Enterprise has no Live transport to register against. |
Steps 3 and 4 are not optional cleanup. Both scaffolded integration tests drive the **non-live** path, and a Live model doesn't degrade to text — it rejects it, so `runner.run()` and `/run_sse` fail outright. Rewrite the tests; don't delete them.
Same shape as the scaffolded test, but driven by `run_live` and asserting on the transcript rather than on text parts:
import asyncio
from google.adk.agents.live_request_queue import LiveRequestQueue
from google.adk.agents.run_config import RunConfig
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
from app.agent import root_agent
APP_NAME = "test"
USER_ID = "test_user"
def test_agent_live_stream() -> None:
"""The agent answers over run_live and returns audio plus a transcript."""
async def _turn() -> tuple[str, int]:
session_service = InMemorySessionService()
# The session must exist before run_live, or it raises "Session not found".
session = await session_service.create_session(
app_name=APP_NAME, user_id=USER_ID
)
runner = Runner(
agent=root_agent, session_service=session_service, app_name=APP_NAME
)
queue = LiveRequestQueue()
queue.send_content(
types.Content(role="user", parts=[types.Part(text="Why is the sky blue?")])
)
transcript, audio_chunks = "", 0
try:
async for event in runner.run_live(
user_id=USER_ID,
session_id=session.id,
live_request_queue=queue,
# Transcription is on by default — see "RunConfig".
run_config=RunConfig(response_modalities=["AUDIO"]),
):
# Consume the finished aggregate; partials would duplicate text.
if (
event.output_transcription
and event.output_transcription.finished
and event.output_transcription.text
):
transcript += event.output_transcription.text
if event.content and event.content.parts:
audio_chunks += sum(
1 for part in event.content.parts if part.inline_data
)
if event.turn_complete:
break
finally:
queue.close()
return transcript, audio_chunks
transcript, audio_chunks = asyncio.run(_turn())
assert transcript.strip(), "Expected a non-empty output transcript"
assert audio_chunks > 0, "Expected the agent to return audio"Three edits, and the first is the one that's easy to miss:
which step 2 deleted — use `f"{BASE_URL}/list-apps"` instead. Miss this and the probe raises `NameError`, which the surrounding `except RequestException` does **not** catch, so every test in the file errors before the server is even contacted. (`/list-apps` is a sound readiness signal: uvicorn serves no request until the lifespan startup completes.)
and add the `/run_live` test below. Those three are the whole file, so the new test replaces them rather than joining them.
`test_reasoning_engine_stream` — `async_stream_query` is the non-live path too.
import asyncio import json import uuid import requests from websockets.asyncio.client import connect APP_NAME = "
The CLI and skills that turn any coding assistant into an expert at creating, evaluating, and deploying AI agents on Google Cloud.
Repo: google/agents-cli
Requires `google.golang.org/adk/v2 >= v2.0.0`, which is where the `workflow` package and `agent/workflowagent` first ship.
Reflects `google.golang.org/adk/v2 v2.1.0`, the version the `adk_go` template pins. If a symbol here is missing, check your `go.mod` before assuming the page…
Requires `google-adk >= 2.0.0`. This page documents the Python graph API; ADK Go has its own — see `references/adk-go-workflows.md`. Requires **Python >=…
* **`Agent`**: The core intelligent unit. Can be `LlmAgent` (LLM-driven) or `BaseAgent` (custom/workflow). * **`Tool`**: Callable function providing external…
Recipes live in [google/adk-samples](https://github.com/google/adk-samples). **`core/python/`** is the curated tier — canonical ADK patterns maintained by the…
**Assumes `/google-agents-cli-scaffold` scaffolding.** If your project isn't scaffolded yet, see `/google-agents-cli-scaffold` first.