fix(agentic): cap-recovery de-noise, Gemini serial-tool workaround, translation-400 retry#16
Merged
Merged
Conversation
The graceful tool-iteration cap recovery worked in 6/6 completed runs of the TSX smoke, yet each healthy recovered run surfaced ERROR-level spans, making the runs look failed in trace review. Investigation: the runner itself only logged the recovery at INFO — it never emitted an ERROR. The ERROR level comes from ADK internals: ADK raises LlmCallsLimitExceededError inside run_async, and ADK's own span (plus the OpenInference ADK instrumentation) records that exception and marks the span ERROR before it ever reaches our except clause. That status is stamped inside the already-closed ADK span, so we cannot cleanly override it from our code without reaching into ADK/OTEL internals. Change what is ours: upgrade the recovery log from INFO to a single WARNING that names the cap and states the recovery is expected, not a failure — so operators have one authoritative, easy-to-grep signal. Document the residual, unsuppressable ADK/OTEL ERROR span noise in the runner's class docstring so it is not mistaken for a real failure. Tests: assert a recovered capped run emits exactly one runner WARNING carrying the cap value and no runner ERROR record. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…around) The Vector proxy's OpenAI<->Gemini translation drops `function_response.name` on Gemini *parallel* tool-call batches, producing a blocking 400 that costs the whole prediction. The proxy team has been notified (see planning-docs/workshop-paper/proxy-bug-report-function-response-name.md on the content branch); this is an interim mitigation. build_adk_agent now appends a short instruction line telling Gemini-family agents to call tools one at a time, applied only when the agent (a) is Gemini-family and (b) actually has tools — a tool-free agent can never emit a parallel batch. Claude parallel batches translate fine and are left untouched. Investigated the LiteLLM `parallel_tool_calls=False` knob as an alternative: ADK's LiteLlm forwards it to litellm.acompletion, but whether the Vector proxy honours that OpenAI param is unverified — it silently drops others (e.g. reasoning_effort; see planning-docs/vector-llm-proxy.md). The prompt line is the deterministic, offline-testable lever, so we use that and keep it clearly marked as a workaround to remove once the proxy is fixed. Tests: the serial-call line is appended for a Gemini agent with tools (both the bare-string and proxy-wrapped LiteLlm paths) and absent for a tool-free Gemini agent and for a Claude agent with tools. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Defense in depth for the Vector-proxy OpenAI<->Gemini translation bug that drops function_response.name on Gemini parallel tool-call batches, surfacing as a blocking 400 that otherwise loses the whole prediction. The agent-factory serial-tool-call workaround reduces how often the model emits a parallel batch, but if one still slips through, AgentPredictor.predict now retries the whole run exactly once. The runner's fresh_session_per_message default makes the rerun start from a clean session. The retry is kept strictly to that one error signature: the exception string must contain "function_response.name" AND carry a bad-request signal (HTTP 400 status code or a BadRequestError-shaped class name). Any other failure — and a second consecutive translation 400 — propagates unchanged. Tests: one translation 400 retries once and succeeds; a second consecutive translation 400 re-raises after the single retry; an unrelated 400 and a marker-bearing non-400 error both propagate without a retry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary — trace-review-driven hygiene (3 of 4 concerns; sandbox persistence held)
build_adk_agentappends a call-tools-one-at-a-time instruction for Gemini-family models with tools, mitigating the proxy's parallel-batchfunction_response.nametranslation bug (reported to the proxy team). Claude untouched. The LiteLLMparallel_tool_calls=Falseknob was investigated but the proxy silently drops unrecognized params, so the deterministic prompt lever was chosen.AgentPredictor.predictretries exactly once on a BadRequest carryingfunction_response.name(fresh session), so a translation-bug hit costs a retry, not a prediction.Verification (orchestrator-run)
pre-commit --all-files clean; 684 passed, 7 skipped. Live re-verify items (serial-instruction efficacy, real-400 signature match, residual span noise) queued for the next smoke.
Sandbox investigation (for the persistence decision — no changes shipped)
aieng-agents'CodeInterpreter.run_codecreates a fresh E2B sandbox per call and kills it infinally— documented behavior, exactly matching the observed NameErrors. Per-run persistence would mean re-architecting that external tool or a run-scoped wrapper threaded through ADK's tool plumbing.archis confirmed absent from the E2B template. Separately:DomainConfig.code_exec_preinstalledis only rendered into the adaptive agent's instruction — the stateless code agent is never told what's installed; that's the natural fix site once the hold lifts.🤖 Generated with Claude Code