[eric] browser: the first-message fast path learns which integrations are natively connected, so a Slack ask stops opening a browser when Slack tools exist

This commit is contained in:
ciregenz
2026-08-10 08:18:59 -07:00
parent 263ce73b05
commit 366f74f688
2 changed files with 43 additions and 1 deletions
@@ -242,11 +242,39 @@ def seed_hints_for_task(prompt: str) -> str:
return ("\n\nKnown site facts (use their URL patterns for ENTRY):\n" + "\n".join(lines)) if lines else "" return ("\n\nKnown site facts (use their URL patterns for ENTRY):\n" + "\n".join(lines)) if lines else ""
def connected_integration_names() -> list[str]:
"""Names of MCP integrations the user has actually connected (Slack, Notion, ...), lowercase."""
try:
from backend.apps.tools_lib.tools_lib import load_all_tools
return [
t.name.lower() for t in load_all_tools()
if t.mcp_config and t.enabled and t.auth_status in ("configured", "connected")
]
except Exception:
return []
def browsy_beyond_connected(prompt: str, connected: list[str]) -> bool:
"""True when browser-ish evidence survives after removing connected-integration names. "Make a
Slack skill" with Slack connected has none left and must route to the orchestrator's native
tools (ENG-225); "go to slack.com and click around" still reads browser."""
stripped = prompt
for name in connected:
for token in name.split():
if len(token) >= 3:
stripped = re.sub(re.escape(token), " ", stripped, flags=re.I)
return bool(P_BROWSY_RE.search(stripped))
async def classify_and_brief(prompt: str, settings, primary_api: str | None) -> tuple[str, str]: async def classify_and_brief(prompt: str, settings, primary_api: str | None) -> tuple[str, str]:
"""One cheap aux call returns a READ/ACT/NO verdict plus a routing brief """One cheap aux call returns a READ/ACT/NO verdict plus a routing brief
(entry URL + step outline), timeboxed; any failure means NO (normal path).""" (entry URL + step outline), timeboxed; any failure means NO (normal path)."""
t0 = time.monotonic() t0 = time.monotonic()
try: try:
p_connected = connected_integration_names()
if p_connected and not browsy_beyond_connected(prompt, p_connected):
logger.info("[browser-fast-path] only connected-integration names matched; normal path (native tools win)")
return "no", ""
from backend.apps.settings.credentials import get_anthropic_client_for_model from backend.apps.settings.credentials import get_anthropic_client_for_model
from backend.apps.agents.providers.registry import resolve_aux_model from backend.apps.agents.providers.registry import resolve_aux_model
@@ -264,7 +292,8 @@ async def classify_and_brief(prompt: str, settings, primary_api: str | None) ->
temperature=0, temperature=0,
system=P_CLASSIFIER_SYSTEM, system=P_CLASSIFIER_SYSTEM,
messages=[{"role": "user", "content": ( messages=[{"role": "user", "content": (
normalize_for_classifier(prompt[:2000]) + seed_hints_for_task(prompt))}], (f"[The user has these integrations natively connected, and tasks doable through them are NOT browser tasks, answer NO: {', '.join(p_connected)}]\n" if p_connected else "")
+ normalize_for_classifier(prompt[:2000]) + seed_hints_for_task(prompt))}],
), ),
timeout=8.0, timeout=8.0,
) )
+13
View File
@@ -176,3 +176,16 @@ def test_results_url_shapes():
assert RESULTS_URL_RE.search(u), u assert RESULTS_URL_RE.search(u), u
for u in misses: for u in misses:
assert not RESULTS_URL_RE.search(u), u assert not RESULTS_URL_RE.search(u), u
def test_connected_integration_names_route_native_not_browser():
"""ENG-225: 'make a Slack skill' with Slack connected must NOT read browser-ish; the same words
with nothing connected keep the cookie-borrow browser path."""
from backend.apps.agents.browser import browser_fast_path as fp
haik = ("Send a note in the Miscellaneous Slack channel. Better yet, make a Slack skill that "
"activates every time any of the Slack tools are called and prepends [AI].")
assert fp.browsy_beyond_connected(haik, ["slack"]) is False
assert fp.browsy_beyond_connected(haik, []) is True
assert fp.browsy_beyond_connected("go to slack.com and read the pricing page", ["slack"]) is True
assert fp.browsy_beyond_connected("add a row to my Notion tracker", ["notion"]) is False
assert fp.browsy_beyond_connected("send a linkedin message to my recruiter", ["slack", "notion"]) is True