Skip to content

Anthropic provider: no way to set strict: true on tool schemas (needed for reliable tool calls with adaptive thinking) #4432

Description

@alexandrasouly-aisi

When using the anthropic provider with reasoning_effort set (i.e. adaptive thinking), tool_choice is intentionally not sent (_providers/anthropic.py around L410) — which is correct, since Anthropic's API disables extended thinking when tool_choice is {type: "tool"} or {type: "any"}; only auto yields both a thinking block and a tool call.

That means the only way to get both reasoning and a schema-guaranteed tool call on Anthropic is tool_choice: auto + strict: true on the tool definition (Anthropic supports this: https://docs.anthropic.com/en/docs/build-with-claude/tool-use#strict-tool-use). But AnthropicAPI.tool_params_for_tool_info hardcodes:

ToolParam(name=tool.name, description=tool.description, input_schema=json_schema_dump(tool.parameters))

with no strict field and no ToolInfo.options passthrough, so there's no way to opt in.

Repro (v0.3.220):

from inspect_ai.model import get_model, GenerateConfig
from inspect_ai.tool import ToolInfo, ToolParams, ToolFunction
from inspect_ai.util import json_schema
from pydantic import BaseModel

class Out(BaseModel):
    reasoning: str
    x: int

s = json_schema(Out)
tool = ToolInfo(
    name="emit", description="emit",
    parameters=ToolParams(properties=s.properties, required=s.required, additionalProperties=False),
)
m = get_model("anthropic/claude-sonnet-5", config=GenerateConfig(reasoning_effort="high"))
out = await m.generate("call emit with x=1", tools=[tool], tool_choice=ToolFunction(name="emit"))
# request sent has thinking:{type:adaptive}, tool_choice omitted (correctly),
# and the tool has no `strict` — so the model may return malformed/partial args

Proposed fix: honour ToolInfo.options["strict"] = True (or add a top-level ToolInfo.strict) in tool_params_for_tool_info, and drop minimum/maximum from input_schema when strict is set (Anthropic rejects those keywords under strict).

Happy to send a PR if this direction sounds right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions