Skip to content

Feature request: expose tool_choice parameter in ClaudeAgentOptions #655

@panplumousse-star

Description

@panplumousse-star

Summary

The Anthropic Messages API supports a tool_choice parameter (auto, any, none, or force a specific tool by name), but the Agent SDK does not expose it in ClaudeAgentOptions.

Use case

When building autonomous agent pipelines, some workflows require an agent to always call a specific tool before finishing — e.g., a research agent that must persist its findings via a save_research_report MCP tool.

Currently, the only controls available are allowed_tools and disallowed_tools, which filter tool availability but don't force a tool call. The agent can still choose to respond with plain text instead of calling the required tool, which is non-deterministic and leads to lost work.

What happens today

result = await query(
    prompt="Research topic X and save findings",
    options=ClaudeAgentOptions(
        allowed_tools=["WebSearch", "WebFetch", "save_research_report"],
        # No way to force save_research_report to be called
    )
)
# Sometimes the agent calls save_research_report ✅
# Sometimes it just responds with text ❌ — findings are lost

What we'd like

result = await query(
    prompt="Research topic X and save findings",
    options=ClaudeAgentOptions(
        allowed_tools=["WebSearch", "WebFetch", "save_research_report"],
        tool_choice={"type": "tool", "name": "save_research_report"},
        # Or: tool_choice="any" to require at least one tool call
    )
)

Workarounds tried

  • Prompt reinforcement ("you MUST call this tool") — improves reliability but not deterministic
  • Post-processing validation + retry — works but wastes tokens/budget
  • Fallback extraction from raw response — lossy, degrades quality

Notes

  • The Messages API already supports this: tool_choice: auto | any | none | {type: "tool", name: "X"}
  • Known constraint: forced tool use (any/tool) is incompatible with extended thinking — this should be documented if exposed
  • Even partial support (e.g., tool_choice="any") would be valuable for mandatory-persistence workflows

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions