Skip to content

fix(advanced): send Gemini a function calling mode on subagent calls - #1071

Merged
radu-mocanu merged 2 commits into
mainfrom
fix/gemini-advanced-tool-config
Sep 14, 2026
Merged

radu-mocanu merged 2 commits into
mainfrom
fix/gemini-advanced-tool-config

Conversation

@radu-mocanu

@radu-mocanu radu-mocanu commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • advanced agents send Gemini a function_calling_config mode on subagent calls, so gemini-2.5-flash stops replying with Python source instead of a tool call
  • a faulty finish reason raises on the advanced path, for every provider, instead of arriving as an empty message
  • a turn with no text and no tool calls is refused rather than accepted as the agent's final answer

Why

a deepagents subagent has no response format, so nothing forced a tool choice and vertex fell back to AUTO. the malformed reply came back empty, read as a final answer, and the run either looped to its recursion limit or reported success with the subagent having contributed nothing.

Copilot AI lite review requested due to automatic review settings September 7, 2026 17:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The middleware change is narrowly scoped, aligns advanced-agent behavior with the already-established payload handler flow, and is backed by comprehensive new/updated tests for the reported failure modes.

Pull request overview

This PR fixes advanced-agent + subagent interactions with Gemini (notably gemini-2.5-flash) by ensuring deep-agent model calls are shaped/validated via the same provider payload handler logic used in the ReAct path, preventing malformed function-call outputs from being silently accepted as empty “final answers”.

Changes:

  • Add _PayloadHandlerMiddleware to (a) inject Gemini function_calling_config in VALIDATED mode when tool_choice is unset, and (b) validate provider stop reasons + reject empty non-reasoning, non-tool-call responses.
  • Ensure the middleware is applied to both the main advanced agent and declarative subagents (including the general-purpose subagent) via _subagents_with_middleware.
  • Add targeted tests for tool-config injection, stop-reason validation, empty-answer rejection, and subagent wiring; update existing middleware-count assertions to focus on the runtime-prompt middleware.
File summaries
File Description
src/uipath_langchain/agent/advanced/agent.py Adds payload-handler middleware, wires it into deep-agent middleware and subagent specs, and rejects empty responses.
tests/agent/advanced/test_payload_handler_middleware.py New unit tests covering tool_config injection, stop-reason checks, empty-answer rejection, and subagent wiring.
tests/agent/advanced/test_create_advanced_agent_graph.py Updates assertions to select the runtime system-prompt middleware rather than assuming it’s the only middleware.
tests/agent/advanced/test_conversational_advanced_agent_graph.py Same as above for the conversational advanced agent graph tests.
pyproject.toml Bumps project version to 0.17.5.
uv.lock Updates locked package version to 0.17.5.
Review details
  • Files reviewed: 5/6 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@radu-mocanu
radu-mocanu force-pushed the fix/gemini-advanced-tool-config branch 2 times, most recently from 3140b99 to e0bd636 Compare September 14, 2026 12:10
@radu-mocanu radu-mocanu changed the title fix(agent): send Gemini a function calling mode on advanced agent calls fix(advanced): send Gemini a function calling mode on subagent calls Sep 14, 2026
An advanced agent's subagent turn carries no forced tool_choice, so the
request reached Gemini with no function_calling_config at all and Vertex
fell back to AUTO. gemini-2.5-flash then answered with Python source
instead of a function call, finishing MALFORMED_FUNCTION_CALL. Only the
main agent was spared, because its structured-output response format
forces tool_choice on every call.

Nothing on the advanced path called check_stop_reason either, so that
malformed finish reason degraded into an empty message that reads as a
final answer: the subagent handed back an empty result and the caller
either looped to its recursion limit or reported success it had not
achieved.

One middleware now routes deep-agent calls through the payload handler
the react path already uses. It injects the handler's tool_config only
when tool_choice is unset, matching langchain_google_genai's own gate so
the two can never conflict, and it checks the finish reason for every
provider. A turn with no text, no tool call, and no reasoning is refused
rather than accepted as an answer.

create_deep_agent gives its middleware argument to the main agent alone
and assembles the general-purpose subagent itself, so the subagent is
reached through its spec. deepagents still builds that subagent's own
middleware stack, tools, model, and prompt around ours.
@radu-mocanu
radu-mocanu force-pushed the fix/gemini-advanced-tool-config branch from e0bd636 to 564c2f4 Compare September 14, 2026 15:13
main released 0.18.2 while this branch was carrying a bump to that same
version, so the rebase resolved the bump away and left the branch with
none. 0.18.0 through 0.18.2 are published.
@radu-mocanu
radu-mocanu enabled auto-merge (squash) September 14, 2026 15:19
@sonarqubecloud

Copy link
Copy Markdown

@radu-mocanu
radu-mocanu merged commit d28afd7 into main Sep 14, 2026
47 checks passed
@radu-mocanu
radu-mocanu deleted the fix/gemini-advanced-tool-config branch September 14, 2026 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants