Recent development · Practical technical guide · 3 November 2026
ADK Go v2.7.0, released on 2 November 2026, caps model calls per invocation at 500, makes optional placeholders surface errors, gives each credential its own MCP session and switches telemetry to GenAI v2. What the source does and what to check before upgrading.
What the release contains
Google released ADK Go v2.7.0 on 2 November 2026. The notes list new features (Anthropic Claude as an experimental model, search-gated tool discovery, experimental classifiers, Gemini built-in tools) and five breaking changes. This article covers the changes most likely to alter a running agent, checked against the v2.7.0 source. The model-call budget rules below were also run with Go 1.26.10 against the v2.7.0 module, using a scripted model and no provider; the other behaviour described is read from the code, not run.
A cap of 500 model calls per invocation
RunConfig.MaxLLMCalls bounds the model calls one invocation may make, across every agent it runs. The field's comment in agent/run_config.go spells out the semantics, and they differ from adk-python in one important way.
| Value | ADK Go 2.7 | adk-python max_llm_calls |
|---|---|---|
| field not set (0) | 500, or ADK_MAX_LLM_CALLS if it parses as an integer | 0 means no limit |
| negative, such as -1 | no limit | not the documented way |
| ADK_MAX_LLM_CALLS not an integer | ignored silently, 500 applies | |
| ADK_MAX_LLM_CALLS=0 or negative | no limit |
The counter increments before it checks, so a limit of n allows exactly n calls, and the next one ends the run with an error wrapping agent.ErrLLMCallsLimitExceeded. Sub-agents run through agenttool get their own budget of the same size, and the compaction summarizer's calls are not counted. A run started without the runner has no limit.
Two things to check. Code ported from Python that sets 0 to disable the limit now gets 500; use -1. And long-running agents that legitimately make hundreds of calls, such as a coding loop, will now stop with an error at 500; decide whether that is a bug you want surfaced or a limit you raise. Handle the error with errors.Is and report it as a budget stop rather than a crash. The companion example in agent-decision-lab runs a scripted model that never stops calling a tool and tests five cases against v2.7.0: a limit of 3 allows exactly three calls, 0 with no usable override stops at 500, ADK_MAX_LLM_CALLS=7 applies only when the field is 0, and -1 removes the limit.
Go against the v2.7.0 API; the budget rules it relies on are exercised by the companion tests.
cfg := agent.RunConfig{MaxLLMCalls: 120} // a deliberate per-task budget
for ev, err := range r.Run(ctx, userID, sessionID, msg, cfg) {
if errors.Is(err, agent.ErrLLMCallsLimitExceeded) {
return reportBudgetStop(sessionID) // tell the user the task was cut short
}
if err != nil {
return err
}
handle(ev)
}Optional placeholders now fail on real errors
Instructions can contain {key?} and {artifact.name?}, which render empty when the value is missing. Before 2.7.0 they rendered empty on any error too, so an unavailable session store or artifact service silently produced a prompt with a hole in it. In instruction_processor.go the optional branch now returns empty only for session.ErrStateKeyNotExist or fs.ErrNotExist, and every other error fails the run. If an artifact placeholder is used and no artifact service is configured, the run fails with "artifact service is not initialized".
Two consequences. A custom artifact.Service must wrap fs.ErrNotExist for missing files, or optional placeholders that used to render empty will now fail. And an agenttool sub-agent whose instruction uses an optional artifact placeholder fails when the root runner has no artifact service, as the release notes warn.
One MCP session per credential
With mcptoolset.Config.Auth set, each distinct credential now gets its own MCP session, so servers that bind a session to the user who opened it stop answering other users with 403. The pool in tool/mcptoolset/client.go closes sessions idle for 10 minutes and caps the pool at 64 sessions, evicting the least recently used idle one; sessions in use are never evicted, so the cap can be exceeded while more than 64 are busy. For a multi-tenant agent this is a correctness fix, and also a new source of connections to the MCP server: plan for one per active user, not one per process. Without Auth nothing changes.
Telemetry and the rollback switch
Traces now follow the OpenTelemetry GenAI semantic conventions v2. The notes list the visible changes: one gen_ai.client.inference.operation.details event per model call replaces the old log events, message content on spans becomes a structured value, tool arguments and results are recorded only when content capture is on, and an LLM-agent root gets an invoke_workflow parent span. Dashboards and alerts built on the old names will break. Setting ADK_TELEMETRY_SCHEMA_VERSION_OPT_IN=otel_semconv_1_36 restores the old format, supported until at least 31 March 2027, which gives time to migrate queries.
New capabilities worth knowing about
- Search-gated tools.
tool/toolsearchwraps a toolset so the model starts with asearch_toolstool and a small core set; it ranks tools with BM25 and returns up to 8 matches. The package comment warns that gating decides what the model sees, not what a caller may use, so pass a toolset already filtered for the caller. - Claude models.
model/anthropicmodelimplements the model interface over the Anthropic Messages API and Vertex AI, marked experimental. - Go 1.26.10 required. The module now requires it; update toolchains in CI first.
- Smaller behaviour changes.
LoopAgentstops on context cancellation,geminitool.GoogleSearcherrors on non-Gemini models, and the OpenAI-compatible model refuses config fields newer than it supports.
How search-gated discovery behaves
Large tool catalogues, such as several MCP servers behind one agent, cost context on every model call. The toolsearch wrapper starts the model with search_tools plus a configured core set. The search tool accepts a natural-language task, an exact selection written as select:tool_a,tool_b, or a regular expression over tool names. Natural-language queries are ranked with BM25 over names, descriptions and argument metadata, results scoring below a tenth of the top match are dropped, at most eight are returned, and descriptions are cut to 200 characters in the results.
Discovered tools are recorded in session state under a key prefixed tool_search:discovered: and the agent's name, so they stay declared for the rest of the session rather than for one step. They are appended in discovery order, which the source says keeps as much of the provider's prompt-cache prefix as possible, and a discovered tool that the base toolset stops returning drops out. A long session still accumulates tools, slowly giving back the context saving. The source also warns that a base tool reaching the agent another way, such as the agent's own tool list, fails every later model step with a duplicate-tool error once discovered: give each tool only through the gating toolset.
Upgrade checklist
- Search for
MaxLLMCallsandmax_llm_callsin ported code; replace 0-means-unlimited with -1, or set a deliberate budget. - Grep instructions for
?}placeholders and run each agent once against a staging session store to see whether any now fail. - If you implement
artifact.Service, wrapfs.ErrNotExistfor missing files. - Set the telemetry opt-in variable before upgrading, then migrate dashboards and remove it.
- For multi-tenant MCP with auth, check the MCP server's connection limits against your peak number of active users.
Sources and scope
Checked against these sources on 3 November 2026. Event: ADK Go v2.7.0 released, 2 November 2026; recheck it before acting. Read from the v2.7.0 release notes and source on 3 November 2026. The MaxLLMCalls rules were run on 3 November 2026 with Go 1.26.10 and google.golang.org/adk/v2 v2.7.0 on one Windows 11 machine, with a scripted model; placeholders, MCP sessions, telemetry and tool search were not run.
- ADK Go v2.7.0 release notes (2 November 2026)
- ADK Go v2.7.0 source: agent/run_config.go (MaxLLMCalls semantics)
- ADK Go v2.7.0 source: internal/agent/runconfig/limits.go (ResolveMaxLLMCalls, ADK_MAX_LLM_CALLS)
- ADK Go v2.7.0 source: internal/llminternal/instruction_processor.go (optional placeholders)
- ADK Go v2.7.0 source: tool/mcptoolset/client.go (per-credential sessions, idle timeout, pool cap)
- ADK Go v2.7.0 source: tool/toolsearch/toolsearch.go (search-gated tool discovery)
ADK Go 2.7.0 stops an invocation after 500 model calls unless told otherwise, and unlike Python 0 means the default, so use -1 for no limit. Optional placeholders now fail on real errors, MCP auth gets per-credential sessions, and telemetry switches to GenAI v2 with a rollback variable.