fix: improve library search to match any word instead of exact phrase

Previously, searching for "flight price drop alert" required that exact
phrase to be in the agent name/description. Now it splits into individual
words and matches agents containing ANY of: flight, price, drop, alert.

This fixes the issue where "flight price tracker" wasn't found when
searching for "flight price drop alert" even though they share keywords.
This commit is contained in:
Zamil Majdy
2026-01-29 22:28:24 -06:00
parent dc92a7b520
commit 0d1d275e8d
3 changed files with 26 additions and 26 deletions

View File

@@ -153,18 +153,12 @@ async def search_agents(
# If no results from UUID lookup, do text search
if not agents:
logger.info(
f"Searching user library for: {query!r} (user_id={user_id})"
)
logger.info(f"Searching user library for: {query}")
results = await library_db.list_library_agents(
user_id=user_id, # type: ignore[arg-type]
search_term=query,
page_size=10,
)
logger.info(
f"Library search returned {len(results.agents)} agents "
f"(total_items={results.pagination.total_items})"
)
for agent in results.agents:
agents.append(
AgentInfo(

View File

@@ -1,6 +1,5 @@
"""Tool for searching agents in the user's library."""
import logging
from typing import Any
from backend.api.features.chat.model import ChatSession
@@ -9,8 +8,6 @@ from .agent_search import search_agents
from .base import BaseTool
from .models import ToolResponseBase
logger = logging.getLogger(__name__)
class FindLibraryAgentTool(BaseTool):
"""Tool for searching agents in the user's library."""
@@ -47,10 +44,8 @@ class FindLibraryAgentTool(BaseTool):
async def _execute(
self, user_id: str | None, session: ChatSession, **kwargs
) -> ToolResponseBase:
query = kwargs.get("query", "").strip()
logger.info(f"find_library_agent called: query={query!r}, user_id={user_id}")
return await search_agents(
query=query,
query=kwargs.get("query", "").strip(),
source="library",
session_id=session.session_id,
user_id=user_id,

View File

@@ -77,21 +77,32 @@ async def list_library_agents(
}
# Build search filter if applicable
# Split into words and match ANY word in name or description
if search_term:
where_clause["OR"] = [
{
"AgentGraph": {
"is": {"name": {"contains": search_term, "mode": "insensitive"}}
}
},
{
"AgentGraph": {
"is": {
"description": {"contains": search_term, "mode": "insensitive"}
words = [w.strip() for w in search_term.split() if len(w.strip()) >= 3]
if words:
or_conditions: list[prisma.types.LibraryAgentWhereInput] = []
for word in words:
or_conditions.append(
{
"AgentGraph": {
"is": {"name": {"contains": word, "mode": "insensitive"}}
}
}
}
},
]
)
or_conditions.append(
{
"AgentGraph": {
"is": {
"description": {
"contains": word,
"mode": "insensitive",
}
}
}
}
)
where_clause["OR"] = or_conditions
# Determine sorting
order_by: prisma.types.LibraryAgentOrderByInput | None = None