diff --git a/nanobot/agent/loop.py b/nanobot/agent/loop.py index 63ee92ca5..e4f4ec991 100644 --- a/nanobot/agent/loop.py +++ b/nanobot/agent/loop.py @@ -33,7 +33,7 @@ from nanobot.providers.base import LLMProvider from nanobot.session.manager import Session, SessionManager if TYPE_CHECKING: - from nanobot.config.schema import ChannelsConfig, ExecToolConfig, WebSearchConfig + from nanobot.config.schema import ChannelsConfig, ExecToolConfig, WebToolsConfig from nanobot.cron.service import CronService @@ -59,8 +59,7 @@ class AgentLoop: model: str | None = None, max_iterations: int = 40, context_window_tokens: int = 65_536, - web_search_config: WebSearchConfig | None = None, - web_proxy: str | None = None, + web_config: WebToolsConfig | None = None, exec_config: ExecToolConfig | None = None, cron_service: CronService | None = None, restrict_to_workspace: bool = False, @@ -69,7 +68,7 @@ class AgentLoop: channels_config: ChannelsConfig | None = None, timezone: str | None = None, ): - from nanobot.config.schema import ExecToolConfig, WebSearchConfig + from nanobot.config.schema import ExecToolConfig, WebToolsConfig self.bus = bus self.channels_config = channels_config @@ -78,8 +77,7 @@ class AgentLoop: self.model = model or provider.get_default_model() self.max_iterations = max_iterations self.context_window_tokens = context_window_tokens - self.web_search_config = web_search_config or WebSearchConfig() - self.web_proxy = web_proxy + self.web_config = web_config or WebToolsConfig() self.exec_config = exec_config or ExecToolConfig() self.cron_service = cron_service self.restrict_to_workspace = restrict_to_workspace @@ -95,8 +93,7 @@ class AgentLoop: workspace=workspace, bus=bus, model=self.model, - web_search_config=self.web_search_config, - web_proxy=web_proxy, + web_config=self.web_config, exec_config=self.exec_config, restrict_to_workspace=restrict_to_workspace, ) @@ -142,8 +139,9 @@ class AgentLoop: restrict_to_workspace=self.restrict_to_workspace, path_append=self.exec_config.path_append, )) - self.tools.register(WebSearchTool(config=self.web_search_config, proxy=self.web_proxy)) - self.tools.register(WebFetchTool(proxy=self.web_proxy)) + if self.web_config.enable: + self.tools.register(WebSearchTool(config=self.web_config.search, proxy=self.web_config.proxy)) + self.tools.register(WebFetchTool(proxy=self.web_config.proxy)) self.tools.register(MessageTool(send_callback=self.bus.publish_outbound)) self.tools.register(SpawnTool(manager=self.subagents)) if self.cron_service: diff --git a/nanobot/agent/subagent.py b/nanobot/agent/subagent.py index 5266fc8b1..6487bc11c 100644 --- a/nanobot/agent/subagent.py +++ b/nanobot/agent/subagent.py @@ -17,7 +17,7 @@ from nanobot.agent.tools.shell import ExecTool from nanobot.agent.tools.web import WebFetchTool, WebSearchTool from nanobot.bus.events import InboundMessage from nanobot.bus.queue import MessageBus -from nanobot.config.schema import ExecToolConfig +from nanobot.config.schema import ExecToolConfig, WebToolsConfig from nanobot.providers.base import LLMProvider @@ -30,8 +30,7 @@ class SubagentManager: workspace: Path, bus: MessageBus, model: str | None = None, - web_search_config: "WebSearchConfig | None" = None, - web_proxy: str | None = None, + web_config: "WebToolsConfig | None" = None, exec_config: "ExecToolConfig | None" = None, restrict_to_workspace: bool = False, ): @@ -41,8 +40,7 @@ class SubagentManager: self.workspace = workspace self.bus = bus self.model = model or provider.get_default_model() - self.web_search_config = web_search_config or WebSearchConfig() - self.web_proxy = web_proxy + self.web_config = web_config or WebToolsConfig() self.exec_config = exec_config or ExecToolConfig() self.restrict_to_workspace = restrict_to_workspace self.runner = AgentRunner(provider) @@ -100,14 +98,16 @@ class SubagentManager: tools.register(WriteFileTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(EditFileTool(workspace=self.workspace, allowed_dir=allowed_dir)) tools.register(ListDirTool(workspace=self.workspace, allowed_dir=allowed_dir)) - tools.register(ExecTool( - working_dir=str(self.workspace), - timeout=self.exec_config.timeout, - restrict_to_workspace=self.restrict_to_workspace, - path_append=self.exec_config.path_append, - )) - tools.register(WebSearchTool(config=self.web_search_config, proxy=self.web_proxy)) - tools.register(WebFetchTool(proxy=self.web_proxy)) + if self.exec_config.enable: + tools.register(ExecTool( + working_dir=str(self.workspace), + timeout=self.exec_config.timeout, + restrict_to_workspace=self.restrict_to_workspace, + path_append=self.exec_config.path_append, + )) + if self.web_config.enable: + tools.register(WebSearchTool(config=self.web_config.search, proxy=self.web_config.proxy)) + tools.register(WebFetchTool(proxy=self.web_config.proxy)) system_prompt = self._build_subagent_prompt() messages: list[dict[str, Any]] = [ diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index cacb61ae6..c3727d319 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -541,8 +541,7 @@ def gateway( model=config.agents.defaults.model, max_iterations=config.agents.defaults.max_tool_iterations, context_window_tokens=config.agents.defaults.context_window_tokens, - web_search_config=config.tools.web.search, - web_proxy=config.tools.web.proxy or None, + web_config=config.tools.web, exec_config=config.tools.exec, cron_service=cron, restrict_to_workspace=config.tools.restrict_to_workspace, @@ -747,8 +746,7 @@ def agent( model=config.agents.defaults.model, max_iterations=config.agents.defaults.max_tool_iterations, context_window_tokens=config.agents.defaults.context_window_tokens, - web_search_config=config.tools.web.search, - web_proxy=config.tools.web.proxy or None, + web_config=config.tools.web, exec_config=config.tools.exec, cron_service=cron, restrict_to_workspace=config.tools.restrict_to_workspace, diff --git a/nanobot/config/schema.py b/nanobot/config/schema.py index c8b69b42e..1978a17c8 100644 --- a/nanobot/config/schema.py +++ b/nanobot/config/schema.py @@ -107,7 +107,7 @@ class GatewayConfig(Base): class WebSearchConfig(Base): """Web search tool configuration.""" - provider: str = "brave" # brave, tavily, duckduckgo, searxng, jina + provider: str = "duckduckgo" # brave, tavily, duckduckgo, searxng, jina api_key: str = "" base_url: str = "" # SearXNG base URL max_results: int = 5 @@ -116,6 +116,7 @@ class WebSearchConfig(Base): class WebToolsConfig(Base): """Web tools configuration.""" + enable: bool = True proxy: str | None = ( None # HTTP/SOCKS5 proxy URL, e.g. "http://127.0.0.1:7890" or "socks5://127.0.0.1:1080" )