aiml
SearchMy learning
Menu

Lesson 18 of 20Module 5

Scaffold and deploy an agent with the Agents CLI

Use an Agents CLI project for an existing ADK agent, inspect deployment defaults, set explicit resource limits, and resume a recorded remote session.

Prerequisites

An ADK agent, uv, the Agents CLI, Google Cloud ADC and an approved Agent Runtime project.

By the end, you can

  • Inspect an Agents CLI manifest and its generated application project.
  • Choose explicit deployment limits and distinguish update metadata from a new create.
  • Resume a recorded remote conversation and interpret CLI validation failures.
Runtime
Python 3.11–3.13, uv, gcloud and the Agents CLI
Dependencies
Google ADK 2.12.0; Agents CLI 1.11.0; the downloaded uv.lock

Lab code, tests and fixtures (ZIP, 193 KB)Quiz check your understanding

Progress is saved in this browser.

The Agents CLI adds application files and deployment configuration around an existing ADK agent. Here the docuctl docs assistant is the agent; the new work is its project manifest, generated serving code and deployment settings. All cloud output below came from the earlier deployment, which has since been deleted.

When you need this. Your team has a working Python agent but needs a repeatable project layout that another developer can run and deploy. Keep the agent’s instruction and tools separate from the CLI’s generated files, and inspect the resource defaults before turning a local prototype into a hosted process.

For the complete scaffold, evaluation and infrastructure workflow, use the Agents CLI course. This lesson keeps its narrower focus on the recorded managed-runtime deployment, resource defaults and stale update-target behavior.

Recorded example. The archived “Scaffold and deploy an agent with the Agents CLI” demonstration retains the earlier shipctl scenario; the current lab uses docuctl and does not claim a new model result.

Recorded remote question and session continuationRecorded output (excerpt) · textFull output
Querying remote agent: https://us-central1-aiplatform.googleapis.com/v1/projects/vertex-ai-experminent/locations/us-central1/reasoningEngines/2774248431663710208 (mode: adk)
[user]: I run shipctl 2.x. How do I roll production back to r41?
[docs_helper]: To roll production back to release `r41` in shipctl 2.x, run:

```bash
shipctl rollback --env production --to r41
```

This points traffic back to `r41` without rebuilding. Note that database migrations are not rolled back automatically.

Session: 7729729093029068800
  Resume with: agents-cli run "<message>" --url "https://us-central1-aiplatform.googleapis.com/v1/projects/vertex-ai-experminent/locations/us-central1/reasoningEngines/2774248431663710208" --mode adk --session-id 7729729093029068800
data flowreturnartifact hand-offfailureagent.pyagents-cliscaffold enhanceagentApp + manifestdocs_helper.agent.appwritesagents-cli deployexplicit limitsconfigurationAgent RuntimeApp + Runnertarget metadata is stalevalidation fails before deploylookup failsAgent RuntimeIDsavedagents-cli run--url--session-idtargetresumedata flowreturnartifact hand-offfailureexisting agent.pyagents-cliscaffold enhanceagentApp + manifestdocs_helper.agent.appwritesagents-cli deployexplicit resource limitsconfigurationAgentRuntimestale IDrefusedcreatelookupsaved Agent Runtime IDmetadataagents-cli run--url--session-idtarget ID
agents-cli scaffold enhance keeps root_agent and writes an App wrapper plus the deployment manifest. The generated serving code constructs a Runner. agents-cli deploy hosts that App on Agent Runtime and saves its resource ID for the target URL; a later agents-cli run supplies that URL and a separate recorded session ID. The saved target lookup failed in a separate run, before deployment.

Lab setup. Download the complete lab ZIP, extract it and open a terminal in adk-agents-cli/. Use the bundled lockfile for this generated project:

Install the project and separate CLI toolTerminal · bash
uv sync --frozen
uv tool install google-agents-cli==1.11.0

Use Python 3.11–3.13 for this project. Local project checks and cloud deployment commands are separated in the bundled README.

1. Inspect the project around the existing agent

The lab includes the generated runtime files, uv.lock and manifest. Generic demo evals and placeholder tests are omitted; the local checks below cover this docs-assistant project. The original scaffold enhance recording shows the CLI finding docs_helper/agent.py, retaining root_agent, and adding an App object. It also created a backup before changing files. This is project generation, rather than a second implementation of the agent.

agents-cli-manifest.yamlSource · yamlDownload
name: "docs-helper"
acli_version: "1.11.0"
agent_directory: "docs_helper"
region: 'us-central1'
base_template: "local_docs-helper"
generated_at: "2026-10-22T01:45:52.584862+00:00"
language: "python"
framework: "google-adk"
create_params:
  # The ADK name of the root agent, as rendered into the agent source. Rename
  # the agent and you must change it in both places: telemetry reports this as
  # gen_ai.agent.name, and it is what agents-cli reports for the project.
  root_agent_name: "docs_helper"
  deployment_target: "agent_runtime"
  session_type: "in_memory"
  cicd_runner: "skip"
  is_a2a: true
  agent_gateway: false
  agent_guidance_filename: "GEMINI.md"
  agent_runtime:
    identity_default: "agent_identity"

agent_directory identifies the Python package, and deployment_target: agent_runtime chooses the deployment adapter. The generated project skipped CI/CD for this exercise. It includes files for later automation, but no CI pipeline was exercised by the recorded run. See the enhance output for the original operation; the project can be examined offline.

2. Inspect defaults before choosing a deployment size

From the extracted lab directory, set GOOGLE_CLOUD_PROJECT to your project and configure Application Default Credentials (ADC). Preview the CLI’s create defaults with --dry-run; this validates Google Cloud access without creating the deployment:

Preview deployment settings with a dry runTerminal · bash
agents-cli deploy --dry-run --project $GOOGLE_CLOUD_PROJECT --region us-central1
Recorded deployment dry runRecorded output (excerpt) · textFull output
cpu: 1
memory: 4Gi
min_instances: 0
max_instances: 10
container_concurrency: 8
(defaults apply on create; existing values preserved on update)

The CLI preserves existing values on an update when flags are absent. That differs from a create, where defaults apply. Read agents-cli deploy --help and the dry-run output for the installed release, then set the CPU, memory, instance bounds and identity choice deliberately. A low maximum limits simultaneous containers; it does not set a spending cap or prove that the application handles that workload.

3. Deploy the generated application

Deploy to Agent Runtime with explicit resource limits:

Deploy with explicit resource limitsTerminal · bash
agents-cli deploy --project $GOOGLE_CLOUD_PROJECT --region us-central1 \
  --cpu 1 --memory 1Gi --min-instances 0 --max-instances 1 --no-agent-identity

The service still runs under a Google Cloud service agent; --no-agent-identity disables Agent Identity without disabling cloud IAM. The deployment output records the settings that were applied:

Parameters and result from the recorded deploymentRecorded output · textDownload
  Project: vertex-ai-experminent
  Location: us-central1
  Display Name: docs-helper
  Min Instances: 0
  Max Instances: 1
  CPU: 1
  Memory: 1Gi
  Container Concurrency: 8
  Agent Identity: Disabled
Agent Runtime ID: projects/PROJECT_NUMBER/locations/us-central1/reasoningEngines/2774248431663710208

Use the project README’s commands only in a project where deployment and its costs are approved. The generated deployment_metadata.json is deliberately absent from the download: shipping a recorded engine ID would make another developer’s CLI target a stale deployment. An example file documents its shape.

Recorded pre-deploy validation failureRecorded output (excerpt) · textFull output
Target engine: Agent Runtime 'projects/PROJECT_NUMBER/locations/us-central1/reasoningEngines/2774248431663710208' not found.
The resource recorded in deployment_metadata.json may have been deleted.
Delete the metadata file to deploy a new engine, or check your permissions.
Error: Pre-deploy validation failed (1 of 3 checks): Target engine.
Fix the items above, then run the deploy.

A downloaded stale deployment target. The download omits live deployment metadata, so it does not point at the deleted recorded instance. Configure your own deployment.

The target-engine lookup failed for the metadata’s resource name. Check the project, region and whether the instance still exists before updating or replacing metadata. Do not delete the file merely to silence the failure: doing so changes the next operation from update to create.

Conflicting preview flags. Use --dry-run without --force; this rejection occurs before cloud checks. In this saved check, the CLI printed an error while exiting zero, so scripts must inspect the result rather than treating every zero exit as a successful preview:

Local CLI validation, no cloud checksRecorded output · textDownload
$ agents-cli scaffold enhance --dry-run --force --skip-checks --auto-approve
Agents CLI v1.11.0
Error: --dry-run is not compatible with --force mode.
exit 0
Offline project and installed-CLI checksRecorded output · textDownload
test_conflicting_preview_flags_report_an_error_even_with_exit_zero (test_project.ScaffoldProject.test_conflicting_preview_flags_report_an_error_even_with_exit_zero) ... ok
test_documented_limits_and_identity_flags_exist (test_project.ScaffoldProject.test_documented_limits_and_identity_flags_exist) ... ok
test_download_does_not_target_the_recorded_deleted_deployment (test_project.ScaffoldProject.test_download_does_not_target_the_recorded_deleted_deployment) ... ok
test_manifest_selects_agent_runtime_and_the_existing_agent (test_project.ScaffoldProject.test_manifest_selects_agent_runtime_and_the_existing_agent) ... ok

----------------------------------------------------------------------
Ran 4 tests in 5.417s

OK

The local checks inspect files and CLI help; they do not redeploy or grade model answers. The recorded instance was deleted after the exercise. For your own instance, complete its deployment-specific cleanup before discarding the metadata that identifies it.

4. Resume the remote session from the CLI

The first saved agents-cli run asked how to return production to a named release. The CLI printed a session ID and a continuation command. The next run reused that ID for “And on staging?”, and the answer retained the release and version from the conversation.

Recorded continuation with the same session IDRecorded output · textDownload
Querying remote agent: https://us-central1-aiplatform.googleapis.com/v1/projects/vertex-ai-experminent/locations/us-central1/reasoningEngines/2774248431663710208 (mode: adk)
[user]: And on staging?
[docs_helper]: To roll staging back to `r41` in shipctl 2.x, change the `--env` flag:

```bash
shipctl rollback --env staging --to r41
```

Session: 7729729093029068800
  Resume with: agents-cli run "<message>" --url "https://us-central1-aiplatform.googleapis.com/v1/projects/vertex-ai-experminent/locations/us-central1/reasoningEngines/2774248431663710208" --mode adk --session-id 7729729093029068800

This checks one conversation path. It is not an evaluation of the agent’s general command accuracy. Keep the session ID with the authenticated user in the caller; a string typed into a CLI is not itself an authorization credential.

What’s next

Deploy an ADK agent to Agent Runtime uses ADK’s native deployment command and calls the runtime methods directly.

Read the unchanged docs assistant
docs_helper/agent.pySource · pythonDownload
"""The docs assistant on Gemini Enterprise Agent Platform: Gemini through Vertex, recall through Memory Bank."""
import os
from pathlib import Path

from google.adk import Agent
from google.adk.models.google_llm import Gemini
from google.adk.tools import load_memory
from google.genai import types

DOCS = Path(__file__).resolve().parent / "docs"
PAGES = sorted(p.stem for p in DOCS.glob("*.md"))
# The recorded run uses global for this model. Sessions and Memory Bank stay regional
# (GOOGLE_CLOUD_LOCATION), so the model client gets its own location.
MODEL_LOCATION = os.environ.get("DOCS_MODEL_LOCATION", "global")


def read_page(page: str) -> dict:
    """Read one page of the docuctl documentation: config, deploy, rollback or tokens."""
    if page not in PAGES:
        return {"error": f"No page {page!r}. Pages: {', '.join(PAGES)}."}
    return {"page": page, "text": (DOCS / f"{page}.md").read_text(encoding="utf-8")}


INSTRUCTION = """You answer questions from developers about docuctl, the team's deploy CLI.
Read the relevant page with read_page before you answer. Answers depend on the developer's
docuctl major version (1.x or 2.x). If the developer has not said it in this conversation,
call load_memory to look for it in earlier conversations before you ask. Keep the answer
under 80 words."""

root_agent = Agent(
    name="docs_helper",
    model=Gemini(model="gemini-3.8-flash", client_kwargs={"location": MODEL_LOCATION}),
    instruction=INSTRUCTION,
    tools=[read_page, load_memory],
    generate_content_config=types.GenerateContentConfig(
        temperature=0.2, thinking_config=types.ThinkingConfig(thinking_level="low")),
)

from google.adk.apps import App

app = App(root_agent=root_agent, name="docs_helper")

Check your understanding

A downloaded project omits deployment_metadata.json. Why should you inspect a stale target before removing local metadata?

Choose one answer, then check your reasoning.

Read the explanation

The target metadata selects an existing deployment. Removing it changes the operation; it does not repair the old resource lookup.

References

Official documentation, installed Agents CLI help/source and ADK APIs checked October 22, 2026.

Written by Arjun Prabhulal.

Module 5

Deploy agents on Google Cloud