Ver en Español
From development to production: streaming, memory, evaluation, deployment, security, and observability
Jun 24, 2026
Updated: Jun 25, 2026

From development to production: streaming, memory, evaluation, deployment, security, and observability

Lesson notebook: Lesson_6.ipynb

In this lesson we close the loop: we take your (multi)agent system from your local environment to production. We lean on the course transcript and check each pillar against the local ADK documentation, so you get a concrete, safe path.

Here is the big picture we'll walk through together:

  • Live bidirectional streaming (voice and video) with Runner.run_live() and event queues.
  • Persistent memory with Vertex AI Memory Bank (--memory_service_uri).
  • Agent evaluation: trajectories and final responses (adk eval, evaluators).
  • Deployment: Vertex AI Agent Engine and alternatives (Cloud Run, GKE).
  • Security and guardrails: authentication, callbacks and plugins, Model Armor, PII redaction, sandboxed code.
  • Observability: logging, metrics, and Cloud Trace with OpenTelemetry.

6.1 Live bidirectional streaming

ADK separates the agent logic from the live transport through two primitives (docs: get-started/streaming/ and streaming/custom-streaming*.md):

  • live_request_queue: sends input to the agent (text, real time audio, activity signals).
  • live_events: stream of agent events (responses, turns, interruptions, tool outputs).

Let's look at the basic pattern (excerpt; see the examples in adk-docs/examples/python/snippets/streaming/adk-streaming):

from google.adk.runners import InMemoryRunner
from google.adk.agents import LiveRequestQueue
from google.adk.agents.run_config import RunConfig
from google.genai import types

# 1) Runner and session
runner = InMemoryRunner(app_name="My Streaming App", agent=root_agent)
session = await runner.session_service.create_session(
    app_name=runner.app_name, user_id="user123"
)

# 2) Configure the response modality (AUDIO or TEXT)
run_config = RunConfig(
    response_modalities=["AUDIO"],
    session_resumption=types.SessionResumptionConfig(),
)

# 3) Live wiring
live_request_queue = LiveRequestQueue()
live_events = runner.run_live(
    session=session,
    live_request_queue=live_request_queue,
    run_config=run_config,
)

# 4) Client to agent
live_request_queue.send_content(
    content=types.Content(role="user", parts=[types.Part(text="Hola")])
)
# For PCM audio:
# live_request_queue.send_realtime(
#     types.Blob(data=pcm_bytes, mime_type="audio/pcm;rate=16000")
# )

# 5) Agent to client (SSE/WS)
async for event in live_events:
    if event.turn_complete or event.interrupted:
        # signal turn or state change
        ...
    elif event.content and event.content.parts:
        part = event.content.parts[0]
        if getattr(part, "inline_data", None) and part.inline_data.mime_type.startswith("audio/pcm"):
            # send audio (base64) to the client
            ...
        elif getattr(part, "text", None):
            # send incremental or final text to the client
            ...

The import from google.adk.agents import LiveRequestQueue should be confirmed against the installed google-adk version. In some versions the class is exposed via google.adk.agents.live_request_queue. Verify the exact path and pin the package version these snippets target.

Models: for voice and video streaming use a model with Gemini Live API support (docs: get-started/streaming/quickstart-streaming.md). A reasonable starting point today is gemini-2.0-flash-live-preview, but keep the note below in mind.

Live model names rotate often. Confirm the recommended Live model ID in the official documentation before pinning it in production; do not take it from this post as final.

ADK Web already uses WebSockets and hides much of the complexity. In production, integrate your own client (FastAPI with WebSocket or SSE) and orchestrate live_request_queue and live_events by hand.

6.2 Persistent memory with Vertex AI Memory Bank

Connect long term memory for cross session personalization (docs: sessions/memory.md).

To start the ADK server with managed memory from the CLI, pass --memory_service_uri:

adk web \
  --memory_service_uri="agentengine://<AGENT_ENGINE_ID>" \
  path/to/your/agent

Or configure VertexAiMemoryBankService via the SDK if you build your own runner.

The key difference is this: session.state is volatile and short lived, whereas Memory Bank is persistent, with LLM based extraction and summarization plus semantic search.

Vertex AI Memory Bank was in a preview to GA transition in late 2025. Confirm its GA status as of June 2026 and that the agentengine:// URI scheme is still in place unchanged.

6.3 Evaluate your agent: quality over exactness

Agent evaluation targets quality and trajectory, not just a deterministic "pass/fail" (docs: evaluate/index.md).

What to evaluate?

  • Trajectory and tool usage (order, precision, recall, exact match, single tool checks).
  • Final response (match against a reference; for example, ROUGE).

Ways to evaluate:

  • The UI in ADK Web (captures sessions and converts them into an evalset).
  • Programmatically with AgentEvaluator (Python) or with pytest.
  • CLI: adk eval over one or more evalsets.

Let's look at the CLI example (a full evalset and specific evals):

# Full evalset
adk eval \
  path/to/agent \
  path/to/my_evalset.evalset.json

# Only specific evals (comma separated)
adk eval \
  path/to/agent \
  path/to/my_evalset.evalset.json:eval_1,eval_2

Historically adk eval ran locally and did not always require --project or --region. Re run adk eval --help against your current CLI version and correct the flag set (the example above uses the local form, without project or region).

6.4 Deploying at scale

We have three main paths (docs: deploy/agent-engine.md, deploy/cloud-run.md, deploy/gke.md):

Vertex AI Agent Engine. Tight integration with ADK; it manages sessions, scaling, security, and memory. It's the recommended option to start with:

adk deploy agent_engine \
  --project="$GOOGLE_CLOUD_PROJECT" \
  --region="$GOOGLE_CLOUD_LOCATION" \
  --staging_bucket="gs://<YOUR_STAGING_BUCKET>" \
  --trace_to_cloud \
  path/to/your/agent

Cloud Run. Containerizes your agent service and deploys it serverless:

adk deploy cloud_run \
  --project="$GOOGLE_CLOUD_PROJECT" \
  --region="$GOOGLE_CLOUD_LOCATION" \
  --service_name="my-agent-service" \
  path/to/your/agent

GKE. Full control with Kubernetes; use adk deploy gke or your own manifests.

A few tips:

  • Use --trace_to_cloud to send traces to Cloud Trace on managed deployments.
  • If you use managed persistent memory, pass --agent_engine_id or --memory_service_uri as appropriate.

Confirm the adk deploy subcommand names (agent_engine, cloud_run, gke) and the exact flags against adk deploy --help in your installed version before automating them in CI/CD.

6.5 Security and guardrails

Security is defense in depth (docs: safety/index.md).

Authentication and authorization.

  • Agent auth (service accounts) when everyone shares privileges.
  • User auth (OAuth) for per user permissions; record action attribution.

Guardrails with callbacks and plugins.

  • Per agent, per tool, or per model callbacks to filter and transform inputs and outputs.
  • Global plugins (recommended in production) with precedence and early return if they return a value.
  • Plugin examples from the docs: "Gemini as a Judge", "Model Armor", "PII Redaction".

Content filtering and sanitization.

  • A combination of the model's native filters (Gemini Safety) plus your own policies.
  • Sanitize inputs to mitigate prompt injection (both indirect and direct).

Sandboxed code execution.

  • Use safe executors (for example, Built in Code Execution, GKE Code Executor with gVisor) or Vertex Code Interpreter.

Network and perimeters.

  • VPC SC, least privilege, no open networks on code executors.

Tip: For reusable policies, define Plugins and tune them with metrics and telemetry. Remember that plugins run before agent level callbacks and can stop the chain if they return anything other than None.

6.6 Observability and traceability

Let's monitor, debug, and optimize with logging and OpenTelemetry (docs: observability/logging.md, observability/cloud-trace.md).

Logging.

  • Control verbosity from the CLI: --log_level DEBUG|INFO|... on adk web, adk api_server, and adk deploy *.
  • In development, enable DEBUG and review prompts and tool calls.

Cloud Trace (GCP).

  • On managed deployments, add --trace_to_cloud.
  • Or integrate OpenTelemetry exporters (Cloud Trace Span Exporter) in custom runtimes.

Third party integrations.

  • Weave (W&B), Arize AX, Phoenix, and AgentOps, supported and documented.

6.7 Production checklist

  • Models: chosen by latency and capabilities (Live API for voice and video).
  • Memory: --memory_service_uri=agentengine://<id> if applicable.
  • Guardrails: Plugins plus callbacks; documented policies; I/O sanitization; PII redaction.
  • Evaluation: evalsets, clear criteria and thresholds; adk eval in CI/CD.
  • Observability: --log_level, --trace_to_cloud, OTel exporters, configured dashboards.
  • Deployment: Agent Engine (recommended) or Cloud Run/GKE with network security.

Suggested exercises

  1. Take one of the agents from the earlier lessons and make it talk live: wire live_request_queue and live_events to your own WebSocket or SSE client, first in TEXT modality and then in AUDIO.
  2. Connect Vertex AI Memory Bank by starting adk web with --memory_service_uri and check that the agent remembers data across separate sessions.
  3. Create a small evalset, run it with adk eval, and define a minimum quality threshold; then integrate that command into a CI/CD step.
  4. Deploy your agent to Cloud Run or Agent Engine with --trace_to_cloud and review the resulting traces in Cloud Trace.

3-point summary

  1. Live streaming in ADK is built on two primitives, live_request_queue and live_events, that separate the agent logic from the transport; in production you orchestrate the client yourself.
  2. The path to production combines persistent memory (Memory Bank), evaluation with adk eval, managed deployment (Agent Engine, Cloud Run, or GKE), and defense in depth guardrails.
  3. Observability with logging and OpenTelemetry, plus a clear checklist, is what makes all of the above sustainable once the agent is live.

Resources

The deep ADK documentation paths (for example quickstart-streaming/) and the DeepLearning.AI course URL may have changed or redirected. It's worth checking them before publishing.

Previous lesson: Structured responses with schemas and validation

Next: Series conclusion

With this we close the journey from development to production. I hope this lesson is useful to you and that you can apply it to the agent you have in mind. Leave me a comment if it helped or if you have any questions, and if you liked it, share it using the social links below. See you in the series conclusion.

This content is based on the course "Building Live Voice Agents with Google's ADK!" by DeepLearning.AI (course link). This blog aims to bring ADK material to Spanish speakers.

Sebastián Gómez

Sebastian Gomez

Sebastian Gomez

Creador de contenido principalmente acerca de tecnología.

Leave a Reply

0 Comments

Advertisements

Related Posts

Categorias