fix: wire up enabled_tools in agent loop + simplify sandbox tool selection
Completes the fix started in 8318a51 — handle_function_call() accepted
enabled_tools but run_agent.py never passed it. Now both call sites in
_execute_tool_calls() pass self.valid_tool_names, so each agent session
uses its own tool list instead of the process-global
_last_resolved_tool_names (which subagents can overwrite).
Also simplifies the redundant ternary in code_execution_tool.py:
sandbox_tools is already computed correctly (intersection with session
tools, or full SANDBOX_ALLOWED_TOOLS as fallback), so the conditional
was dead logic.
Inspired by PR #663 (JasonOA888). Closes #662.
Tests: 2857 passed.
This commit is contained in:
10
run_agent.py
10
run_agent.py
@@ -2839,7 +2839,10 @@ class AIAgent:
|
||||
spinner.start()
|
||||
_spinner_result = None
|
||||
try:
|
||||
function_result = handle_function_call(function_name, function_args, effective_task_id)
|
||||
function_result = handle_function_call(
|
||||
function_name, function_args, effective_task_id,
|
||||
enabled_tools=list(self.valid_tool_names) if self.valid_tool_names else None,
|
||||
)
|
||||
_spinner_result = function_result
|
||||
except Exception as tool_error:
|
||||
function_result = f"Error executing tool '{function_name}': {tool_error}"
|
||||
@@ -2850,7 +2853,10 @@ class AIAgent:
|
||||
spinner.stop(cute_msg)
|
||||
else:
|
||||
try:
|
||||
function_result = handle_function_call(function_name, function_args, effective_task_id)
|
||||
function_result = handle_function_call(
|
||||
function_name, function_args, effective_task_id,
|
||||
enabled_tools=list(self.valid_tool_names) if self.valid_tool_names else None,
|
||||
)
|
||||
except Exception as tool_error:
|
||||
function_result = f"Error executing tool '{function_name}': {tool_error}"
|
||||
logger.error("handle_function_call raised for %s: %s", function_name, tool_error, exc_info=True)
|
||||
|
||||
@@ -601,7 +601,10 @@ class TestExecuteToolCalls:
|
||||
messages = []
|
||||
with patch("run_agent.handle_function_call", return_value="search result") as mock_hfc:
|
||||
agent._execute_tool_calls(mock_msg, messages, "task-1")
|
||||
mock_hfc.assert_called_once_with("web_search", {"q": "test"}, "task-1")
|
||||
# enabled_tools passes the agent's own valid_tool_names
|
||||
args, kwargs = mock_hfc.call_args
|
||||
assert args[:3] == ("web_search", {"q": "test"}, "task-1")
|
||||
assert set(kwargs.get("enabled_tools", [])) == agent.valid_tool_names
|
||||
assert len(messages) == 1
|
||||
assert messages[0]["role"] == "tool"
|
||||
assert "search result" in messages[0]["content"]
|
||||
@@ -627,7 +630,9 @@ class TestExecuteToolCalls:
|
||||
with patch("run_agent.handle_function_call", return_value="ok") as mock_hfc:
|
||||
agent._execute_tool_calls(mock_msg, messages, "task-1")
|
||||
# Invalid JSON args should fall back to empty dict
|
||||
mock_hfc.assert_called_once_with("web_search", {}, "task-1")
|
||||
args, kwargs = mock_hfc.call_args
|
||||
assert args[:3] == ("web_search", {}, "task-1")
|
||||
assert set(kwargs.get("enabled_tools", [])) == agent.valid_tool_names
|
||||
assert len(messages) == 1
|
||||
assert messages[0]["role"] == "tool"
|
||||
assert messages[0]["tool_call_id"] == "c1"
|
||||
|
||||
@@ -397,9 +397,9 @@ def execute_code(
|
||||
|
||||
try:
|
||||
# Write the auto-generated hermes_tools module
|
||||
tools_src = generate_hermes_tools_module(
|
||||
list(sandbox_tools) if enabled_tools else list(SANDBOX_ALLOWED_TOOLS)
|
||||
)
|
||||
# sandbox_tools is already the correct set (intersection with session
|
||||
# tools, or SANDBOX_ALLOWED_TOOLS as fallback — see lines above).
|
||||
tools_src = generate_hermes_tools_module(list(sandbox_tools))
|
||||
with open(os.path.join(tmpdir, "hermes_tools.py"), "w") as f:
|
||||
f.write(tools_src)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user