From b7df800e947f95615ce2833672201920c459c56a Mon Sep 17 00:00:00 2001 From: Christer Hantilson Date: Fri, 3 Jul 2026 15:46:14 +0200 Subject: [PATCH] fix(agent): fall back to keyword tool selection when retrieval times out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The retrieval-timeout branch hard-coded ALWAYS_AVAILABLE, silently skipping the deterministic keyword hints whenever the embedding backend was slow (e.g. a remote endpoint cold-loading its model). Queries that named email or calendar outright lost those tools and the model concluded the integrations did not exist. Let the timeout fall through to the existing keyword fallback instead — same baseline, plus the hints. Co-Authored-By: Claude Fable 5 --- src/agent_loop.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/agent_loop.py b/src/agent_loop.py index e3fa1f0b6..a0be4eb08 100644 --- a/src/agent_loop.py +++ b/src/agent_loop.py @@ -2532,11 +2532,17 @@ async def stream_agent_loop( ) logger.info(f"[tool-rag] Retrieved tools for query: {sorted(_relevant_tools - ALWAYS_AVAILABLE)}") except asyncio.TimeoutError: + # Leave _relevant_tools unset so the keyword fallback + # below still runs. Hard-coding ALWAYS_AVAILABLE here + # skipped the deterministic keyword hints whenever the + # embedding backend was slow (e.g. a remote endpoint + # cold-loading its model), silently stripping email/ + # calendar tools from queries that named them outright. logger.warning( - "[tool-rag] Retrieval exceeded %.1fs; falling back to always-available tools", + "[tool-rag] Retrieval exceeded %.1fs; falling back to keyword tool selection", _TOOL_SELECTION_TIMEOUT_SECONDS, ) - _relevant_tools = set(ALWAYS_AVAILABLE) + _relevant_tools = None except Exception as e: logger.warning(f"[tool-rag] Retrieval failed, using keyword fallback: {e}") _relevant_tools = None