mirror of
https://github.com/hwchase17/langchain.git
synced 2026-07-01 14:47:02 +00:00
feat(openrouter): surface parallel_tool_calls on bind_tools (#38214)
`ChatOpenRouter.bind_tools()` now accepts a `parallel_tool_calls` argument to disable parallel tool use. --- Users binding tools to `ChatOpenRouter` previously had to know that arbitrary kwargs were forwarded to the OpenRouter SDK in order to disable parallel tool use (e.g. `model.bind(parallel_tool_calls=False)`). This made the option hard to discover. This exposes `parallel_tool_calls` as an explicit keyword-only argument on `ChatOpenRouter.bind_tools()`, matching the ergonomics of `langchain-openai`. When set, it is forwarded to the request exactly as before; when left as `None` it is omitted, preserving existing behavior. No change to the underlying request payload or SDK floor — purely an API/discoverability improvement. Made by [Open SWE](https://openswe.vercel.app/agents/053b59c8-baf4-84e1-c003-425e349e014d) Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
@@ -837,6 +837,7 @@ class ChatOpenRouter(BaseChatModel):
|
||||
*,
|
||||
tool_choice: dict | str | bool | None = None,
|
||||
strict: bool | None = None,
|
||||
parallel_tool_calls: bool | None = None,
|
||||
**kwargs: Any,
|
||||
) -> Runnable[LanguageModelInput, AIMessage]:
|
||||
"""Bind tool-like objects to this chat model.
|
||||
@@ -852,8 +853,13 @@ class ChatOpenRouter(BaseChatModel):
|
||||
|
||||
If `None`, the `strict` argument will not be passed to
|
||||
the model.
|
||||
parallel_tool_calls: Set to `False` to disable parallel tool use.
|
||||
Defaults to `None` (no specification, which allows parallel
|
||||
tool use).
|
||||
**kwargs: Any additional parameters.
|
||||
"""
|
||||
if parallel_tool_calls is not None:
|
||||
kwargs["parallel_tool_calls"] = parallel_tool_calls
|
||||
formatted_tools = [
|
||||
convert_to_openai_tool(tool, strict=strict) for tool in tools
|
||||
]
|
||||
|
||||
@@ -1044,6 +1044,20 @@ class TestBindTools:
|
||||
tools = bound.kwargs["tools"]
|
||||
assert "strict" not in tools[0]["function"]
|
||||
|
||||
def test_bind_tools_parallel_tool_calls_forwarded(self) -> None:
|
||||
"""Test that parallel_tool_calls is forwarded to the request kwargs."""
|
||||
model = _make_model()
|
||||
bound = model.bind_tools([GetWeather], parallel_tool_calls=False)
|
||||
assert isinstance(bound, RunnableBinding)
|
||||
assert bound.kwargs["parallel_tool_calls"] is False
|
||||
|
||||
def test_bind_tools_parallel_tool_calls_none_omits_key(self) -> None:
|
||||
"""Test that parallel_tool_calls=None does not set the key in kwargs."""
|
||||
model = _make_model()
|
||||
bound = model.bind_tools([GetWeather])
|
||||
assert isinstance(bound, RunnableBinding)
|
||||
assert "parallel_tool_calls" not in bound.kwargs
|
||||
|
||||
|
||||
# ===========================================================================
|
||||
# with_structured_output tests
|
||||
|
||||
Reference in New Issue
Block a user