First-party frameworks
A framework ships as a template you scaffold from, not as an extension you install. The template carries its own agents-cli-extension.yaml, so the project gets the framework's command overrides with nothing installed machine-wide.
| Framework | What it does |
|---|---|
| LangChain | Run a LangChain agent through the agents-cli lifecycle. |
| Claude Agent SDK | Run a Claude Agent SDK agent, on Claude on Gemini platform, through the agents-cli lifecycle. |
LangChain#
The LangChain template runs a LangChain agent through the agents-cli lifecycle. It overrides only the framework-coupled commands and leaves everything else, such as deploy, infra, and eval grade, running natively.
Experimental: deploy to Cloud Run or GKE
On Agent Runtime in Gemini platform, the container serves and traces normally, but the integrations that
expect an ADK app do not work, because this project serves A2A and no reasoning_engine
routes. The publish gemini command is refused (registration invokes :streamQuery), the
Console playground cannot invoke the agent, and the Console's session and trace views stay
empty. Traces still reach Cloud Trace.
Create a project#
agents-cli create my-agent \
--agent google/agents-cli/extensions/langchain/template@v1.13.0 \
-d cloud_run
cd my-agent && agents-cli install
The scaffolded project contains agents-cli-extension.yaml at its root. That file is auto-loaded at project scope, so the overrides below are active in this project and nowhere else. Commit it.
What it overrides#
| Command | Behavior in a LangChain project |
|---|---|
playground | uv run langgraph dev, the local LangGraph dev server (also serves A2A). |
publish gemini | Runs the built-in, except on Agent Runtime, where it refuses with the reason. |
run | Invokes the compiled graph in-process. |
eval generate | Produces the standard EvaluationDataset shape, so eval grade is unchanged. |
eval dataset (including synthesize), eval optimize | Refused with an explanation, because both introspect an ADK agent object to build their dataset. |
Everything else stays native: deploy (the target-appropriate native deploy, for example gcloud run deploy --source . on Cloud Run), eval grade / compare / analyze (framework-agnostic), and infra.
The scaffolded agent#
The default app/agent.py is a Gemini ReAct agent built with langchain.agents.create_agent and a sample get_weather tool. It calls Gemini on Gemini platform using Application Default Credentials; set GOOGLE_API_KEY or GEMINI_API_KEY in .env to use AI Studio instead (the scaffolded .env.example names the latter).
The agent is named after the project (my-agent becomes my_agent), or after --root-agent-name if you pass it. Telemetry reports that name as gen_ai.agent.name, and the manifest records it as create_params.root_agent_name. To rename the agent, change it in app/agent.py and in the manifest.
Because the project is built on the framework-neutral empty_py base, the generated code contains no ADK dependency, and the template ships its own coding-agent skill.
Serve over A2A#
The deployed agent serves the Agent2Agent (A2A) protocol, the same protocol the rest of the toolchain expects, so it works unchanged:
- Entrypoint:
uvicorn app.fast_api_app:app(the scaffold DockerfileCMD). - Endpoints: JSON-RPC at
POST /a2a/app; Agent Card at/a2a/app/.well-known/agent-card.json. - Streaming: the executor streams LLM token chunks as incremental A2A task artifacts (
capabilities.streaming=True), so a real chat model streams token-by-token. Graphs whose nodes don't stream tokens fall back to a single final artifact.
Query a deployed (or locally served) agent over A2A. Because the project overrides run with in-process graph invocation, set AGENTS_CLI_DISABLE_OVERRIDES=1 to reach the built-in A2A client:
AGENTS_CLI_DISABLE_OVERRIDES=1 agents-cli run --url https://<service-url> --mode a2a --app-name app "hello"
Full journey#
agents-cli create my-agent --agent google/agents-cli/extensions/langchain/template@v1.13.0 -d cloud_run
cd my-agent && agents-cli install
agents-cli run "what's the weather in San Francisco?" # in-process graph
agents-cli eval generate --dataset tests/eval/datasets/basic-dataset.json -o tests/eval/output/
agents-cli eval grade --traces tests/eval/output/ --config tests/eval/eval_config.yaml
agents-cli deploy --project <project-id> # native Cloud Run deploy
Notes#
- Credentials:
runandevalcall Gemini, so they needGOOGLE_CLOUD_PROJECTplus ADC, orGOOGLE_API_KEY/GEMINI_API_KEYfor AI Studio. - Run the built-in instead of an override: prefix with
AGENTS_CLI_DISABLE_OVERRIDES=1(for example,AGENTS_CLI_DISABLE_OVERRIDES=1 agents-cli run "hi"). - Deploy contract:
app/fast_api_app.pymust keep exposingapp. If you restructure the agent, keep that import working. - Compatibility: the template's manifest declares no
requiresrange, so its overrides apply on any CLI version. See Authoring → Compatibility for declaring one in your own.
Claude Agent SDK#
The Claude template runs a Claude Agent SDK (Python) agent through the agents-cli lifecycle, with the model served by Claude on Gemini platform. Like the LangChain template, it overrides only the framework-coupled commands.
Experimental: deploy to Agent Runtime or Cloud Run
The template supports agent_runtime and cloud_run. The model named in
app/agent.py (default claude-haiku-4-5) must be enabled for the project in Model
Garden.
On Agent Runtime the container serves A2A and traces normally. It also serves Agent
Runtime's :query and :streamQuery methods, so agents-cli run --mode adk works and
an ingress Agent Gateway can govern the agent. The publish gemini command is refused, the Console
playground cannot invoke the agent, and the Console's session and trace views stay
empty. Traces still reach Cloud Trace. Agent Runtime's managed sessions are ADK-only
and Cloud SQL isn't set up there automatically, so transcripts stay on the instance
unless you set it up by hand (see Notes).
Scaffold an existing agent#
The template's contract is app/agent.py exporting root_agent, a ClaudeAgentOptions. The template ships a step-by-step migration guide for your coding agent, at .agents/skills/agents-cli-claude/references/migrate-claude-agent.md in the scaffolded project. By hand:
cd my-claude-agent
agents-cli scaffold enhance google/agents-cli/extensions/claude/template@v1.13.0 -d cloud_run
The enhance command writes the template as create would: the server, a sample app/agent.py, pyproject.toml, Dockerfile, deployment files, tests and agents-cli-extension.yaml. Each of your files it replaces moves to .agents-cli-original/ at the same path; your other files stay where they are. Then port your agent into app/agent.py, add your dependencies with uv add, carry over what you need from .agents-cli-original/ and delete it. To start from scratch instead:
agents-cli create my-agent --agent google/agents-cli/extensions/claude/template@v1.13.0 -d cloud_run
What it overrides#
| Command | Behavior in a Claude project |
|---|---|
run | Runs root_agent in process through the SDK. |
eval generate | Produces the standard EvaluationDataset shape, with tool calls as function_call / function_response parts, so eval grade is unchanged. |
playground | Refused with an explanation: the SDK has no local dev UI. |
eval dataset synthesize, eval optimize | Refused with an explanation: both drive the agent through ADK. |
publish gemini | Runs the built-in, which registers over A2A, except on Agent Runtime, where it refuses with the reason. |
The deploy and infra commands and the eval grade, eval compare and eval analyze subcommands stay native.
How the agent runs#
The app/app_utils/claude.py file runs each turn with the SDK's query(), which starts the Claude Code CLI bundled in the claude-agent-sdk wheel; no Node.js is needed in the image for the agent itself. It points the CLI at Gemini platform (CLAUDE_CODE_USE_VERTEX=1, CLOUD_ML_REGION defaulting to global, and the project from GOOGLE_CLOUD_PROJECT or ADC). The Anthropic API is not supported.
Each conversation runs in its own working directory, so the agent never sees the app source and concurrent conversations don't share files. The agent's own CLAUDE.md, .claude/ (settings, output styles, skills, subagents, hooks) and .mcp.json live in agent_config/; they are copied into that directory and loaded as project settings. The same files at the project root belong to your coding assistant: the served agent never reads them. Python hooks and can_use_tool callbacks in root_agent work unchanged.
Give a served agent an explicit tool list: tools=[] disables Claude Code's built-in tools (Bash, Read, Write, ...), and allowed_tools names the tools it may call, such as mcp__weather__get_weather for a @tool served by create_sdk_mcp_server (the middle part is the mcp_servers key). An agent with subagents (agents= or agent_config/.claude/agents/) also needs "Agent" in both lists. stdio MCP servers started with npx need Node.js: uncomment the Node line in the scaffolded Dockerfile.
The agent is named after the project (my-agent becomes my_agent), or after --root-agent-name if you pass it. The scaffold writes that name to AGENT_NAME in app/app_utils/settings.py, and spans (gen_ai.agent.name), BigQuery Agent Analytics rows and eval traces all report it. It isn't in app/agent.py as in the LangChain template, because in a migrated project app/agent.py is your file, and ClaudeAgentOptions has no name field. To rename the agent, change AGENT_NAME and create_params.root_agent_name in the manifest.
Migrate an existing agent#
- Run
agents-cli scaffold enhance <template> -d cloud_run. The files the template replaces, such aspyproject.toml,README.mdand.env, move to.agents-cli-original/. - Expose the agent as
root_agent = ClaudeAgentOptions(...)inapp/agent.py, typically by moving the options a script builds inmain()there and importing its tools. Add your dependencies withuv add, keeping the template'sclaude-agent-sdkrange, carry over what you need from.agents-cli-original/, and delete it. - Pin the model, and map subagent aliases (
model: sonnet) to models enabled in your project withenv={"ANTHROPIC_DEFAULT_SONNET_MODEL": "..."}. agents-cli install,agents-cli run, write eval cases,agents-cli deploy.
Serve the agent over A2A#
The server is the same A2A surface as the LangChain template: JSON-RPC at POST /a2a/app, Agent Card at /a2a/app/.well-known/agent-card.json, /health. Text streams as it is generated. Each A2A conversation maps to one Claude session. Scaffold with --session-type cloud_sql to store sessions in a Cloud SQL Postgres database (provisioned by agents-cli infra single-project), so a conversation resumes on any instance and survives restarts; the default, in_memory, keeps them on the instance. To let the agent call other A2A agents, add remote_agent("<name>", "<url>") from app/app_utils/remote_agents.py to root_agent.mcp_servers. For a Cloud Run callee it sends an ID token (the caller needs roles/run.invoker on it); for an Agent Runtime callee, given its passthrough URL (https://<location>-aiplatform.googleapis.com/reasoningEngines/v1/projects/<project>/locations/<location>/reasoningEngines/<id>/api/a2a/app), it sends an OAuth access token (the caller needs roles/aiplatform.user). The run override hands calls with --url or --mode to the built-in A2A client:
agents-cli run --url https://<service-url> --mode a2a --app-name app "hello"
# Agent Runtime: the engine's resource URL
agents-cli run --url https://<location>-aiplatform.googleapis.com/v1/projects/<project>/locations/<location>/reasoningEngines/<id> --mode a2a "hello"
Full journey#
cd my-claude-agent
agents-cli scaffold enhance google/agents-cli/extensions/claude/template@v1.13.0 -d cloud_run
agents-cli install
agents-cli run "what's the weather in San Francisco?" # in-process
agents-cli eval generate --dataset tests/eval/datasets/basic-dataset.json -o tests/eval/output/
agents-cli eval grade --traces tests/eval/output/<dataset>.json --config tests/eval/eval_config.yaml
agents-cli deploy # native Cloud Run deploy
Notes#
- Credentials:
runandevalcall Claude on Gemini platform, so they need ADC and a project with the model enabled. The deployed agent needsroles/aiplatform.user. New projects, on Cloud Run and Agent Runtime, run the agent with Agent Identity, anddeploygrants it. A Cloud Run project created with--cloud-run-identity-default service_account(or before Agent Identity became the default) deploys either as the service account passed via--service-account, or as the default compute account, so runagents-cli infra single-project --applyand deploy with--service-account <name>-app@<project>.iam.gserviceaccount.com..envsetsGOOGLE_CLOUD_PROJECT, andagents-cli deployforwards it to the service (Agent Runtime sets it itself). - Sessions: with the default
in_memorysession type, transcripts live on the instance, so a conversation that reaches another instance, or outlives a restart, starts fresh.--session-type cloud_sqlkeeps them in Cloud SQL on Cloud Run. On Agent Runtime,--session-typedoesn't apply: Cloud SQL works there with manual network and database setup (see the project's.agents/skills/agents-cli-claude/references/claude.md). Without it, the default shape scales to zero (--min-instances 0), so an idle conversation is lost; deploy with--min-instances 1to keep a single instance warm. - Sizing: a tool-using turn takes about 270 MiB, so the default shape (4 GiB, concurrency 8) fits; file-heavy agents need more memory per concurrent session.
- Telemetry: the OpenInference Claude Agent SDK instrumentor records an
invoke_agentspan per turn (model, token usage, cost) and anexecute_toolspan per tool call in Cloud Trace, withgen_ai.*attributes. The Claude Code CLI's own spans (each model request, each tool step) are relayed to Cloud Trace through a localhost forwarder and nest under the turn span in the same trace. Message content and tool arguments are redacted unlessOTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTenables capture. As with ADK agents, every request starts its own trace, so a call to another agent throughremote_agentshows up as two traces, the caller's and the callee's;gen_ai.conversation.idlinks each side's turns. Python log records go to Cloud Logging (theadk-otellog, orreasoning_engine_stdouton Agent Runtime, as with ADK agents) with their severity and the turn's trace, and ADK's agent metrics (gen_ai.invoke_agent.duration,gen_ai.execute_tool.duration,gen_ai.invoke_agent.inference_calls,gen_ai.invoke_agent.tool_calls) plusgen_ai.client.token.usagego to Cloud Monitoring. With--bq-analytics, each turn's events also go to BigQuery Agent Analytics: theagent_eventstable and views ADK's plugin writes, so its SDK and dashboards work for Claude agents too.
Last updated