2424from deepagents .graph import BASE_AGENT_PROMPT
2525from deepagents .middleware .patch_tool_calls import PatchToolCallsMiddleware
2626from deepagents .middleware .subagents import GENERAL_PURPOSE_SUBAGENT
27- from deepagents .middleware .summarization import create_summarization_middleware
2827from langchain .agents import create_agent
2928from langchain .agents .middleware import TodoListMiddleware
3029from langchain_anthropic .middleware import AnthropicPromptCachingMiddleware
3433from sqlalchemy .ext .asyncio import AsyncSession
3534
3635from app .agents .new_chat .context import SurfSenseContextSchema
36+ from app .agents .new_chat .filesystem_backends import build_backend_resolver
37+ from app .agents .new_chat .filesystem_selection import FilesystemSelection
3738from app .agents .new_chat .llm_config import AgentConfig
3839from app .agents .new_chat .middleware import (
3940 DedupHITLToolCallsMiddleware ,
41+ FileIntentMiddleware ,
4042 KnowledgeBaseSearchMiddleware ,
4143 MemoryInjectionMiddleware ,
4244 SurfSenseFilesystemMiddleware ,
4345)
46+ from app .agents .new_chat .middleware .safe_summarization import (
47+ create_safe_summarization_middleware ,
48+ )
4449from app .agents .new_chat .system_prompt import (
4550 build_configurable_system_prompt ,
4651 build_surfsense_system_prompt ,
4752)
48- from app .agents .new_chat .tools .registry import build_tools_async
53+ from app .agents .new_chat .tools .registry import build_tools_async , get_connector_gated_tools
4954from app .db import ChatVisibility
5055from app .services .connector_service import ConnectorService
5156from app .utils .perf import get_perf_logger
@@ -162,6 +167,7 @@ async def create_surfsense_deep_agent(
162167 thread_visibility : ChatVisibility | None = None ,
163168 mentioned_document_ids : list [int ] | None = None ,
164169 anon_session_id : str | None = None ,
170+ filesystem_selection : FilesystemSelection | None = None ,
165171):
166172 """
167173 Create a SurfSense deep agent with configurable tools and prompts.
@@ -236,6 +242,8 @@ async def create_surfsense_deep_agent(
236242 )
237243 """
238244 _t_agent_total = time .perf_counter ()
245+ filesystem_selection = filesystem_selection or FilesystemSelection ()
246+ backend_resolver = build_backend_resolver (filesystem_selection )
239247
240248 # Discover available connectors and document types for this search space
241249 available_connectors : list [str ] | None = None
@@ -285,105 +293,10 @@ async def create_surfsense_deep_agent(
285293 "llm" : llm ,
286294 }
287295
288- # Disable Notion action tools if no Notion connector is configured
289296 modified_disabled_tools = list (disabled_tools ) if disabled_tools else []
290- has_notion_connector = (
291- available_connectors is not None and "NOTION_CONNECTOR" in available_connectors
292- )
293- if not has_notion_connector :
294- notion_tools = [
295- "create_notion_page" ,
296- "update_notion_page" ,
297- "delete_notion_page" ,
298- ]
299- modified_disabled_tools .extend (notion_tools )
300-
301- # Disable Linear action tools if no Linear connector is configured
302- has_linear_connector = (
303- available_connectors is not None and "LINEAR_CONNECTOR" in available_connectors
304- )
305- if not has_linear_connector :
306- linear_tools = [
307- "create_linear_issue" ,
308- "update_linear_issue" ,
309- "delete_linear_issue" ,
310- ]
311- modified_disabled_tools .extend (linear_tools )
312-
313- # Disable Google Drive action tools if no Google Drive connector is configured
314- has_google_drive_connector = (
315- available_connectors is not None and "GOOGLE_DRIVE_FILE" in available_connectors
316- )
317- if not has_google_drive_connector :
318- google_drive_tools = [
319- "create_google_drive_file" ,
320- "delete_google_drive_file" ,
321- ]
322- modified_disabled_tools .extend (google_drive_tools )
323-
324- has_dropbox_connector = (
325- available_connectors is not None and "DROPBOX_FILE" in available_connectors
326- )
327- if not has_dropbox_connector :
328- modified_disabled_tools .extend (["create_dropbox_file" , "delete_dropbox_file" ])
329-
330- has_onedrive_connector = (
331- available_connectors is not None and "ONEDRIVE_FILE" in available_connectors
332- )
333- if not has_onedrive_connector :
334- modified_disabled_tools .extend (["create_onedrive_file" , "delete_onedrive_file" ])
335-
336- # Disable Google Calendar action tools if no Google Calendar connector is configured
337- has_google_calendar_connector = (
338- available_connectors is not None
339- and "GOOGLE_CALENDAR_CONNECTOR" in available_connectors
340- )
341- if not has_google_calendar_connector :
342- calendar_tools = [
343- "create_calendar_event" ,
344- "update_calendar_event" ,
345- "delete_calendar_event" ,
346- ]
347- modified_disabled_tools .extend (calendar_tools )
348-
349- # Disable Gmail action tools if no Gmail connector is configured
350- has_gmail_connector = (
351- available_connectors is not None
352- and "GOOGLE_GMAIL_CONNECTOR" in available_connectors
353- )
354- if not has_gmail_connector :
355- gmail_tools = [
356- "create_gmail_draft" ,
357- "update_gmail_draft" ,
358- "send_gmail_email" ,
359- "trash_gmail_email" ,
360- ]
361- modified_disabled_tools .extend (gmail_tools )
362-
363- # Disable Jira action tools if no Jira connector is configured
364- has_jira_connector = (
365- available_connectors is not None and "JIRA_CONNECTOR" in available_connectors
366- )
367- if not has_jira_connector :
368- jira_tools = [
369- "create_jira_issue" ,
370- "update_jira_issue" ,
371- "delete_jira_issue" ,
372- ]
373- modified_disabled_tools .extend (jira_tools )
374-
375- # Disable Confluence action tools if no Confluence connector is configured
376- has_confluence_connector = (
377- available_connectors is not None
378- and "CONFLUENCE_CONNECTOR" in available_connectors
297+ modified_disabled_tools .extend (
298+ get_connector_gated_tools (available_connectors )
379299 )
380- if not has_confluence_connector :
381- confluence_tools = [
382- "create_confluence_page" ,
383- "update_confluence_page" ,
384- "delete_confluence_page" ,
385- ]
386- modified_disabled_tools .extend (confluence_tools )
387300
388301 # Remove direct KB search tool; we now pre-seed a scoped filesystem via middleware.
389302 if "search_knowledge_base" not in modified_disabled_tools :
@@ -407,6 +320,20 @@ async def create_surfsense_deep_agent(
407320 _t0 = time .perf_counter ()
408321 _enabled_tool_names = {t .name for t in tools }
409322 _user_disabled_tool_names = set (disabled_tools ) if disabled_tools else set ()
323+
324+ # Collect generic MCP connector info so the system prompt can route queries
325+ # to their tools instead of falling back to "not in knowledge base".
326+ _mcp_connector_tools : dict [str , list [str ]] = {}
327+ for t in tools :
328+ meta = getattr (t , "metadata" , None ) or {}
329+ if meta .get ("mcp_is_generic" ) and meta .get ("mcp_connector_name" ):
330+ _mcp_connector_tools .setdefault (
331+ meta ["mcp_connector_name" ], [],
332+ ).append (t .name )
333+
334+ if _mcp_connector_tools :
335+ _perf_log .info ("MCP connector tool routing: %s" , _mcp_connector_tools )
336+
410337 if agent_config is not None :
411338 system_prompt = build_configurable_system_prompt (
412339 custom_system_instructions = agent_config .system_instructions ,
@@ -415,12 +342,14 @@ async def create_surfsense_deep_agent(
415342 thread_visibility = thread_visibility ,
416343 enabled_tool_names = _enabled_tool_names ,
417344 disabled_tool_names = _user_disabled_tool_names ,
345+ mcp_connector_tools = _mcp_connector_tools ,
418346 )
419347 else :
420348 system_prompt = build_surfsense_system_prompt (
421349 thread_visibility = thread_visibility ,
422350 enabled_tool_names = _enabled_tool_names ,
423351 disabled_tool_names = _user_disabled_tool_names ,
352+ mcp_connector_tools = _mcp_connector_tools ,
424353 )
425354 _perf_log .info (
426355 "[create_agent] System prompt built in %.3fs" , time .perf_counter () - _t0
@@ -437,12 +366,15 @@ async def create_surfsense_deep_agent(
437366 gp_middleware = [
438367 TodoListMiddleware (),
439368 _memory_middleware ,
369+ FileIntentMiddleware (llm = llm ),
440370 SurfSenseFilesystemMiddleware (
371+ backend = backend_resolver ,
372+ filesystem_mode = filesystem_selection .mode ,
441373 search_space_id = search_space_id ,
442374 created_by_id = user_id ,
443375 thread_id = thread_id ,
444376 ),
445- create_summarization_middleware (llm , StateBackend ),
377+ create_safe_summarization_middleware (llm , StateBackend ),
446378 PatchToolCallsMiddleware (),
447379 AnthropicPromptCachingMiddleware (unsupported_model_behavior = "ignore" ),
448380 ]
@@ -458,21 +390,25 @@ async def create_surfsense_deep_agent(
458390 deepagent_middleware = [
459391 TodoListMiddleware (),
460392 _memory_middleware ,
393+ FileIntentMiddleware (llm = llm ),
461394 KnowledgeBaseSearchMiddleware (
462395 llm = llm ,
463396 search_space_id = search_space_id ,
397+ filesystem_mode = filesystem_selection .mode ,
464398 available_connectors = available_connectors ,
465399 available_document_types = available_document_types ,
466400 mentioned_document_ids = mentioned_document_ids ,
467401 anon_session_id = anon_session_id ,
468402 ),
469403 SurfSenseFilesystemMiddleware (
404+ backend = backend_resolver ,
405+ filesystem_mode = filesystem_selection .mode ,
470406 search_space_id = search_space_id ,
471407 created_by_id = user_id ,
472408 thread_id = thread_id ,
473409 ),
474410 SubAgentMiddleware (backend = StateBackend , subagents = [general_purpose_spec ]),
475- create_summarization_middleware (llm , StateBackend ),
411+ create_safe_summarization_middleware (llm , StateBackend ),
476412 PatchToolCallsMiddleware (),
477413 DedupHITLToolCallsMiddleware (agent_tools = tools ),
478414 AnthropicPromptCachingMiddleware (unsupported_model_behavior = "ignore" ),
0 commit comments