langchain - ✅(Solved) Fix LangChain v1.1-1.12 create_agent with response_format hardcodes tool_choice="any" for structured output tool, breaking Anthropic thinking + structured output. [3 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langchain-ai/langchain#35539Fetched 2026-04-08 00:25:46
View on GitHub
Comments
1
Participants
2
Timeline
14
Reactions
0
Timeline (top)
cross-referenced ×4labeled ×4referenced ×2closed ×1

create_agent(model, ..., response_format=Schema) converts structured output to a tool call with tool_choice="any".

Anthropic rejects this with "Thinking may not be enabled when tool_choice forces tool use" when model has thinking={"type": "enabled"}.

Expected: Use provider native structured output (with_structured_output(method="anthropic_json_mode")) or tool_choice="auto".

Actual: Forces tool-based structured output with tool_choice="any".

Error Message

Error Message and Stack Trace (if applicable)

Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'Thinking may not be enabled when tool_choice forces tool use.'}, 'request_id': 'req_011CYggXHSpHGThY9So9qSzy'} Error: 400: 'Thinking may not be enabled when tool_choice forces tool use.'

Root Cause

create_agent(model, ..., response_format=Schema) converts structured output to a tool call with tool_choice="any".

Anthropic rejects this with "Thinking may not be enabled when tool_choice forces tool use" when model has thinking={"type": "enabled"}.

Expected: Use provider native structured output (with_structured_output(method="anthropic_json_mode")) or tool_choice="auto".

Actual: Forces tool-based structured output with tool_choice="any".

Fix Action

Workaround

Manual LangGraph or llm.with_structured_output(Result, method="anthropic_json_mode").

PR fix notes

PR #35544: fix(anthropic): drop forced tool_choice when thinking is enabled

Description (problem / solution / changelog)

Description

Fixes #35539.

ChatAnthropic.bind_tools() now detects when thinking mode is active and tool_choice forces tool use ("any" or a specific tool name). In that case it drops the forced tool_choice and emits a warning, preventing the Anthropic API error: "Thinking may not be enabled when tool_choice forces tool use."

This matches the existing behavior in _get_llm_for_structured_output_when_thinking_is_enabled (line 1451), which already omits tool_choice for the same reason when called via with_structured_output(). The gap was that bind_tools() had no such guard, so callers like create_agent with ToolStrategy would pass tool_choice="any" through to the API.

Changes

  • langchain_anthropic/chat_models.py: After tool_choice normalization in bind_tools(), check self.thinking is enabled and tool_choice type is "any" or "tool". If so, delete tool_choice from kwargs and warn.
  • tests/unit_tests/test_chat_models.py: 8 test cases covering all forced tool_choice variants (string and dict), auto passthrough, and thinking-disabled/None/absent passthrough.

Issue

When using create_agent(model, response_format=Schema) with a ChatAnthropic model that has thinking={"type": "enabled"}, the agent sends tool_choice="any" to the Anthropic API, which rejects it with a 400 error.

Test plan

  • test_bind_tools_drops_forced_tool_choice_when_thinking_enabled — verifies all forced variants are dropped with warning
  • test_bind_tools_keeps_forced_tool_choice_when_thinking_disabled — verifies no regression for non-thinking usage
  • Existing test_anthropic_bind_tools_tool_choice — verifies no regression on standard tool_choice behavior

Changed files

  • libs/partners/anthropic/langchain_anthropic/chat_models.py (modified, +20/-0)
  • libs/partners/anthropic/tests/unit_tests/test_chat_models.py (modified, +87/-0)

PR #35551: fix(anthropic): downgrade tool_choice when thinking is enabled

Description (problem / solution / changelog)

Summary

  • create_agent(model, response_format=Schema) with a thinking-enabled Anthropic model crashes with 400: "Thinking may not be enabled when tool_choice forces tool use" because the factory sets tool_choice="any" for structured output
  • ChatAnthropic.bind_tools now detects when thinking is enabled and tool_choice forces tool use ("any" or a specific tool name), and downgrades to "auto" with a warning
  • This matches the approach already used by ChatAnthropic.with_structured_output (via _get_llm_for_structured_output_when_thinking_is_enabled)

Files changed

  • libs/partners/anthropic/langchain_anthropic/chat_models.py — 8 lines in bind_tools() to detect and downgrade forced tool_choice when thinking is enabled
  • libs/partners/anthropic/tests/unit_tests/test_chat_models.py — 2 test functions covering downgrade behavior + warning emission, and pass-through without thinking

Test plan

  • test_bind_tools_tool_choice_downgraded_when_thinking_enabled — verifies "any" and named tool choice are downgraded to "auto" with warning; "auto" and None are unchanged without warning
  • test_bind_tools_tool_choice_not_downgraded_without_thinking — verifies "any" and named tool choice pass through unchanged when thinking is not enabled
  • Existing test_anthropic_bind_tools_tool_choice still passes
  • Full anthropic unit test suite: 77 passed, 0 failed

Closes #35539

🤖 Generated with Claude Code

Changed files

  • libs/partners/anthropic/langchain_anthropic/chat_models.py (modified, +16/-0)
  • libs/partners/anthropic/tests/unit_tests/test_chat_models.py (modified, +56/-0)

PR #35564: fix(langchain): avoid hardcoding tool_choice='any' in create_agent when thinking is enabled

Description (problem / solution / changelog)

Summary

  • create_agent with response_format hardcodes tool_choice="any" when using ToolStrategy, which causes Anthropic's API to reject requests with 400: "Thinking may not be enabled when tool_choice forces tool use"
  • Adds a _has_thinking_enabled() helper that detects when a model has thinking/reasoning actively enabled (Anthropic thinking param, OpenAI/DeepSeek reasoning_effort param)
  • When thinking is enabled, falls back to tool_choice="auto" instead of "any" — the model can still voluntarily call the structured output tool, but the API constraint is respected
  • Default behavior (tool_choice="any") is preserved for all models without thinking enabled

Fixes #35539

Test plan

  • Added 7 unit tests for _has_thinking_enabled() helper covering: Anthropic thinking enabled/adaptive/disabled/None, no thinking attribute, OpenAI reasoning_effort set/None
  • Added 2 integration tests for TestToolChoiceWithThinking verifying: tool_choice="auto" when thinking is enabled, tool_choice="any" preserved when thinking is not enabled
  • All 38 tests in test_response_format.py pass (29 existing + 9 new)
  • Full agents test suite (725 tests) passes with zero regressions

🤖 Generated with Claude Code

Changed files

  • libs/langchain_v1/langchain/agents/factory.py (modified, +34/-2)
  • libs/langchain_v1/tests/unit_tests/agents/test_response_format.py (modified, +129/-1)

Code Example

from langchain_anthropic import ChatAnthropic
from pydantic_v1 import BaseModel, Field
from langchain.agents import create_agent

class Result(BaseModel):
    answer: str = Field(description="Final answer")

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20241022",
    thinking={"type": "enabled", "budget_tokens": 5000}
)

agent = create_agent(llm, tools=[], response_format=Result, system_prompt="Answer directly.")
agent.invoke({"messages": [{"role": "user", "content": "What is 2+2?"}]})

---

Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'Thinking may not be enabled when tool_choice forces tool use.'}, 'request_id': 'req_011CYggXHSpHGThY9So9qSzy'}

---

from langchain_anthropic import ChatAnthropic
from pydantic_v1 import BaseModel, Field
from langchain.agents import create_agent

class Result(BaseModel):
    answer: str = Field(description="Final answer")

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20241022",
    thinking={"type": "enabled", "budget_tokens": 5000}
)

agent = create_agent(llm, tools=[], response_format=Result, system_prompt="Answer directly.")
agent.invoke({"messages": [{"role": "user", "content": "What is 2+2?"}]})
RAW_BUFFERClick to expand / collapse

Checked other resources

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package (Required)

  • langchain
  • langchain-openai
  • langchain-anthropic
  • langchain-classic
  • langchain-core
  • langchain-model-profiles
  • langchain-tests
  • langchain-text-splitters
  • langchain-chroma
  • langchain-deepseek
  • langchain-exa
  • langchain-fireworks
  • langchain-groq
  • langchain-huggingface
  • langchain-mistralai
  • langchain-nomic
  • langchain-ollama
  • langchain-openrouter
  • langchain-perplexity
  • langchain-qdrant
  • langchain-xai
  • Other / not sure / general

Related Issues / PRs

No response

Reproduction Steps / Example Code (Python)

from langchain_anthropic import ChatAnthropic
from pydantic_v1 import BaseModel, Field
from langchain.agents import create_agent

class Result(BaseModel):
    answer: str = Field(description="Final answer")

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20241022",
    thinking={"type": "enabled", "budget_tokens": 5000}
)

agent = create_agent(llm, tools=[], response_format=Result, system_prompt="Answer directly.")
agent.invoke({"messages": [{"role": "user", "content": "What is 2+2?"}]})

Error Message and Stack Trace (if applicable)

Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'Thinking may not be enabled when tool_choice forces tool use.'}, 'request_id': 'req_011CYggXHSpHGThY9So9qSzy'}

Description

create_agent(model, ..., response_format=Schema) converts structured output to a tool call with tool_choice="any".

Anthropic rejects this with "Thinking may not be enabled when tool_choice forces tool use" when model has thinking={"type": "enabled"}.

Expected: Use provider native structured output (with_structured_output(method="anthropic_json_mode")) or tool_choice="auto".

Actual: Forces tool-based structured output with tool_choice="any".

Reproduction

from langchain_anthropic import ChatAnthropic
from pydantic_v1 import BaseModel, Field
from langchain.agents import create_agent

class Result(BaseModel):
    answer: str = Field(description="Final answer")

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20241022",
    thinking={"type": "enabled", "budget_tokens": 5000}
)

agent = create_agent(llm, tools=[], response_format=Result, system_prompt="Answer directly.")
agent.invoke({"messages": [{"role": "user", "content": "What is 2+2?"}]})

Error: 400: 'Thinking may not be enabled when tool_choice forces tool use.'

Environment

  • langchain==1.1.x
  • langchain-anthropic==0.x.x

Workaround

Manual LangGraph or llm.with_structured_output(Result, method="anthropic_json_mode").

Source

create_agent → structured output → tool binding → tool_choice="any".

Fix: Add provider_strategy="anthropic_json_mode" or detect thinking param → skip tool-based structured output.

System Info

ystem Information

OS: Linux OS Version: #91-Ubuntu SMP PREEMPT_DYNAMIC Tue Nov 18 14:14:30 UTC 2025 Python Version: 3.13.11 (main, Dec 9 2025, 02:03:30) [GCC 12.2.0]

Package Information

langchain_core: 1.2.17 langchain: 1.2.10 langchain_community: 0.4 langsmith: 0.4.37 langchain_anthropic: 1.3.4 langchain_classic: 1.0.0 langchain_google_genai: 4.2.0 langchain_google_vertexai: 3.2.1 langchain_openai: 1.0.1 langchain_postgres: 0.0.16 langchain_text_splitters: 1.0.0 langgraph_sdk: 0.3.9

Optional packages not installed

deepagents deepagents-cli

Other Dependencies

aiohttp: 3.13.0 anthropic: 0.84.0 asyncpg: 0.31.0 bottleneck: 1.6.0 dataclasses-json: 0.6.7 filetype: 1.2.0 google-cloud-aiplatform: 1.134.0 google-cloud-storage: 3.8.0 google-genai: 1.60.0 httpx: 0.28.1 httpx-sse: 0.4.3 jsonpatch: 1.33 langgraph: 1.0.10 numexpr: 2.14.1 numpy: 2.3.4 openai: 2.14.0 openai-agents: 0.4.1 orjson: 3.11.5 packaging: 25.0 pgvector: 0.3.6 psycopg: 3.2.11 psycopg-pool: 3.3.0 pyarrow: 22.0.0 pydantic: 2.12.3 pydantic-settings: 2.12.0 pytest: 8.4.2 PyYAML: 6.0.3 pyyaml: 6.0.3 requests: 2.32.5 requests-toolbelt: 1.0.0 rich: 14.2.0 SQLAlchemy: 2.0.44 sqlalchemy: 2.0.44 tenacity: 9.1.2 tiktoken: 0.12.0 typing-extensions: 4.15.0 uuid-utils: 0.14.0 validators: 0.35.0 zstandard: 0.25.0

extent analysis

Problem Summary

The issue is caused by a conflict between the thinking parameter and the tool_choice parameter when creating an agent with LangChain.

Root Cause Analysis

The root cause is that the create_agent function forces tool-based structured output when tool_choice is set to "any", but the Anthropic provider does not support thinking when tool choice is forced.

Fix Plan

To fix this issue, you can use one of the following solutions:

1. Use provider_strategy="anthropic_json_mode"

llm = ChatAnthropic(
    model="claude-3-5-sonnet-20241022",
    thinking={"type": "enabled", "budget_tokens": 5000}
)

llm = llm.with_structured_output(Result, method="anthropic_json_mode")
agent = create_agent(llm, tools=[], response_format=Result, system_prompt="Answer directly.")

2. Detect thinking param and skip tool-based structured output

if llm.thinking and llm.thinking["type"] == "enabled":
    response_format = llm.with_structured_output(Result, method="anthropic_json_mode")
else:
    response_format = Result
agent = create_agent(llm, tools=[], response_format=response_format, system_prompt="Answer directly.")

Verification

To verify that the fix worked, you can run the reproduction code again and check if the error message is resolved.

Extra Tips

  • Make sure to update the langchain and langchain-anthropic packages to the latest versions.
  • If you are using a custom provider, make sure to implement the with_structured_output method correctly.
  • Consider using the provider_strategy parameter to specify the structured output method for each provider.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

langchain - ✅(Solved) Fix LangChain v1.1-1.12 create_agent with response_format hardcodes tool_choice="any" for structured output tool, breaking Anthropic thinking + structured output. [3 pull requests, 1 comments, 2 participants]