mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-06 14:22:47 +02:00
Gate supervisor connector routes by searchable inventory and simplify routing specs.
This commit is contained in:
parent
91e12bd31e
commit
33fc457dcc
3 changed files with 215 additions and 145 deletions
|
|
@ -9,7 +9,12 @@ from typing import Any
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class DomainRoutingSpec:
|
class DomainRoutingSpec:
|
||||||
"""One ``@tool`` the supervisor calls to delegate to a compiled domain graph."""
|
"""One supervisor-facing routing ``@tool`` bound to a compiled domain graph.
|
||||||
|
|
||||||
|
``curated_context`` is optional for **any** route: when set, the routing tool prepends its return
|
||||||
|
value into the child task via :func:`~app.agents.multi_agent_chat.core.delegation.compose_child_task`.
|
||||||
|
:func:`build_supervisor_routing_tools` does not pass it (all routes treated the same); use when building specs manually.
|
||||||
|
"""
|
||||||
|
|
||||||
tool_name: str
|
tool_name: str
|
||||||
description: str
|
description: str
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
"""Gate supervisor routing tools by connected searchable connector types (aligned with ``new_chat`` KB).
|
||||||
|
|
||||||
|
When ``available_connectors`` is ``None``, all routes are emitted (caller did not pass an inventory).
|
||||||
|
|
||||||
|
When provided, a connector route is emitted only if at least one required searchable type is present.
|
||||||
|
MCP tools are filtered upstream in :func:`~app.agents.multi_agent_chat.core.mcp_partition.partition_mcp_tools_by_expert_route`
|
||||||
|
so merges only include tools for connected accounts.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
# Route tool_name → searchable connector / doc-type strings (same family as
|
||||||
|
# ``chat_deepagent._CONNECTOR_TYPE_TO_SEARCHABLE`` values in ``available_connectors``).
|
||||||
|
_ROUTE_REQUIRES_ANY: dict[str, frozenset[str]] = {
|
||||||
|
"calendar": frozenset(
|
||||||
|
{"GOOGLE_CALENDAR_CONNECTOR", "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR"}
|
||||||
|
),
|
||||||
|
"confluence": frozenset({"CONFLUENCE_CONNECTOR"}),
|
||||||
|
"discord": frozenset({"DISCORD_CONNECTOR"}),
|
||||||
|
"dropbox": frozenset({"DROPBOX_FILE"}),
|
||||||
|
"gmail": frozenset({"GOOGLE_GMAIL_CONNECTOR", "COMPOSIO_GMAIL_CONNECTOR"}),
|
||||||
|
"google_drive": frozenset(
|
||||||
|
{"GOOGLE_DRIVE_FILE", "COMPOSIO_GOOGLE_DRIVE_CONNECTOR"}
|
||||||
|
),
|
||||||
|
"luma": frozenset({"LUMA_CONNECTOR"}),
|
||||||
|
"notion": frozenset({"NOTION_CONNECTOR"}),
|
||||||
|
"onedrive": frozenset({"ONEDRIVE_FILE"}),
|
||||||
|
"teams": frozenset({"TEAMS_CONNECTOR"}),
|
||||||
|
# MCP-only supervisor routes (see ``core.mcp_partition.MCP_ONLY_ROUTE_KEYS_IN_ORDER``).
|
||||||
|
"linear": frozenset({"LINEAR_CONNECTOR"}),
|
||||||
|
"slack": frozenset({"SLACK_CONNECTOR"}),
|
||||||
|
"jira": frozenset({"JIRA_CONNECTOR"}),
|
||||||
|
"clickup": frozenset({"CLICKUP_CONNECTOR"}),
|
||||||
|
"airtable": frozenset({"AIRTABLE_CONNECTOR"}),
|
||||||
|
"generic_mcp": frozenset({"MCP_CONNECTOR"}),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def include_connector_route(
|
||||||
|
route_key: str,
|
||||||
|
available_connectors: list[str] | None,
|
||||||
|
) -> bool:
|
||||||
|
"""Return whether to register this connector route on the supervisor.
|
||||||
|
|
||||||
|
If ``available_connectors`` is omitted, preserve legacy behaviour (emit the route).
|
||||||
|
|
||||||
|
Otherwise require at least one matching entry in ``available_connectors`` for connector-backed routes.
|
||||||
|
Builtin routes (research, memory, …) have no entry in ``_ROUTE_REQUIRES_ANY`` and are always included.
|
||||||
|
"""
|
||||||
|
if available_connectors is None:
|
||||||
|
return True
|
||||||
|
required = _ROUTE_REQUIRES_ANY.get(route_key)
|
||||||
|
if required is None:
|
||||||
|
return True
|
||||||
|
avail = set(available_connectors)
|
||||||
|
return bool(required & avail)
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from langchain_core.language_models import BaseChatModel
|
from langchain_core.language_models import BaseChatModel
|
||||||
|
|
@ -64,6 +63,7 @@ from app.agents.multi_agent_chat.expert_agent.mcp_bridge import build_mcp_route_
|
||||||
from app.agents.multi_agent_chat.core.mcp_partition import MCP_ONLY_ROUTE_KEYS_IN_ORDER
|
from app.agents.multi_agent_chat.core.mcp_partition import MCP_ONLY_ROUTE_KEYS_IN_ORDER
|
||||||
from app.agents.multi_agent_chat.routing.domain_routing_spec import DomainRoutingSpec
|
from app.agents.multi_agent_chat.routing.domain_routing_spec import DomainRoutingSpec
|
||||||
from app.agents.multi_agent_chat.routing.from_domain_agents import routing_tools_from_specs
|
from app.agents.multi_agent_chat.routing.from_domain_agents import routing_tools_from_specs
|
||||||
|
from app.agents.multi_agent_chat.routing.route_connector_gate import include_connector_route
|
||||||
|
|
||||||
_MCP_ONLY_ROUTE_DESCRIPTIONS: dict[str, str] = {
|
_MCP_ONLY_ROUTE_DESCRIPTIONS: dict[str, str] = {
|
||||||
"linear": (
|
"linear": (
|
||||||
|
|
@ -96,143 +96,89 @@ def build_supervisor_routing_tools(
|
||||||
llm: BaseChatModel,
|
llm: BaseChatModel,
|
||||||
*,
|
*,
|
||||||
registry_dependencies: dict[str, Any] | None = None,
|
registry_dependencies: dict[str, Any] | None = None,
|
||||||
gmail_curated_context: Callable[[str], str | None] | None = None,
|
|
||||||
calendar_curated_context: Callable[[str], str | None] | None = None,
|
|
||||||
include_deliverables: bool = True,
|
include_deliverables: bool = True,
|
||||||
mcp_tools_by_route: dict[str, list[BaseTool]] | None = None,
|
mcp_tools_by_route: dict[str, list[BaseTool]] | None = None,
|
||||||
|
available_connectors: list[str] | None = None,
|
||||||
) -> list[BaseTool]:
|
) -> list[BaseTool]:
|
||||||
"""``expert_agent.builtins`` (research, memory, deliverables) plus ``expert_agent.connectors`` → routing tools.
|
"""Build supervisor routing tools: builtins first, then connector experts (same pattern for all).
|
||||||
|
|
||||||
|
Requires ``registry_dependencies`` to produce any routing tools; otherwise returns an empty list.
|
||||||
|
|
||||||
Pass ``registry_dependencies`` from
|
Pass ``registry_dependencies`` from
|
||||||
:func:`app.agents.multi_agent_chat.core.registry.build_registry_dependencies`
|
:func:`app.agents.multi_agent_chat.core.registry.build_registry_dependencies`
|
||||||
to enable **all** registry-backed routes (Gmail, Calendar, chat, doc stores, Luma, …) and builtins
|
for builtins (**research**, **memory**, **deliverables** when ``include_deliverables``) and every
|
||||||
(**research**, **memory**, **deliverables** when ``include_deliverables``). Use a real chat ``thread_id``
|
registry-backed connector route.
|
||||||
in deps when deliverables need thread-scoped registry factories.
|
|
||||||
|
|
||||||
``mcp_tools_by_route`` maps supervisor route keys (e.g. ``gmail``, ``linear``) to MCP tools loaded
|
``mcp_tools_by_route`` maps route keys to MCP tools merged into the matching expert subgraph.
|
||||||
elsewhere; those tools are merged into the matching expert subgraph only — the supervisor sees
|
|
||||||
routing tools, not raw MCP tools.
|
When ``available_connectors`` is set (searchable connector strings, same shape as ``new_chat``),
|
||||||
|
a vendor route is registered only if the connector is available **or** MCP tools are present for
|
||||||
|
that route.
|
||||||
"""
|
"""
|
||||||
mcp = mcp_tools_by_route or {}
|
if registry_dependencies is None:
|
||||||
if registry_dependencies is not None:
|
return routing_tools_from_specs([])
|
||||||
gmail_native = build_gmail_tools(registry_dependencies)
|
|
||||||
calendar_native = build_calendar_tools(registry_dependencies)
|
|
||||||
else:
|
|
||||||
gmail_native = []
|
|
||||||
calendar_native = []
|
|
||||||
|
|
||||||
gmail_domain_agent = build_gmail_domain_agent(llm, gmail_native + mcp.get("gmail", []))
|
mcp = mcp_tools_by_route or {}
|
||||||
calendar_domain_agent = build_calendar_domain_agent(
|
specs: list[DomainRoutingSpec] = []
|
||||||
llm,
|
|
||||||
calendar_native + mcp.get("calendar", []),
|
research_tools = build_research_tools(registry_dependencies)
|
||||||
|
research_agent = build_research_domain_agent(llm, research_tools)
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="research",
|
||||||
|
description=(
|
||||||
|
"Route web search, page scraping, and SurfSense documentation help to the "
|
||||||
|
"research sub-agent. Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=research_agent,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
specs: list[DomainRoutingSpec] = [
|
memory_tools = build_memory_tools(registry_dependencies)
|
||||||
|
memory_agent = build_memory_domain_agent(llm, memory_tools)
|
||||||
|
specs.append(
|
||||||
DomainRoutingSpec(
|
DomainRoutingSpec(
|
||||||
tool_name="gmail",
|
tool_name="memory",
|
||||||
description=(
|
description=(
|
||||||
"Route Gmail-related work to the Gmail sub-agent. "
|
"Route saving long-term facts and preferences (personal or team memory) to the "
|
||||||
"Pass a clear natural-language task."
|
"memory sub-agent. Pass a clear natural-language task."
|
||||||
),
|
),
|
||||||
domain_agent=gmail_domain_agent,
|
domain_agent=memory_agent,
|
||||||
curated_context=gmail_curated_context,
|
|
||||||
),
|
),
|
||||||
DomainRoutingSpec(
|
)
|
||||||
tool_name="calendar",
|
|
||||||
description=(
|
|
||||||
"Route Google Calendar work to the Calendar sub-agent. "
|
|
||||||
"Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=calendar_domain_agent,
|
|
||||||
curated_context=calendar_curated_context,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
if registry_dependencies is not None:
|
if include_deliverables:
|
||||||
research_tools = build_research_tools(registry_dependencies)
|
deliverables_tools = build_deliverables_tools(registry_dependencies)
|
||||||
research_agent = build_research_domain_agent(llm, research_tools)
|
deliverables_agent = build_deliverables_domain_agent(llm, deliverables_tools)
|
||||||
specs.append(
|
specs.append(
|
||||||
DomainRoutingSpec(
|
DomainRoutingSpec(
|
||||||
tool_name="research",
|
tool_name="deliverables",
|
||||||
description=(
|
description=(
|
||||||
"Route web search, page scraping, and SurfSense documentation help to the "
|
"Route structured outputs (reports, podcasts, video presentations, resumes, "
|
||||||
"research sub-agent. Pass a clear natural-language task."
|
"images) to the deliverables sub-agent. Pass a clear natural-language task."
|
||||||
),
|
),
|
||||||
domain_agent=research_agent,
|
domain_agent=deliverables_agent,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
memory_tools = build_memory_tools(registry_dependencies)
|
# Connector experts (registry-backed + optional MCP merge): alphabetical by route key.
|
||||||
memory_agent = build_memory_domain_agent(llm, memory_tools)
|
if include_connector_route("calendar", available_connectors):
|
||||||
specs.append(
|
calendar_agent = build_calendar_domain_agent(
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="memory",
|
|
||||||
description=(
|
|
||||||
"Route saving long-term facts and preferences (personal or team memory) to the "
|
|
||||||
"memory sub-agent. Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=memory_agent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
if include_deliverables:
|
|
||||||
deliverables_tools = build_deliverables_tools(registry_dependencies)
|
|
||||||
deliverables_agent = build_deliverables_domain_agent(llm, deliverables_tools)
|
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="deliverables",
|
|
||||||
description=(
|
|
||||||
"Route structured outputs (reports, podcasts, video presentations, resumes, "
|
|
||||||
"images) to the deliverables sub-agent. Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=deliverables_agent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
discord_tools = build_discord_tools(registry_dependencies)
|
|
||||||
discord_agent = build_discord_domain_agent(
|
|
||||||
llm,
|
llm,
|
||||||
discord_tools + mcp.get("discord", []),
|
build_calendar_tools(registry_dependencies) + mcp.get("calendar", []),
|
||||||
)
|
)
|
||||||
specs.append(
|
specs.append(
|
||||||
DomainRoutingSpec(
|
DomainRoutingSpec(
|
||||||
tool_name="discord",
|
tool_name="calendar",
|
||||||
description=(
|
description=(
|
||||||
"Route Discord work (channels, messages) to the Discord sub-agent. "
|
"Route Google Calendar work to the Calendar sub-agent. "
|
||||||
"Pass a clear natural-language task."
|
"Pass a clear natural-language task."
|
||||||
),
|
),
|
||||||
domain_agent=discord_agent,
|
domain_agent=calendar_agent,
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
teams_tools = build_teams_tools(registry_dependencies)
|
|
||||||
teams_agent = build_teams_domain_agent(
|
|
||||||
llm,
|
|
||||||
teams_tools + mcp.get("teams", []),
|
|
||||||
)
|
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="teams",
|
|
||||||
description=(
|
|
||||||
"Route Microsoft Teams work (channels, messages) to the Teams sub-agent. "
|
|
||||||
"Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=teams_agent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
notion_tools = build_notion_tools(registry_dependencies)
|
|
||||||
notion_agent = build_notion_domain_agent(llm, notion_tools)
|
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="notion",
|
|
||||||
description=(
|
|
||||||
"Route Notion page work to the Notion sub-agent. Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=notion_agent,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if include_connector_route("confluence", available_connectors):
|
||||||
confluence_tools = build_confluence_tools(registry_dependencies)
|
confluence_tools = build_confluence_tools(registry_dependencies)
|
||||||
confluence_agent = build_confluence_domain_agent(llm, confluence_tools)
|
confluence_agent = build_confluence_domain_agent(llm, confluence_tools)
|
||||||
specs.append(
|
specs.append(
|
||||||
|
|
@ -246,6 +192,50 @@ def build_supervisor_routing_tools(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if include_connector_route("discord", available_connectors):
|
||||||
|
discord_tools = build_discord_tools(registry_dependencies)
|
||||||
|
discord_agent = build_discord_domain_agent(llm, discord_tools + mcp.get("discord", []))
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="discord",
|
||||||
|
description=(
|
||||||
|
"Route Discord work (channels, messages) to the Discord sub-agent. "
|
||||||
|
"Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=discord_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if include_connector_route("dropbox", available_connectors):
|
||||||
|
dropbox_tools = build_dropbox_tools(registry_dependencies)
|
||||||
|
dropbox_agent = build_dropbox_domain_agent(llm, dropbox_tools)
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="dropbox",
|
||||||
|
description=(
|
||||||
|
"Route Dropbox file work to the Dropbox sub-agent. Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=dropbox_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if include_connector_route("gmail", available_connectors):
|
||||||
|
gmail_agent = build_gmail_domain_agent(
|
||||||
|
llm,
|
||||||
|
build_gmail_tools(registry_dependencies) + mcp.get("gmail", []),
|
||||||
|
)
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="gmail",
|
||||||
|
description=(
|
||||||
|
"Route Gmail-related work to the Gmail sub-agent. "
|
||||||
|
"Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=gmail_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if include_connector_route("google_drive", available_connectors):
|
||||||
google_drive_tools = build_google_drive_tools(registry_dependencies)
|
google_drive_tools = build_google_drive_tools(registry_dependencies)
|
||||||
google_drive_agent = build_google_drive_domain_agent(llm, google_drive_tools)
|
google_drive_agent = build_google_drive_domain_agent(llm, google_drive_tools)
|
||||||
specs.append(
|
specs.append(
|
||||||
|
|
@ -259,31 +249,7 @@ def build_supervisor_routing_tools(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
dropbox_tools = build_dropbox_tools(registry_dependencies)
|
if include_connector_route("luma", available_connectors):
|
||||||
dropbox_agent = build_dropbox_domain_agent(llm, dropbox_tools)
|
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="dropbox",
|
|
||||||
description=(
|
|
||||||
"Route Dropbox file work to the Dropbox sub-agent. Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=dropbox_agent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
onedrive_tools = build_onedrive_tools(registry_dependencies)
|
|
||||||
onedrive_agent = build_onedrive_domain_agent(llm, onedrive_tools)
|
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name="onedrive",
|
|
||||||
description=(
|
|
||||||
"Route Microsoft OneDrive file work to the OneDrive sub-agent. "
|
|
||||||
"Pass a clear natural-language task."
|
|
||||||
),
|
|
||||||
domain_agent=onedrive_agent,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
luma_tools = build_luma_tools(registry_dependencies)
|
luma_tools = build_luma_tools(registry_dependencies)
|
||||||
luma_agent = build_luma_domain_agent(llm, luma_tools + mcp.get("luma", []))
|
luma_agent = build_luma_domain_agent(llm, luma_tools + mcp.get("luma", []))
|
||||||
specs.append(
|
specs.append(
|
||||||
|
|
@ -297,20 +263,63 @@ def build_supervisor_routing_tools(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
for route_key in MCP_ONLY_ROUTE_KEYS_IN_ORDER:
|
if include_connector_route("notion", available_connectors):
|
||||||
only_mcp = mcp.get(route_key) or []
|
notion_tools = build_notion_tools(registry_dependencies)
|
||||||
if not only_mcp:
|
notion_agent = build_notion_domain_agent(llm, notion_tools)
|
||||||
continue
|
specs.append(
|
||||||
desc = _MCP_ONLY_ROUTE_DESCRIPTIONS.get(
|
DomainRoutingSpec(
|
||||||
route_key,
|
tool_name="notion",
|
||||||
f"Route {route_key} MCP work to the {route_key} sub-agent. Pass a clear natural-language task.",
|
description=(
|
||||||
)
|
"Route Notion page work to the Notion sub-agent. Pass a clear natural-language task."
|
||||||
specs.append(
|
|
||||||
DomainRoutingSpec(
|
|
||||||
tool_name=route_key,
|
|
||||||
description=desc,
|
|
||||||
domain_agent=build_mcp_route_domain_agent(llm, route_key, only_mcp),
|
|
||||||
),
|
),
|
||||||
)
|
domain_agent=notion_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if include_connector_route("onedrive", available_connectors):
|
||||||
|
onedrive_tools = build_onedrive_tools(registry_dependencies)
|
||||||
|
onedrive_agent = build_onedrive_domain_agent(llm, onedrive_tools)
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="onedrive",
|
||||||
|
description=(
|
||||||
|
"Route Microsoft OneDrive file work to the OneDrive sub-agent. "
|
||||||
|
"Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=onedrive_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if include_connector_route("teams", available_connectors):
|
||||||
|
teams_tools = build_teams_tools(registry_dependencies)
|
||||||
|
teams_agent = build_teams_domain_agent(llm, teams_tools + mcp.get("teams", []))
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name="teams",
|
||||||
|
description=(
|
||||||
|
"Route Microsoft Teams work (channels, messages) to the Teams sub-agent. "
|
||||||
|
"Pass a clear natural-language task."
|
||||||
|
),
|
||||||
|
domain_agent=teams_agent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for route_key in MCP_ONLY_ROUTE_KEYS_IN_ORDER:
|
||||||
|
only_mcp = mcp.get(route_key) or []
|
||||||
|
if not only_mcp:
|
||||||
|
continue
|
||||||
|
if not include_connector_route(route_key, available_connectors):
|
||||||
|
continue
|
||||||
|
desc = _MCP_ONLY_ROUTE_DESCRIPTIONS.get(
|
||||||
|
route_key,
|
||||||
|
f"Route {route_key} MCP work to the {route_key} sub-agent. Pass a clear natural-language task.",
|
||||||
|
)
|
||||||
|
specs.append(
|
||||||
|
DomainRoutingSpec(
|
||||||
|
tool_name=route_key,
|
||||||
|
description=desc,
|
||||||
|
domain_agent=build_mcp_route_domain_agent(llm, route_key, only_mcp),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return routing_tools_from_specs(specs)
|
return routing_tools_from_specs(specs)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue