refactor(agents): split tool registry into pure-data catalog, decouple connectors

Replace the connector-coupled BUILTIN_TOOLS registry with a pure-data
catalog so shared/tools no longer imports any connector module, making the
connector packages independently deletable.

- add shared/tools/catalog.py (ToolMetadata + TOOL_CATALOG, 41 tools, no imports)
- point GET /agent/tools (the only live consumer) at the catalog
- relocate ToolDefinition into action_log middleware (its sole consumer);
  drop the inert tool_definitions wiring (no tool defines reverse)
- delete shared/tools/registry.py: connector imports, dead factories,
  dead get_connector_gated_tools, and BUILTIN_TOOLS
- drop stale dedup-propagation test (path removed in C1) + refresh docstrings

import-all guardrail + agents unit suite green (987 passed).
This commit is contained in:
CREDO23 2026-06-04 19:43:50 +02:00
parent c3238d8840
commit 003924062d
13 changed files with 154 additions and 826 deletions

View file

@ -12,7 +12,7 @@ from langchain_core.tools import tool
from app.agents.shared.feature_flags import AgentFeatureFlags
from app.agents.shared.middleware.action_log import ActionLogMiddleware
from app.agents.shared.tools.registry import ToolDefinition
from app.agents.shared.middleware.action_log import ToolDefinition
@dataclass

View file

@ -91,10 +91,9 @@ def test_no_agent_tools_means_no_dedup() -> None:
"""After the cleanup tier removed the legacy ``_NATIVE_HITL_TOOL_DEDUP_KEYS``
map, dedup is purely declarative no resolvers means no dedup runs.
Coverage for the previously hardcoded native HITL tools now lives on
each :class:`ToolDefinition.dedup_key` in
:mod:`app.agents.shared.tools.registry`, which is wired through to
``tool.metadata`` by :func:`build_tools`.
Dedup is purely declarative: tools opt in by carrying a ``dedup_key``
(callable) or ``hitl_dedup_key`` (arg name) in their ``metadata``. With no
agent tools, there are no resolvers and dedup is a no-op.
"""
mw = DedupHITLToolCallsMiddleware(agent_tools=None)
state = {
@ -109,27 +108,6 @@ def test_no_agent_tools_means_no_dedup() -> None:
assert out is None
def test_registry_propagates_dedup_key_to_tool_metadata() -> None:
"""Smoke-check the wiring path that replaced the legacy native map.
``ToolDefinition.dedup_key`` set in the registry must be copied onto
the constructed tool's ``metadata`` so :class:`DedupHITLToolCallsMiddleware`
can pick it up at agent build time.
"""
from app.agents.shared.tools.registry import (
BUILTIN_TOOLS,
wrap_dedup_key_by_arg_name,
)
notion_tool_defs = [t for t in BUILTIN_TOOLS if t.name == "create_notion_page"]
assert notion_tool_defs, "registry should still expose create_notion_page"
tool_def = notion_tool_defs[0]
assert tool_def.dedup_key is not None
# Same wrapping helper used in the registry — sanity check identity
sample = wrap_dedup_key_by_arg_name("title")({"title": "Plan"})
assert sample == "plan"
def test_full_args_dedup_keeps_distinct_calls_sharing_a_field() -> None:
"""Regression: MCP tools (e.g. ``createJiraIssue``) used to dedup on
the schema's first required field, which is often the workspace /