fix(agent): make the tool-selection timeout configurable

Tool selection has a 1.5s budget covering three steps: index init, MCP
indexing, and retrieval. That suits a warm index on quick hardware. It
is tight anywhere else, because the steps run inside a request while the
app may also be loading FastEmbed, reaching ChromaDB and spawning MCP
servers.

The failure mode is what makes this worth fixing rather than the number
itself. On expiry, selection falls back to ALWAYS_AVAILABLE — which
contains no MCP tool at all. Every MCP server therefore disappears for
that turn, and the agent reports it does not have tools it is connected
to and could call directly. The warning line says the timeout expired;
nothing says the consequence was dropping the entire MCP surface, so the
two are not obviously related when reading logs.

Makes the value overridable via ODYSSEUS_TOOL_SELECTION_TIMEOUT so a
slower or busier deployment can buy headroom without patching. The
default is unchanged at 1.5s, so nothing moves for existing installs.

Also adds the missing `import os` — the module did not import it and
made no use of `os.` anywhere, so the new call would have raised
NameError at import time. Worth flagging because py_compile does not
catch it: it checks syntax, not name resolution.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Matthieu 2026-07-26 21:24:08 +02:00
parent d8a2059df8
commit acdfadbba9

View file

@ -9,6 +9,7 @@ The LLM decides when to use tools by writing fenced code blocks.
import asyncio
import collections
import json
import os
import re
import time
import logging
@ -894,7 +895,20 @@ _ADMIN_SCHEMA_NAMES = frozenset([
"create_session", "list_sessions", "send_to_session", "pipeline",
"ask_teacher", "list_models", "search_chats",
])
_TOOL_SELECTION_TIMEOUT_SECONDS = 1.5
# Budget for the three tool-selection steps (index init, MCP indexing, retrieval).
#
# 1.5s suits a warm index on quick hardware. It is tight anywhere else: the steps
# run during a request, while the app may also be loading FastEmbed, reaching
# ChromaDB and spawning MCP servers. When it expires, selection falls back to
# ALWAYS_AVAILABLE — which contains no MCP tool at all, so every MCP server
# silently disappears for that turn. The agent then reports it lacks tools it is
# in fact connected to, and nothing in the logs ties the two together.
#
# Overridable so slower or busier deployments can buy headroom without a patch.
# The default is unchanged.
_TOOL_SELECTION_TIMEOUT_SECONDS = float(
os.environ.get("ODYSSEUS_TOOL_SELECTION_TIMEOUT", "1.5")
)
def _is_ollama_openai_compat_url(endpoint_url: str) -> bool: