mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-09 19:27:54 +02:00
feat(prebuilt): expose available tools on ToolRuntime (#7512)
This commit is contained in:
@@ -808,6 +808,7 @@ class ToolNode(RunnableCallable):
|
||||
context=runtime.context,
|
||||
store=runtime.store,
|
||||
stream_writer=runtime.stream_writer,
|
||||
tools=list(self.tools_by_name.values()),
|
||||
execution_info=runtime.execution_info,
|
||||
server_info=runtime.server_info,
|
||||
)
|
||||
@@ -842,6 +843,7 @@ class ToolNode(RunnableCallable):
|
||||
context=runtime.context,
|
||||
store=runtime.store,
|
||||
stream_writer=runtime.stream_writer,
|
||||
tools=list(self.tools_by_name.values()),
|
||||
execution_info=runtime.execution_info,
|
||||
server_info=runtime.server_info,
|
||||
)
|
||||
@@ -1576,6 +1578,7 @@ class ToolRuntime(_DirectlyInjectedToolArg, Generic[ContextT, StateT]):
|
||||
- `context`: Runtime context (shared with `Runtime`)
|
||||
- `store`: `BaseStore` instance for persistent storage (shared with `Runtime`)
|
||||
- `stream_writer`: `StreamWriter` for streaming output (shared with `Runtime`)
|
||||
- `tools`: List of all available `BaseTool` instances
|
||||
|
||||
No `Annotated` wrapper is needed - just use `runtime: ToolRuntime`
|
||||
as a parameter.
|
||||
@@ -1618,6 +1621,7 @@ class ToolRuntime(_DirectlyInjectedToolArg, Generic[ContextT, StateT]):
|
||||
context: ContextT
|
||||
config: RunnableConfig
|
||||
stream_writer: StreamWriter
|
||||
tools: list[BaseTool]
|
||||
tool_call_id: str | None
|
||||
store: BaseStore | None
|
||||
execution_info: ExecutionInfo | None = None
|
||||
|
||||
@@ -69,6 +69,7 @@ def _create_config_with_runtime(store=None, state=None):
|
||||
context={},
|
||||
store=store,
|
||||
stream_writer=None,
|
||||
tools=[],
|
||||
tool_call_id="test_id",
|
||||
)
|
||||
return {
|
||||
|
||||
@@ -2016,8 +2016,8 @@ async def test_tool_node_inject_runtime_dynamic_tool_via_wrap_tool_call_async()
|
||||
assert tool_message.tool_call_id == "call_dynamic_2"
|
||||
|
||||
|
||||
def test_tool_runtime_forwards_execution_info_and_server_info() -> None:
|
||||
"""Test that execution_info and server_info are forwarded from Runtime to ToolRuntime."""
|
||||
def test_tool_runtime_forwards_execution_info_server_info_and_tools() -> None:
|
||||
"""Test that execution_info, server_info, and tools are forwarded from Runtime to ToolRuntime."""
|
||||
from langgraph.runtime import ExecutionInfo, ServerInfo
|
||||
|
||||
exec_info = ExecutionInfo(
|
||||
@@ -2043,9 +2043,15 @@ def test_tool_runtime_forwards_execution_info_and_server_info() -> None:
|
||||
"""Tool that captures runtime info."""
|
||||
captured["execution_info"] = runtime.execution_info
|
||||
captured["server_info"] = runtime.server_info
|
||||
captured["tools"] = runtime.tools
|
||||
return "ok"
|
||||
|
||||
node = ToolNode([info_tool])
|
||||
@dec_tool
|
||||
def other_tool(y: int) -> str:
|
||||
"""Another tool available to the runtime."""
|
||||
return str(y)
|
||||
|
||||
node = ToolNode([info_tool, other_tool])
|
||||
tool_call = {
|
||||
"name": "info_tool",
|
||||
"args": {"x": 1},
|
||||
@@ -2054,17 +2060,21 @@ def test_tool_runtime_forwards_execution_info_and_server_info() -> None:
|
||||
}
|
||||
msg = AIMessage("", tool_calls=[tool_call])
|
||||
config: RunnableConfig = {"configurable": {"__pregel_runtime": mock_runtime}}
|
||||
node.invoke({"messages": [msg]}, config=config)
|
||||
result = node.invoke({"messages": [msg]}, config=config)
|
||||
|
||||
assert result["messages"][-1].content == "ok"
|
||||
assert captured["execution_info"] is exec_info
|
||||
assert captured["execution_info"].thread_id == "t-1"
|
||||
assert captured["execution_info"].task_id == "tk-1"
|
||||
assert captured["server_info"] is server_info
|
||||
assert captured["server_info"].assistant_id == "asst-1"
|
||||
assert [tool.name for tool in captured["tools"]] == ["info_tool", "other_tool"]
|
||||
|
||||
|
||||
async def test_tool_runtime_forwards_execution_info_and_server_info_async() -> None:
|
||||
"""Test that execution_info and server_info are forwarded in async path."""
|
||||
async def test_tool_runtime_forwards_execution_info_server_info_and_tools_async() -> (
|
||||
None
|
||||
):
|
||||
"""Test that execution_info, server_info, and tools are forwarded in async path."""
|
||||
from langgraph.runtime import ExecutionInfo, ServerInfo
|
||||
|
||||
exec_info = ExecutionInfo(
|
||||
@@ -2090,9 +2100,15 @@ async def test_tool_runtime_forwards_execution_info_and_server_info_async() -> N
|
||||
"""Async tool that captures runtime info."""
|
||||
captured["execution_info"] = runtime.execution_info
|
||||
captured["server_info"] = runtime.server_info
|
||||
captured["tools"] = runtime.tools
|
||||
return "ok"
|
||||
|
||||
node = ToolNode([info_tool_async])
|
||||
@dec_tool
|
||||
async def other_tool_async(y: int) -> str:
|
||||
"""Another async tool available to the runtime."""
|
||||
return str(y)
|
||||
|
||||
node = ToolNode([info_tool_async, other_tool_async])
|
||||
tool_call = {
|
||||
"name": "info_tool_async",
|
||||
"args": {"x": 1},
|
||||
@@ -2101,12 +2117,17 @@ async def test_tool_runtime_forwards_execution_info_and_server_info_async() -> N
|
||||
}
|
||||
msg = AIMessage("", tool_calls=[tool_call])
|
||||
config: RunnableConfig = {"configurable": {"__pregel_runtime": mock_runtime}}
|
||||
await node.ainvoke({"messages": [msg]}, config=config)
|
||||
result = await node.ainvoke({"messages": [msg]}, config=config)
|
||||
|
||||
assert result["messages"][-1].content == "ok"
|
||||
assert captured["execution_info"] is exec_info
|
||||
assert captured["execution_info"].thread_id == "t-2"
|
||||
assert captured["server_info"] is server_info
|
||||
assert captured["server_info"].graph_id == "graph-2"
|
||||
assert [tool.name for tool in captured["tools"]] == [
|
||||
"info_tool_async",
|
||||
"other_tool_async",
|
||||
]
|
||||
|
||||
|
||||
# --- InjectedToolArg security tests ---
|
||||
|
||||
Reference in New Issue
Block a user