fix(claude-code): implement tool_choice support for forced tool calls#733
Merged
nicoloboschi merged 2 commits intoMar 30, 2026
Merged
Conversation
The call_with_tools() method now properly handles the tool_choice parameter to force specific tool calls. Previously, the parameter was accepted but ignored, causing the reflect agent to fail when trying to force specific tools on each iteration. Fixes vectorize-io#732 Changes: - When tool_choice forces a specific function: filter allowed_tools to only that tool (with mcp prefix) and add a strong system prompt instruction - When tool_choice is 'required': add instruction that model must call at least one tool - When tool_choice is 'none': clear allowed_tools and mcp_servers to disable all tools - When tool_choice is 'auto' (default): no change (existing behavior) This matches the approach used in the OpenAI provider while adapting to the Claude Agent SDK's lack of native tool_choice parameter by using allowed_tools filtering and system prompt instructions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
25c2ecf to
9df390f
Compare
Contributor
Author
|
CI update: The remaining test failures appear to be infrastructure-related ( |
nicoloboschi
approved these changes
Mar 30, 2026
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
Fixes #732 — Reflect agent never calls tools with claude-code provider because
tool_choiceparameter was accepted but completely ignored.Root Cause
The
call_with_tools()method inclaude_code_llm.pydeclaredtool_choice: str | dict[str, Any] = "auto"as a parameter but never used it. When the reflect agent passedtool_choice={"type": "function", "function": {"name": "search_mental_models"}}to force specific tools on each iteration, the claude-code provider ignored it entirely. Result:tools=[none]across all iterations, hallucinated "no information found" responses.Fix
Since the Claude Agent SDK doesn't have a native
tool_choiceparameter, the fix enforces it through two mechanisms:allowed_toolsfiltering — restrict which tools are available to the modelBehavior for each tool_choice value:
{"type": "function", "function": {"name": "X"}}mcp__hindsight_tools__X"required""none""auto"(default)This mirrors the approach in
openai_compatible_llm.py(lines 553-565) while adapting to the Claude Agent SDK's constraints.Changes
hindsight-api-slim/hindsight_api/engine/providers/claude_code_llm.py: 43 insertions, 3 deletionsClaudeAgentOptionscreationTesting
ruff checkcleancall_with_tools()code path —call()(non-tool) is unchangedtools=[search_mental_models, search_observations, recall]instead oftools=[none]