Agent Engine (Gemini Enterprise Agent Platform)

The agent-engine feature makes an ADK-Rust agent drivable by the Gemini Enterprise Agent Platform as a custom-container ReasoningEngine. A container running serve_agent_engine answers reasoningEngines.query, reasoningEngines.streamQuery, the console Playground, and the platform SDKs — the same runtime contract adk-python's AdkApp implements.

Overview

The platform drives a deployed engine through two container endpoints:

EndpointModeResponse
POST /api/reasoning_engineunary{"output": ...}
POST /api/stream_reasoning_enginestreamingone JSON object per line (Content-Type: application/json, no SSE framing)

Both take the dispatch envelope {"class_method": "...", "input": {...}}. The envelope is snake_case — the platform dispatches on Python method names. The turnkey app also serves GET /health for container health checks.

Quick start

Enable the feature (it is included in the gemini-agent-platform meta-feature):

[dependencies]
adk-rust = { version = "2.1.0", features = ["minimal", "agent-engine"] }

For an agent that uses the full platform — managed sessions, Memory Bank, Example Store, the code-execution sandbox, RAG, evaluation, and the Agent and Skill Registries — one feature brings every integration:

[dependencies]
adk-rust = { version = "2.1.0", features = ["minimal", "gemini-agent-platform"] }

serve_agent_engine is the whole main of a deployable engine. It binds 0.0.0.0:$PORT (fallback 8080) and serves until stopped:

use adk_rust::prelude::*;
use adk_server::agent_engine::{AgentEngineOptions, serve_agent_engine};
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<()> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-3.7-flash")?);

    let agent = LlmAgentBuilder::new("weather_agent")
        .description("Answers weather questions")
        .instruction("You are a helpful weather assistant.")
        .model(model)
        .build()?;

    serve_agent_engine(Arc::new(agent), AgentEngineOptions::new()).await
}

Verify with the codelab's payload:

curl -s -X POST localhost:8080/api/stream_reasoning_engine \
  -H 'Content-Type: application/json' \
  -d '{"class_method": "async_stream_query", "input": {"user_id": "u", "message": "hi"}}'

Each response line is one ADK event as JSON.

Operations

The engine registers the exact operation set adk-python's AdkApp advertises. Sync/async name pairs map to the same handler — the split is a Python artifact the wire contract preserves.

class_methodAPI modeBehavior
create_session, async_create_session"" / asyncCreate a session (optional caller-chosen ID and initial state)
get_session, async_get_session"" / asyncFetch a session with its events
list_sessions, async_list_sessions"" / asyncList a user's sessions
delete_session, async_delete_session"" / asyncDelete a session
stream_query, async_stream_querystream / async_streamRun the agent; the session is created automatically when absent
streaming_agent_run_with_eventsasync_streamRun the agent from an AgentRunRequest JSON string (console Playground path)
async_add_session_to_memoryasyncExtract a session's events into the configured memory service
async_search_memoryasyncSearch the configured memory service
register_operations""Advertise this table to the host

Unknown class methods return 400 with a problem-JSON body. The memory methods return an Unsupported error (501) until a memory service is configured.

Note: reasoningEngines:asyncQuery (durable query jobs) is not registered: the capability must be declared at engine create time, cannot be added post-create, and adk-python's AdkApp does not register it either.

Managed backends

The zero-configuration default keeps sessions in memory — enough to answer queries, but conversations do not survive a container restart. Deployed engines configure managed backends through AgentEngineOptions.

Managed sessions (Vertex AI Sessions)

With the vertex-session feature, VertexAiSessionConfig::from_env() reads the variables the platform sets inside deployed containers (GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION, and GOOGLE_CLOUD_AGENT_ENGINE_ID — the bare numeric engine ID):

use adk_server::agent_engine::AgentEngineOptions;
use adk_session::{VertexAiSessionConfig, VertexAiSessionService};
use std::sync::Arc;

fn managed_sessions() -> adk_core::Result<AgentEngineOptions> {
    let config = VertexAiSessionConfig::from_env()?;
    let sessions = Arc::new(VertexAiSessionService::new_with_adc(config)?);
    Ok(AgentEngineOptions::new().with_session_service(sessions))
}

Outside a deployed container, construct the config explicitly with VertexAiSessionConfig::new(project, location).with_reasoning_engine(id).

Artifacts (Google Cloud Storage)

With the gcs-artifacts feature, GcsArtifactService stores artifacts in the blob layout the Gemini Enterprise console reads (byte-for-byte parity with adk-python). Take the bucket from an environment variable or a flag:

use adk_artifact::GcsArtifactService;
use adk_server::agent_engine::AgentEngineOptions;
use std::sync::Arc;

fn gcs_artifacts() -> adk_core::Result<AgentEngineOptions> {
    let bucket = std::env::var("ADK_ARTIFACT_BUCKET").unwrap_or_else(|_| "my-bucket".to_string());
    let artifacts = Arc::new(GcsArtifactService::new_with_adc(bucket)?);
    Ok(AgentEngineOptions::new().with_artifact_service(artifacts))
}

The artifact service is wired into both the runner (tool-facing saves and loads) and the dispatch state.

Memory

AgentEngineOptions::with_memory_service accepts any adk_memory::MemoryService and enables the two memory class methods. The platform's Memory Bank backend arrives with the vertex-memory feature in a later release.

ServerBuilder integration

An existing ADK server can expose the dispatch surface alongside its REST, UI, and A2A routes:

use adk_server::{ServerBuilder, ServerConfig};

fn build_app(config: ServerConfig) -> axum::Router {
    ServerBuilder::new(config).with_agent_engine(true).build()
}

The dispatch routes serve the loader's root agent with the configured session and artifact services. They do not carry the server's auth middleware: a deployed engine is fronted by the platform, which authenticates callers before they reach the container. Do not expose these endpoints directly to untrusted networks.

Deploying from the CLI

With adk-cli installed with the gcp-deploy feature (cargo install adk-cli --features gcp-deploy), one command creates the engine from a pushed container image:

# 1. Build and push the image
gcloud builds submit --tag us-central1-docker.pkg.dev/PROJECT/agents/my-agent:latest

# 2. Deploy it as a ReasoningEngine
adk-rust deploy agent-engine \
  --image-uri us-central1-docker.pkg.dev/PROJECT/agents/my-agent:latest \
  --project PROJECT \
  --location us-central1 \
  --service-account agent-runner@PROJECT.iam.gserviceaccount.com

Optional flags: --display-name (defaults to the image name) and --kms-key for CMEK. The command declares the full class-method contract from the operations table, waits for the create operation, and prints the engine resource name. The same client is available programmatically as adk_deploy::gcp::GcpDeployClient (umbrella feature gcp-deploy).

Environment variables

VariableMeaning
PORTServing port assigned by the platform (fallback 8080; an invalid value fails startup)
GOOGLE_CLOUD_PROJECTGCP project of the deployment
GOOGLE_CLOUD_LOCATIONGCP location of the deployment
GOOGLE_CLOUD_AGENT_ENGINE_IDBare numeric engine ID, set inside deployed containers

When GOOGLE_CLOUD_AGENT_ENGINE_ID is present and the session service is the in-memory default, the entrypoint logs a warning: deployed engines should use managed sessions.