diff --git a/nanobot/agent/subagent.py b/nanobot/agent/subagent.py index bced6fde..394292c8 100644 --- a/nanobot/agent/subagent.py +++ b/nanobot/agent/subagent.py @@ -170,6 +170,7 @@ class SubagentManager: restrict_to_workspace=self.restrict_to_workspace, sandbox=self.exec_config.sandbox, path_append=self.exec_config.path_append, + allowed_env_keys=self.exec_config.allowed_env_keys, )) if self.web_config.enable: tools.register(WebSearchTool(config=self.web_config.search, proxy=self.web_config.proxy)) diff --git a/tests/agent/tools/test_subagent_tools.py b/tests/agent/tools/test_subagent_tools.py new file mode 100644 index 00000000..045d5a45 --- /dev/null +++ b/tests/agent/tools/test_subagent_tools.py @@ -0,0 +1,53 @@ +"""Tests for subagent tool registration and wiring.""" + +import time +from types import SimpleNamespace +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from nanobot.config.schema import AgentDefaults + +_MAX_TOOL_RESULT_CHARS = AgentDefaults().max_tool_result_chars + + +@pytest.mark.asyncio +async def test_subagent_exec_tool_receives_allowed_env_keys(tmp_path): + """allowed_env_keys from ExecToolConfig must be forwarded to the subagent's ExecTool.""" + from nanobot.agent.subagent import SubagentManager, SubagentStatus + from nanobot.bus.queue import MessageBus + from nanobot.config.schema import ExecToolConfig + + bus = MessageBus() + provider = MagicMock() + provider.get_default_model.return_value = "test-model" + mgr = SubagentManager( + provider=provider, + workspace=tmp_path, + bus=bus, + max_tool_result_chars=_MAX_TOOL_RESULT_CHARS, + exec_config=ExecToolConfig(allowed_env_keys=["GOPATH", "JAVA_HOME"]), + ) + mgr._announce_result = AsyncMock() + + async def fake_run(spec): + exec_tool = spec.tools.get("exec") + assert exec_tool is not None + assert exec_tool.allowed_env_keys == ["GOPATH", "JAVA_HOME"] + return SimpleNamespace( + stop_reason="done", + final_content="done", + error=None, + tool_events=[], + ) + + mgr.runner.run = AsyncMock(side_effect=fake_run) + + status = SubagentStatus( + task_id="sub-1", label="label", task_description="do task", started_at=time.monotonic() + ) + await mgr._run_subagent( + "sub-1", "do task", "label", {"channel": "test", "chat_id": "c1"}, status + ) + + mgr.runner.run.assert_awaited_once()