---
title: "Google ADK agents in Python (2026): session service, tool confirmation, resumability, OpenAPIToolset and Agent Engine deployment — Cadenya"
url: "https://cadenya.com/other-content/google-adk-agents-in-python"
description: "Google ADK Python in 2026: DatabaseSessionService vs VertexAiSessionService, tool confirmation and LongRunningFunctionTool for human-in-the-loop, ResumabilityConfig, OpenAPIToolset, LiteLLM with Claude, EventsCompactionConfig, and deploying to Agent Engine or Cloud Run, and Cadenya, where conversation state, approvals and tools from your spec need nothing to deploy."
---

A Google ADK agent in Python needs three decisions before it ships: a session service, tool confirmation for the human-in-the-loop steps, and a place to deploy it. The Google ADK docs give you `DatabaseSessionService` or `VertexAiSessionService` for sessions, `require_confirmation` for approvals, and `adk deploy agent_engine` or `adk deploy cloud_run` for deployment.

So pick Agent Engine (Google’s docs call the service Agent Runtime) when you want Google to build the container and store the sessions. Pick Cloud Run when you want your own SQL session database. Pick the Temporal plugin when you already run Temporal. And if you’d rather host none of it, Cadenya is a hosted agent loop with conversation state, approvals and model choice built in. [What it offers](#what-does-cadenya-offer-that-google-adk-on-agent-engine-or-cloud-run-doesnt) is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 13, 2026.

## Google ADK Python on Agent Engine, Cloud Run, or Temporal

ADK itself is a Python library (`google-adk` 2.11.0, Apache 2.0, Python 3.10 or later). Where it runs is your call:

|  | Agent Engine (Agent Runtime) | Cloud Run | Your own container | Temporal plugin |
| --- | --- | --- | --- | --- |
| How you deploy | adk deploy agent_engine packages your code and builds the container | adk deploy cloud_run, or gcloud run deploy | A Dockerfile and a FastAPI app from get_fast_api_app() | A Worker you run, with GoogleAdkPlugin on the Client and the Worker |
| Where sessions live | Agent Runtime Sessions, through VertexAiSessionService | In memory unless you set --session_service_uri | The session_service_uri you pass | Inside the Workflow, “without managing sessions, a database, or your own retry logic” |
| Tool confirmation with stored sessions | VertexAiSessionService is listed as not supported | Works in memory. DatabaseSessionService is listed as not supported | Same as Cloud Run | Not covered in the integration guide |
| What you install | google-adk[gcp] | google-adk[db] for SQL sessions | google-adk[db] for SQL sessions | temporalio[google-adk]>=1.28.0 |
| What you pay | 50 vCPU-hours and 100 GiB-hours free a month, then $0.085 per vCPU-hour and $0.009 per GiB-hour | Cloud Run usage plus your database | Your servers plus your database | Temporal Cloud or your own Temporal Service, plus the Workers |

The rest of this page walks through each piece in the order you hit it.

## Google ADK sessions: DatabaseSessionService and VertexAiSessionService

A session in ADK is “a single conversation thread between a user and your agent.” The `SessionService` stores its events and state, and you pick one of three:

1.  **`InMemorySessionService`** keeps everything in the process. “All conversation data is lost if the application restarts.”
2.  **`DatabaseSessionService`** writes to PostgreSQL, MySQL, or SQLite through SQLAlchemy. It needs the `db` extra and an async driver.
3.  **`VertexAiSessionService`** stores sessions in Agent Runtime. It needs a Google Cloud project, the `gcp` extra, a storage bucket, and an Agent Runtime resource ID.

The database version looks like this:

```
from google.adk.sessions import DatabaseSessionService
# Example using a local SQLite file:
# Note: The implementation requires an async database driver.
# For SQLite, use 'sqlite+aiosqlite' instead of 'sqlite' to ensure async compatibility.
db_url = "sqlite+aiosqlite:///./my_agent_data.db"
session_service = DatabaseSessionService(db_url=db_url)
```

**The database is yours to run and to migrate.** ADK Python 1.22.0 moved the session schema “from `v0`, which is a pickle-based serialization, to `v1`, which uses JSON-based serialization,” and `adk migrate session` copies the old rows into a new database.

Long sessions also grow the prompt. ADK’s context compaction summarizes “older session history” on rules you set in `EventsCompactionConfig`:

```
from google.adk.apps.app import App, EventsCompactionConfig

compaction_config = EventsCompactionConfig(
    token_threshold=4000,     # Triggers compaction when actual token count exceeds this
    event_retention_size=5    # Number of recent raw events to keep intact when token limit is hit
)

app = App(
    name="my_compacting_agent_app",
    root_agent=root_agent,
    events_compaction_config=compaction_config
)
```

A sliding window (`compaction_interval` and `overlap_size`) works too, and token-based compaction wins when you set both. [Agent memory and context windows](/other-content/agent-memory-and-context-windows) covers the general problem.

## Google ADK tool confirmation and human-in-the-loop

Tool confirmation lets a tool “pause its execution and interact with a user or other system for confirmation” before it runs. It shipped in ADK Python 1.14.0. The yes or no version is one flag, and a function can decide per call:

```
async def confirmation_threshold(
    amount: int, tool_context: ToolContext
) -> bool:
  """Returns true if the amount is greater than 1000."""
  return amount > 1000

root_agent = Agent(
    # ...
    tools = [
        # Pass the threshold function to dynamically require confirmation
        FunctionTool(reimburse, require_confirmation=confirmation_threshold),
    ],
    # ...
)
```

For a structured answer, the tool calls `tool_context.request_confirmation(hint=..., payload=...)` and reads `tool_confirmation.payload` on the next pass. Without the ADK web UI, your app answers over REST: it posts a `function_response` named `adk_request_confirmation` to `/run_sse`, with the `id` of the original `FunctionCall`. With resumability on, it “also must include the Invocation ID,” or ADK “starts a new invocation with the confirmation response.”

**Here’s the catch for production.** The same page lists two known limitations: “DatabaseSessionService is not supported by this feature” and “VertexAiSessionService is not supported by this feature.” So the approval flow and the persistent session stores don’t mix today.

The older route is `LongRunningFunctionTool`. When the model calls one, “the agent runner pauses the agent run,” and your client sends the final response back “for the next run.” Your code owns the waiting and the follow-up message. [Human-in-the-loop approvals for AI agents](/other-content/human-in-the-loop-approvals-for-ai-agents) compares this pattern across frameworks.

## Google ADK resumability with ResumabilityConfig

Resumability (ADK Python 1.16 and later) lets a run “pick up where it left off” after a crash or a dropped connection. You switch it on for the whole `App`:

```
app = App(
    name='my_resumable_agent',
    root_agent=root_agent,
    # Set the resumability config to enable resumability.
    resumability_config=ResumabilityConfig(
        is_resumable=True,
    ),
)
```

Then you resume with the Invocation ID from the event history, through `/run_sse` or `runner.run_async(..., invocation_id=...)`. Three rules on the same page shape how you use it:

1.  Tools run “at least once,” and “may run more than once when resuming a workflow.” A refund tool needs its own duplicate check. ([Retries and idempotency for agent tool calls](/other-content/retries-and-idempotency-for-agent-tool-calls) shows how.)
2.  “Do not modify a stopped agent workflow before resuming it.” Adding or removing agents before a resume “is not supported.”
3.  Custom agents need code changes: a state class, checkpoints for each step, and an `end_of_agent=True` marker.

**Rule 2 matters most if you deploy often.** A stopped run has to resume on the agent definition it started with.

## Google ADK OpenAPIToolset and LiteLLM with Claude

`OpenAPIToolset` turns an OpenAPI spec into tools. It reads “OpenAPI Specification (v3.x)” as a dict, a JSON string, or a YAML string, resolves “any internal references (`$ref`),” and creates one `RestApiTool` per operation. Tool names come from the `operationId`, in snake case, up to 60 characters:

```
from google.adk.tools.openapi_tool.openapi_spec_parser.openapi_toolset import OpenAPIToolset

# Example with a JSON string
openapi_spec_json = '...' # Your OpenAPI JSON string
toolset = OpenAPIToolset(spec_str=openapi_spec_json, spec_str_type="json")
```

ADK Python 2.0.0 added `header_provider`, `ssl_verify`, and `tool_name_prefix` (for two specs with clashing names). You pass the spec in as a string or a dict, so the tools match whatever copy you loaded.

For a model other than Gemini, ADK wraps LiteLLM, “an OpenAI-compatible interface to over 100+ LLMs.” Claude looks like this:

```
from google.adk.agents import LlmAgent
from google.adk.models.lite_llm import LiteLlm

agent_claude_direct = LlmAgent(
    model=LiteLlm(model="anthropic/claude-3-haiku-20240307"),
    name="claude_direct_agent",
    instruction="You are an assistant powered by Claude Haiku.",
    # ... other agent parameters
)
```

ADK requires `litellm>=1.84`. (The LiteLLM page opens with a security advisory: unauthorized code shipped in LiteLLM 1.82.7 and 1.82.8 on PyPI on March 24, 2026.) The model is a line of Python in the agent definition. [Switching model providers for AI agents](/other-content/switching-model-providers-for-ai-agents) goes deeper.

## Deploy Google ADK to Agent Engine or Cloud Run

Agent Engine is “a fully managed auto-scaling service on Google Cloud” for ADK agents. You enable the Agent Platform and Cloud Resource Manager APIs, then run:

```
adk deploy agent_engine \
        --project=$PROJECT_ID \
        --region=$LOCATION_ID \
        --display_name="My First Agent" \
        multi_tool_agent
```

The command “packages your code, builds it into a container, and deploys it.” Billing runs on Agent Compute and Agent Memory: the first 50 vCPU-hours and 100 GiB-hours each month are free, then $0.085 per vCPU-hour and $0.009 per GiB-hour. “For Runtime, idle time spent waiting for the next prompt between turns is not billed.” Sessions add $0.30 per GiB-month of storage and one vCPU-hour per million writes.

Cloud Run is the container route, and `adk deploy cloud_run` is “recommended for Python.” **Set the session flag, or your sessions vanish.** Without `--session_service_uri` and `--artifact_service_uri`, “sessions and artifacts are lost whenever a Cloud Run instance is recycled.” Pass `agentengine://<agent_engine>` to use Agent Runtime Sessions, or any SQLAlchemy URL for your own database. The dev UI ships only with `--with_ui`.

And Temporal? Its `GoogleAdkPlugin` “runs each model call and tool call as a Temporal Activity,” so an agent “keeps its place across Worker restarts, deploys, and transient failures.” You run the Workers and either a Temporal Service or Temporal Cloud ([the cost breakdown](/other-content/temporal-cloud-vs-self-hosted-cost) has the numbers).

## What does Cadenya offer that Google ADK on Agent Engine or Cloud Run doesn’t?

Google ADK gives you the agent code, and you still pick, run, and wire the session store, the approval flow, and the deployment. **Cadenya is the whole loop: conversation state, approvals, tools from your spec, and any model, with nothing to deploy.** Here’s what that covers:

1.  **Nothing else to run.** No Google Cloud project, no Agent Runtime resource, no Cloud Run service, no Temporal Worker. You create an objective over HTTP, and your app stays a stateless web tier.
2.  **No session database to choose or migrate.** Every objective carries a durable event log of its loop. You list the stored events after a run or stream them live, with no async driver, no SQLAlchemy URL, and no `adk migrate session`.
3.  **Approvals that work with stored state.** Mark a tool set as needing approval, for every tool or the ones a filter matches. The objective pauses on `toolApprovalRequested`, and “multiple tools can wait at the same time.” You approve with the `toolCallId`, or deny with a memo that steers the agent.
4.  **Edit the agent while objectives wait.** An objective “keeps that variation’s configuration snapshot even if you edit the variation later.” So you can change the prompt, tools or model while an objective waits, and that objective keeps the configuration it started with.
5.  **Tools from your OpenAPI spec, kept current.** Point a tool set at an OpenAPI 3.0 or later document by URL, and Cadenya “checks the specification for changes each hour.” Filters and progressive discovery keep a big API out of the context window. MCP servers and plain HTTP endpoints work too.
6.  **Any model, on your own keys.** The model is a setting on a variation, not a line of Python, so a switch needs no deploy and no LiteLLM pin. Use any model on OpenRouter or your own endpoint that speaks the OpenAI chat format, and pay your provider directly. Weighted variations route more traffic to whichever model or prompt scores higher.
7.  **Context compaction included.** Cadenya compacts the context window when a conversation gets long and records a `contextWindowCompacted` event. One API call compacts a running objective on demand.
8.  **Acting on behalf of the signed-in user.** An objective can carry a short-lived token, such as “a JWT minted to act on behalf of a user,” and the objective secret wins over the shared one on each tool call.
9.  **A Python SDK for the Python you run.** The `cadenya` package supports Python 3.9 and later, and the TypeScript, Ruby, and Go SDKs ship alongside it. All four are at 1.9.0 under Apache-2.0, and the TypeScript SDK has shipped 113 versions since April 2026.
10.  **A price in one line.** Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop. A loop is one LLM request, so there are no vCPU-hours or GiB-hours to estimate.

[How objectives work](/docs/guides/the-basics/objectives) walks through a full run, and the free plan needs no card.

Create an account at [app.cadenya.com/signup](https://app.cadenya.com/signup?utm_source=cadenya.com&utm_medium=article&utm_campaign=google-adk-agents-in-python), then copy your API key from the [API keys page](https://app.cadenya.com/account/apiKeys).