github google/adk-python v2.9.0

3 hours ago

Changelog

2.9.0 (2026-09-10)

Highlights

This release focuses on agent resilience and ecosystem integration by introducing automatic model failover, native voice support via LiveKit, and compatibility with MCP SDK 2.x.

  • Models: Safeguard agent uptime by automatically failing over to backup models when the primary model encounters errors. (c300b8d)
  • Integrations: Build rich voice and telephony agents using the newly added LiveKit runner. (f277d91)
  • Workflows: Simplify graph workflow management by authoring and loading ADK 2.0 graphs directly from declarative YAML configurations. (2a9461b)
  • MCP: Work with MCP SDK 2.x servers as well as 1.x. Installs continue to resolve 1.x by default; install 2.x deliberately to opt in. (856acf2)

Breaking changes

  • Workflow node resumption: A node that failed now runs again when the workflow resumes, where before it replayed as though it had completed. Make node bodies idempotent: a node that performs an external side effect and then fails will perform that side effect again on every resume.
  • GCS tool local paths: The GCS tools now read and write local files only inside the directory named by local_file_root, and refuse local file access entirely when that setting is absent. Paths may be absolute or relative, and are judged by where they resolve.
  • In-memory sessions only: InMemorySessionService now raises SessionNotFoundError when an event is appended to a session it does not hold, instead of accepting the event and discarding it. The database-backed services already behaved this way, so this affects in-memory sessions alone.

Two further changes are marked breaking in the commit log but do not affect a
default installation. Nested workflow retry changes behavior only for a node
that already sets retry_config. The MCP SDK 2.x field handling applies only if
you install MCP 2.x deliberately, which this release does not resolve to.

All changes

⚠ BREAKING CHANGES

  • retry a nested workflow when a node inside it fails
  • confine GCS tool local file paths to a configured root
  • rerun a failed node on resume instead of replaying it as complete
  • raise SessionNotFoundError when appending to an unknown session
  • mcp: under MCP SDK 2.x, fields a server sends that the SDK does not declare no longer reach the caller. 2.x closed its models, so an unknown key on a CallToolResult, or on a tool declaration read via raw_mcp_tool, is discarded during validation before ADK sees it. _meta is unaffected: it is a declared field and still arrives. Nothing in ADK can restore the others; a server that relies on vendor extensions should move them under _meta. On 1.x they still arrive as before.

Features

  • add a2a_state_forwarding sample (1b28de4)
  • add FallbackModel for automatic failover between models (c300b8d)
  • add get_authenticated_url and get_signed_url to GcsArtifactService (10ac52b)
  • add ignore_args option to tool trajectory evaluation (e2a213f)
  • add transfer_reason to transfer_to_agent to prevent loops (22ab4d8)
  • agent evaluations print detailed results when all tests pass (e1ae543), closes #3891
  • generalize docker build and run for multicloud environments (0673f05)
  • integrations: add LiveKit runner for voice and telephony (f277d91)
  • load ADK 2.0 graph workflows from YAML configuration (2a9461b)
  • mcp: support MCP SDK 2.x alongside 1.x (856acf2)
  • support hyphenated column names in BigQuery tools (b736b0d)
  • telemetry: add ability to track skill loads (0cd24c8)
  • telemetry: add script execution instrumentation (0dbc37d)
  • telemetry: export logs over OTLP to telemetry.googleapis.com (5e6df42)
  • tools: support FunctionNode auto-inference in NodeTool (ea8609d)

Bug Fixes

  • a2a: quote a fetched card description and drop relayed auth responses (7ee3ae9)
  • a2a: require https for a non-loopback agent card URL (fe30ebb)
  • a2a: stop a completed task delegation breaking later peer delegations (04be48b), closes #6831
  • add optional OIDC verification for Pub/Sub and Eventarc triggers (73d9fe0)
  • append the user's next turn when it joins a paused task (678d7e9)
  • apply state_delta when resuming without a new_message (6de43b0), closes #6644
  • artifacts: give concurrent gcs artifact saves distinct versions (0a12027)
  • auth: declare that AuthHandler.generate_auth_uri can return None (e4c8994)
  • balance callback lifecycle for hallucinated tool calls (f842a15), closes #4775
  • bigquery: lazy-load Dataplex so BigQueryToolset imports without it (b65be01)
  • callables: extract unified CallableSpec and resolve doc and unwrap edge cases (c506ddf)
  • cancel the invocation when a sync run() generator is closed early (080d5e7)
  • cli: explicitly set memory_service_uri='memory://' when --in_memory is passed (b0bb3dd)
  • cli: make the decorators on API and dev server routes take effect (308cc32)
  • cli: sync the Agent Engine class-method catalogue with its source (0043044)
  • close a task-mode delegation when the remote agent finishes (4cd8aa4)
  • coerce an integral float back to int for an int-typed tool parameter (adbee3c)
  • coerce callable AgentInfo.instruction for app-info (ada8652), closes #6909
  • default AgentCardBuilder capabilities to streaming=True (b018062), closes #6672
  • defer local state/event mutation until Vertex append succeeds (903f37f), closes #6998
  • end a live session when the client closes the request queue, instead of reconnecting or busy-waiting (07b1173)
  • end tool callback chains on the first non-None result (895b6f2)
  • environment: terminate the whole process tree when a local command times out (fa321f1)
  • fail a workflow when a detached dynamic node errors or interrupts (34e13df)
  • flows: keep code execution going instead of reporting no content (ae30506), closes #7002
  • flows: move before_tool_callback from prepare phase into per-tool execution (fb45e24)
  • flows: propagate contextvars set in before_tool_callback to the tool (0b75a66)
  • flows: restrict agent transfer to the declared transfer targets (8fefa37)
  • forward GenerateContentConfig.seed to LiteLLM (668e024), closes #6513
  • forward the agent's generation config (temperature, top_p, top_k, max_output_tokens, seed, media_resolution) to the Live API (bd74c42)
  • gcs: judge a local path by where it lands, not by whether it is absolute (48b28de)
  • guard malformed tool call argument JSON in LiteLlm response parsing (6e59663), closes #5896
  • handle failed inference cases gracefully in GEPA pipeline (7bffb0a), closes #6004
  • honor save_live_blob when caching live user audio (b2c7664)
  • initialize Anthropic client off event loop (e421017)
  • invalidate import caches during agent module validation (c7ffcfa), closes #6948
  • keep the original event id when reloading a Vertex session (864914b), closes #6530
  • keep the tool filter and name prefix when cloning a skill toolset (e4f1700)
  • keep the turn anchor when a long-running tool result is posted back (b499fbe)
  • label the dynamic instruction so a model does not read it as a user turn and imitate it (8cdbbb1)
  • log an error when a model returns multiple candidates (25f5214)
  • make SkillToolset system instruction respect tool_filter (66d7609), closes #6448
  • match a branch's run ids exactly when resolving HITL interrupts (8db82ba)
  • mcp: keep resolving MCP 1.x by default (46edaa2)
  • mcp: only attach application default credentials to Google API hosts (f9f4a39)
  • mcp: skip summarization when a tool call pauses for confirmation (cb0eb22)
  • memory: do not let a failing temp-file cleanup mask the upload error (2778930)
  • microsecond-safe DatabaseSessionService on SQL Server (mssql) (7d7bac0)
  • models: stop a content-free thought signature from wedging a session (a5d6238)
  • name the async driver when a database URL uses a sync one (76601c6)
  • never empty the request contents when applying a context cache (8e30a30), closes #6945
  • normalize session_id before duplicate check in in-memory service (bfeb04c), closes #6887
  • openapi: bound the REST API tool's default HTTP waits (5d0bd5f)
  • plugins: keep a staticmethod a staticmethod when auto-tracing wraps it (939ff92)
  • point misplaced generation kwargs at generate_content_config (e51aadc), closes #6836
  • populate model_version on AnthropicLlm responses (408f57d), closes #6847
  • preserve anyOf and camelCase aliases in LiteLLM tool schemas (0e97a8f), closes #6738
  • preserve Gemini 3 thought signatures in interaction history (51f21e7)
  • raise a sub-agent's own error from ParallelAgent, not a group (3ecd3d7)
  • raise AlreadyExistsError on concurrent create_session races (cbccae6)
  • read an MCP tool's schema under either spelling in telemetry (40c8333)
  • rebind an agent's own callback methods when cloning (f449bb7)
  • redis: match app_name and user_id literally when listing sessions (4b26bba)
  • refuse a tool call whose arguments a broken stream cut short (da22e43), closes #6716
  • refuse a transfer to a forbidden parent or peer agent (b0503a0)
  • reload changed agent correctly (397ed42), closes #4956
  • report a metric that never ran as not evaluated, not as failed (9c9b81a)
  • report an unknown tool name to the model instead of raising (f337793)
  • report the real finish reason from a LiteLlm stream (eaed0aa)
  • rerun a paused workflow node after the user answers it (2fb877c)
  • resolve every Claude model id rather than enumerated generations (01919b3)
  • resolve scheduler leakage and use node.clone() in DynamicNodeScheduler (64b5b9c)
  • retry once on 429 in VertexAiSessionService (cc5985a)
  • return custom_metadata from VertexAiMemoryBankService.search_memory (3a37d7a), closes #6946
  • route interleaved interactions function-call deltas by step index (f73bb37), closes #6832
  • samples: correct the live audio path, the live eval config and the multimodal samples (6499a44)
  • samples: read the knowledge agent data store from the environment (d5129f3)
  • sanitize anyOf schemas for Vertex AI function declarations (642439c), closes #6373
  • show adk create --type in --help (d0d5ade), closes #6737
  • skip duplicate user event append on invocation retry (d06a7fe), closes #4506
  • skip rewound invocations when resuming agent in _find_agent_to_run (ed1306f), closes #4169
  • skip summarization for terminal A2A task states (aef3a9c)
  • spanner: release the client, transports and sessions each tool call creates (edf99a3)
  • stop a child branch stamped on a user event moving the invocation root (181d52e)
  • stop after final preprocessing responses (764e2cb), closes #4472
  • stop caching a remote agent card that failed validation (2685acd)
  • stop CompletionsHTTPClient leaking its httpx client via atexit (3fcda36)
  • stop ContainerCodeExecutor leaking via atexit (04f8df1)
  • stop declaring dict value types to Google AI (73803f4)
  • stop offering run_skill_script when no code executor is configured (66315da)
  • stop sending the OAuth client secret to the client (393b3b0)
  • stop silently dropping sampling settings on interactions API (cd0dddc)
  • support multi-turn nested HITL pause and resumption across workflows and agent tools (6d14518)
  • telemetry: end the inference span at the finish reason, not at the first chunk (6364060)
  • telemetry: keep thought signatures out of span attributes (5d965c3)
  • telemetry: remove helper methods for type-safe hallucination checking and update function signatures (e1e4331)
  • tools: import the two annotation names that are referenced but unbound (13376d4)
  • tools: support zero-argument nodes in NodeTool (8128b84)
  • tools: treat an empty openapi security requirement as optional auth (3c6a5b7)
  • treat a max_iterations of zero as zero loop passes (afbcaff)
  • treat an error event without function calls as a final response (75ae2db)
  • update max_llm_calls validation to reject values greater than or equal to sys.maxsize (44e0b2a)
  • utils: adapt callback keyword arguments to positional parameters (a213e76)
  • utils: include agent name in instruction context variable missing error (86b2e5b)
  • utils: report an unknown session id in the cache performance analyzer (f7c0c01)
  • validate app_name before interpolating into deploy Dockerfile (6eb1d35)
  • validate function call author before resuming auth-gated tool calls (328ecb9)
  • vmaas: cache the sandbox access token on the computer instance (21c2fbd)
  • warn once per experimental surface instead of on every use (391fdc6)
  • workflow: drop resume inputs from the resumable node checkpoint (790cb7c)
  • workflow: omit the oauth client secret from the credential request event (fdfa4b1)
  • workflow: retry subclasses of a configured retry exception (f6fe8d2)

Performance Improvements

  • defer imports in code executors (d9648b0)
  • extend the workflow replay index instead of rebuilding it per event (f8fdfed)
  • stop rescanning the session for every user response event (4295bd0)

Documentation

  • a2a: explain the human-input resume tests in their own terms (909ace1)
  • add node as tool developer unit guide and sample docs (9fcd97e)
  • add unit guides for A2A, skills and the execution backends (b89037d)
  • add unit guides for evaluation, serving and observability (eb532ca)
  • agents: state the lazy-import rule the comment only pointed at (ac96686)
  • align callback contracts with runtime behavior (6a811d2)
  • antigravity: add the AntigravityAgent unit guide (86b50c4)
  • antigravity: describe the scenario a compaction-turn test covers (ef714fe)
  • antigravity: name the Antigravity SDK in full and disambiguate "agent" (b71a59c)
  • correct the heading in the llms-full.txt pointer (2880fbf)
  • document Live streaming in adk-agent-builder and adk-architecture (a80d264)
  • document replacing a failed tools listing via get_tools (c7ef8cf), closes #6748
  • features: use a real feature name in the is_feature_enabled example (93cd316)
  • flows: drop the incorrect move instruction from three compatibility shims (d637d1b)
  • give the unit guide skill a voice section (10333f2)
  • live: move LiveRequestQueue developer guide to docs/guides/live (d563bde)
  • memory: describe ttl as the revision_ttl alias it actually is (c3f785c)
  • openai: drop the third-party gateway from the OPENAI_BASE_URL tip (8d624bd)
  • plugins: say what the reflect-and-retry failure counter's lock guarantees (6762652)
  • scope the gVisor claim to the mode that provides it (bd4c6d7)
  • state what a parallel branch isolates and what it shares (a28c66b)
  • tests: remove the internal notebook link from the hello world fixtures (7988f4c)
  • tools: scope the Spanner capabilities setting to the toolset that reads it (c4a7ee2)

Miscellaneous Chores

Don't miss a new adk-python release

NewReleases is sending notifications on new releases.