From 66103c68f62c3b07c4dc1471ee0a8e6804e3a2a7 Mon Sep 17 00:00:00 2001 From: CREDO23 Date: Thu, 4 Jun 2026 19:10:48 +0200 Subject: [PATCH] refactor(agents): colocate main-agent-only tools (scrape_webpage, update_memory) These two tools were "shared-by-folder, not shared-by-use": the only live consumer of shared/tools/{scrape_webpage,update_memory} was the main agent (the research/memory subagents carry their own local copies; web_search, by contrast, is genuinely shared with anonymous_chat and stays put). Move both into main_agent/tools/ (their sole owner). The shared BUILTIN_TOOLS catalog still lists them for action_log/revert + /agent/tools, now via deferred-import factories (_build_scrape_webpage_tool, _build_update_memory_tool) mirroring the create_automation precedent to avoid a multi_agent_chat import cycle. Removed the now-dead re-exports from shared/tools/__init__.py. Verified: full unit suite green (2431 passed, 1 skipped). --- .../main_agent/tools/registry.py | 9 ++-- .../main_agent}/tools/scrape_webpage.py | 0 .../main_agent}/tools/update_memory.py | 0 .../app/agents/shared/tools/__init__.py | 7 --- .../app/agents/shared/tools/registry.py | 50 ++++++++++++------- 5 files changed, 37 insertions(+), 29 deletions(-) rename surfsense_backend/app/agents/{shared => multi_agent_chat/main_agent}/tools/scrape_webpage.py (100%) rename surfsense_backend/app/agents/{shared => multi_agent_chat/main_agent}/tools/update_memory.py (100%) diff --git a/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/registry.py b/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/registry.py index 9f335aae1..2fc79fb14 100644 --- a/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/registry.py +++ b/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/registry.py @@ -23,13 +23,14 @@ from typing import Any from langchain_core.tools import BaseTool -from app.agents.shared.tools.scrape_webpage import create_scrape_webpage_tool -from app.agents.shared.tools.update_memory import ( +from app.agents.shared.tools.web_search import create_web_search_tool +from app.db import ChatVisibility + +from .scrape_webpage import create_scrape_webpage_tool +from .update_memory import ( create_update_memory_tool, create_update_team_memory_tool, ) -from app.agents.shared.tools.web_search import create_web_search_tool -from app.db import ChatVisibility def _build_scrape_webpage_tool(deps: dict[str, Any]) -> BaseTool: diff --git a/surfsense_backend/app/agents/shared/tools/scrape_webpage.py b/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/scrape_webpage.py similarity index 100% rename from surfsense_backend/app/agents/shared/tools/scrape_webpage.py rename to surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/scrape_webpage.py diff --git a/surfsense_backend/app/agents/shared/tools/update_memory.py b/surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/update_memory.py similarity index 100% rename from surfsense_backend/app/agents/shared/tools/update_memory.py rename to surfsense_backend/app/agents/multi_agent_chat/main_agent/tools/update_memory.py diff --git a/surfsense_backend/app/agents/shared/tools/__init__.py b/surfsense_backend/app/agents/shared/tools/__init__.py index 4b5ae3706..82bb96cf6 100644 --- a/surfsense_backend/app/agents/shared/tools/__init__.py +++ b/surfsense_backend/app/agents/shared/tools/__init__.py @@ -8,8 +8,6 @@ Available tools: - generate_podcast: Generate audio podcasts from content - generate_video_presentation: Generate video presentations with slides and narration - generate_image: Generate images from text descriptions using AI models -- scrape_webpage: Extract content from webpages -- update_memory: Update the user's / team's memory document """ # Registry exports @@ -29,8 +27,6 @@ from .registry import ( get_default_enabled_tools, get_tool_by_name, ) -from .scrape_webpage import create_scrape_webpage_tool -from .update_memory import create_update_memory_tool, create_update_team_memory_tool from .video_presentation import create_generate_video_presentation_tool __all__ = [ @@ -44,9 +40,6 @@ __all__ = [ "create_generate_image_tool", "create_generate_podcast_tool", "create_generate_video_presentation_tool", - "create_scrape_webpage_tool", - "create_update_memory_tool", - "create_update_team_memory_tool", "format_documents_for_context", "get_all_tool_names", "get_default_enabled_tools", diff --git a/surfsense_backend/app/agents/shared/tools/registry.py b/surfsense_backend/app/agents/shared/tools/registry.py index 9b1944aa5..6676be644 100644 --- a/surfsense_backend/app/agents/shared/tools/registry.py +++ b/surfsense_backend/app/agents/shared/tools/registry.py @@ -100,13 +100,11 @@ from .onedrive import ( from .podcast import create_generate_podcast_tool from .report import create_generate_report_tool from .resume import create_generate_resume_tool -from .scrape_webpage import create_scrape_webpage_tool from .teams import ( create_list_teams_channels_tool, create_read_teams_messages_tool, create_send_teams_message_tool, ) -from .update_memory import create_update_memory_tool, create_update_team_memory_tool from .video_presentation import create_generate_video_presentation_tool from .web_search import create_web_search_tool @@ -171,6 +169,36 @@ def _build_create_automation_tool(deps: dict[str, Any]) -> BaseTool: ) +def _build_scrape_webpage_tool(deps: dict[str, Any]) -> BaseTool: + # ``scrape_webpage`` is owned by the main agent (its sole live consumer); + # deferred import keeps this catalog free of a ``multi_agent_chat`` cycle. + from app.agents.multi_agent_chat.main_agent.tools.scrape_webpage import ( + create_scrape_webpage_tool, + ) + + return create_scrape_webpage_tool(firecrawl_api_key=deps.get("firecrawl_api_key")) + + +def _build_update_memory_tool(deps: dict[str, Any]) -> BaseTool: + # ``update_memory`` is owned by the main agent; deferred import (see above). + from app.agents.multi_agent_chat.main_agent.tools.update_memory import ( + create_update_memory_tool, + create_update_team_memory_tool, + ) + + if deps["thread_visibility"] == ChatVisibility.SEARCH_SPACE: + return create_update_team_memory_tool( + search_space_id=deps["search_space_id"], + db_session=deps["db_session"], + llm=deps.get("llm"), + ) + return create_update_memory_tool( + user_id=deps["user_id"], + db_session=deps["db_session"], + llm=deps.get("llm"), + ) + + # ============================================================================= # Built-in Tools Registry # ============================================================================= @@ -242,9 +270,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [ ToolDefinition( name="scrape_webpage", description="Scrape and extract the main content from a webpage", - factory=lambda deps: create_scrape_webpage_tool( - firecrawl_api_key=deps.get("firecrawl_api_key"), - ), + factory=_build_scrape_webpage_tool, requires=[], # firecrawl_api_key is optional ), # Web search tool — real-time web search via SearXNG + user-configured engines @@ -293,19 +319,7 @@ BUILTIN_TOOLS: list[ToolDefinition] = [ ToolDefinition( name="update_memory", description="Save important long-term facts, preferences, and instructions to the (personal or team) memory", - factory=lambda deps: ( - create_update_team_memory_tool( - search_space_id=deps["search_space_id"], - db_session=deps["db_session"], - llm=deps.get("llm"), - ) - if deps["thread_visibility"] == ChatVisibility.SEARCH_SPACE - else create_update_memory_tool( - user_id=deps["user_id"], - db_session=deps["db_session"], - llm=deps.get("llm"), - ) - ), + factory=_build_update_memory_tool, requires=[ "user_id", "search_space_id",