Skip to content

fix(agent): don't force tool_choice on models that reject it - #1111

Open
denispetre wants to merge 1 commit into
mainfrom
fix/skip-forced-tool-choice
Open

denispetre wants to merge 1 commit into
mainfrom
fix/skip-forced-tool-choice

Conversation

@denispetre

Copy link
Copy Markdown
Contributor

Problem: on alpha, claude-opus-5-5 fails every ReAct agent run on its first LLM call (run):

tool_choice: type "tool" and "any" are not supported for this model.
  • llm_node forces tool_choice="any" on every non-conversational turn.
  • thinking_rejects_forced_tool_choice only fires on an explicit thinking config, and Opus 5.5 thinks by default.
  • Even when it does fire, the thinking-off extraction retry can't work, because Opus 5.5's thinking can't be turned off.

claude-opus-5 passes the same run (control).

Fix: the gateway flags such models with discovery modelDetails.shouldSkipForcedToolChoice (UiPath/Arima#3103); the LangChain client already exposes that as model.model_details. For flagged models, llm_node:

  • sends tool_choice="auto" instead of any, including when the graph is configured with any
  • on a tool-less turn, re-asks with a trailing "call a tool" user message and keeps thinking and reasoning blocks, instead of the thinking-off extraction
  • still raises THINKING_LIMIT_EXCEEDED on a second stall, as today

Unflagged models are unaffected. The client-side safety net, which relaxes any forced choice that still reaches the wire, is UiPath/uipath-llm-client-python#139.

Tests: TestModelRejectsForcedToolChoice in test_llm_node.py (auto on turn 1 for configured auto/any, nudge keeps thinking and skips extraction, second stall raises) and tests/chat/test_thinking.py for the predicate. tests/agent/react and tests/chat pass.

🤖 Generated with Claude Code

Claude Opus 5.5 400s on tool_choice "any"/"tool" and its thinking can't be
turned off, so every low-code / coded ReAct run fails on its first LLM call
and the thinking-off extraction retry can't recover it either. The gateway
flags such models with modelDetails.shouldSkipForcedToolChoice; for them the
LLM node now sends tool_choice "auto" and re-asks a stalled turn with a
trailing "call a tool" user message, thinking kept. A second stall still
raises THINKING_LIMIT_EXCEEDED.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 23, 2026 10:36

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.

Copilot review overview

🔵 Needs a closer look

Moderate findings remain for legacy-model flag propagation and conversational forced-choice handling; a documentation nit also remains.

Review effort: Lite
Findings: None

What changed in this PR

This PR updates ReAct tool-choice handling for models that reject forced tool calls.

Changes:

  • Detects shouldSkipForcedToolChoice.
  • Uses auto with thinking-preserving tool-call nudges.
  • Adds predicate and ReAct regression tests.
File Summary Final review findings
tests/​chat/​test_thinking.py Tests discovery-flag detection. None.
tests/​agent/​react/​test_llm_node.py Tests adaptive choice, nudging, and stall limits. None.
src/​uipath_langchain/​chat/​thinking.py Detects the gateway rejection flag. Moderate (1 vote): Legacy models discard the discovery flag, so the original forced-choice failure can remain.
src/​uipath_langchain/​agent/​react/​llm_node.py Applies adaptive tool choice and retry behavior. Moderate (1 vote): Legacy-client models may still receive tool_choice="any".
Moderate (1 vote): Conversational graphs can bypass the flagged-model override.
Nit (1 vote): Update the docstring to distinguish nudge retries from thinking-off extraction.
src/​uipath_langchain/​agent/​react/​forced_extraction.py Adds thinking-preserving nudge messages. None.

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

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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.

2 participants