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