From 87d432e1c7fb1dadff24e2742d8b8cf52816fc9f Mon Sep 17 00:00:00 2001 From: Sydney Runkle Date: Thu, 13 Nov 2025 10:01:44 -0500 Subject: [PATCH] Revert changes to keep only chat_agent_executor modifications --- .../langgraph/_internal/_runnable.py | 7 +--- libs/prebuilt/langgraph/prebuilt/tool_node.py | 5 ++- libs/prebuilt/tests/test_tool_node.py | 34 ++++++++++--------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/libs/langgraph/langgraph/_internal/_runnable.py b/libs/langgraph/langgraph/_internal/_runnable.py index 0e51c4286..63e03f544 100644 --- a/libs/langgraph/langgraph/_internal/_runnable.py +++ b/libs/langgraph/langgraph/_internal/_runnable.py @@ -316,12 +316,7 @@ class RunnableCallable(Runnable): continue # If the kwarg is accepted by the function, store the key / runtime attribute to inject - # Use the actual parameter default from the function signature if available, - # otherwise fall back to the default from KWARGS_CONFIG_KEYS - param_default = ( - p.default if p.default is not inspect.Parameter.empty else default - ) - self.func_accepts[kw] = (runtime_key, param_default) + self.func_accepts[kw] = (runtime_key, default) def __repr__(self) -> str: repr_args = { diff --git a/libs/prebuilt/langgraph/prebuilt/tool_node.py b/libs/prebuilt/langgraph/prebuilt/tool_node.py index a42e5ea70..c287743dd 100644 --- a/libs/prebuilt/langgraph/prebuilt/tool_node.py +++ b/libs/prebuilt/langgraph/prebuilt/tool_node.py @@ -84,7 +84,6 @@ from langchain_core.tools.base import ( from langgraph._internal._runnable import RunnableCallable from langgraph.errors import GraphBubbleUp from langgraph.graph.message import REMOVE_ALL_MESSAGES -from langgraph.runtime import DEFAULT_RUNTIME from langgraph.store.base import BaseStore # noqa: TC002 from langgraph.types import Command, Send, StreamWriter from pydantic import BaseModel, ValidationError @@ -703,7 +702,7 @@ class ToolNode(RunnableCallable): self, input: list[AnyMessage] | dict[str, Any] | BaseModel, config: RunnableConfig, - runtime: Runtime = DEFAULT_RUNTIME, + runtime: Runtime, ) -> Any: tool_calls, input_type = self._parse_input(input) config_list = get_config_list(config, len(tool_calls)) @@ -735,7 +734,7 @@ class ToolNode(RunnableCallable): self, input: list[AnyMessage] | dict[str, Any] | BaseModel, config: RunnableConfig, - runtime: Runtime = DEFAULT_RUNTIME, + runtime: Runtime, ) -> Any: tool_calls, input_type = self._parse_input(input) config_list = get_config_list(config, len(tool_calls)) diff --git a/libs/prebuilt/tests/test_tool_node.py b/libs/prebuilt/tests/test_tool_node.py index 60a0c8ea8..a97bd1565 100644 --- a/libs/prebuilt/tests/test_tool_node.py +++ b/libs/prebuilt/tests/test_tool_node.py @@ -9,6 +9,7 @@ from typing import ( NoReturn, TypeVar, ) +from unittest.mock import Mock import pytest from langchain_core.messages import ( @@ -50,26 +51,27 @@ from .model import FakeToolCallingModel pytestmark = pytest.mark.anyio +def _create_mock_runtime(store: BaseStore | None = None) -> Mock: + """Create a mock Runtime object for testing ToolNode outside of graph context. + + This helper is needed because ToolNode._func expects a Runtime parameter + which is injected by RunnableCallable from config["configurable"]["__pregel_runtime"]. + When testing ToolNode directly (outside a graph), we need to provide this manually. + """ + mock_runtime = Mock() + mock_runtime.store = store + mock_runtime.context = None + mock_runtime.stream_writer = lambda *args, **kwargs: None + return mock_runtime + + def _create_config_with_runtime(store: BaseStore | None = None) -> RunnableConfig: - """Create a RunnableConfig for testing ToolNode. - - Since ToolNode now has a default Runtime, this helper can be simplified. - It only needs to inject a store if one is provided, otherwise an empty config works. - - Args: - store: Optional store to inject via runtime. If None, no runtime is needed. + """Create a RunnableConfig with mock Runtime for testing ToolNode. Returns: - RunnableConfig, optionally with __pregel_runtime if store is provided. + RunnableConfig with __pregel_runtime in configurable dict. """ - if store is None: - # No runtime needed - ToolNode will use DEFAULT_RUNTIME - return {} - - # Create a mock runtime only when we need to inject a store - from langgraph.runtime import Runtime - runtime = Runtime(context=None, store=store, stream_writer=lambda *args, **kwargs: None) - return {"configurable": {"__pregel_runtime": runtime}} + return {"configurable": {"__pregel_runtime": _create_mock_runtime(store)}} def tool1(some_val: int, some_other_val: str) -> str: