diff --git a/src/rai_core/rai/agents/langchain/core/tool_runner.py b/src/rai_core/rai/agents/langchain/core/tool_runner.py index 216748e2d..4f7dc71c3 100644 --- a/src/rai_core/rai/agents/langchain/core/tool_runner.py +++ b/src/rai_core/rai/agents/langchain/core/tool_runner.py @@ -73,9 +73,20 @@ def run_one(call: ToolCall): self.logger.info(f"Running tool: {call['name']}, args: {call['args']}") artifact = None + tool = self.tools_by_name.get(call["name"]) + if tool is None: + error_message = f'Unknown tool: "{call["name"]}"' + self.logger.info(error_message) + return ToolMessage( + content=error_message, + name=call["name"], + tool_call_id=call["id"], + status="error", + ) + try: ts = time.perf_counter() - output = self.tools_by_name[call["name"]].invoke(call, config) # type: ignore + output = tool.invoke(call, config) # type: ignore te = time.perf_counter() - ts self.logger.info( f"Tool {call['name']} completed in {te:.2f} seconds. Tool output: {str(output.content)[:100]}{'...' if len(str(output.content)) > 100 else ''}" diff --git a/tests/agents/langchain/test_tool_runner_unknown.py b/tests/agents/langchain/test_tool_runner_unknown.py new file mode 100644 index 000000000..e8f5f01f9 --- /dev/null +++ b/tests/agents/langchain/test_tool_runner_unknown.py @@ -0,0 +1,20 @@ +# Copyright (C) 2026 Robotec.AI +from langchain_core.messages import AIMessage, ToolMessage + +from rai.agents.langchain.core.tool_runner import ToolRunner + + +def test_tool_runner_unknown_tool_returns_error_message(): + runner = ToolRunner(tools=[]) + ai = AIMessage( + content="", + tool_calls=[{"name": "missing_tool", "args": {}, "id": "call_1", "type": "tool_call"}], + ) + out = runner.invoke({"messages": [ai]}) + msgs = out["messages"] + assert len(msgs) == 2 + err = msgs[-1] + assert isinstance(err, ToolMessage) + assert err.status == "error" + assert "Unknown tool" in err.content + assert err.tool_call_id == "call_1"