feat(MAT-64): Add web search tool to text bot
The text bot had no websearch capability while the voice agent did. Added Brave Search integration as a web_search tool so the bot can answer questions about current events and look up information. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
48
bot.py
48
bot.py
@@ -76,6 +76,7 @@ CONFLUENCE_USER = os.environ.get("CONFLUENCE_USER", "")
|
||||
CONFLUENCE_TOKEN = os.environ.get("CONFLUENCE_TOKEN", "")
|
||||
PORTAL_URL = os.environ.get("PORTAL_URL", "")
|
||||
BOT_API_KEY = os.environ.get("BOT_API_KEY", "")
|
||||
BRAVE_API_KEY = os.environ.get("BRAVE_API_KEY", "")
|
||||
MAX_TOOL_ITERATIONS = 5
|
||||
|
||||
SYSTEM_PROMPT = """You are a helpful AI assistant in a Matrix chat room.
|
||||
@@ -94,6 +95,7 @@ IMPORTANT RULES — FOLLOW THESE STRICTLY:
|
||||
- You can see and analyze images that users send. Describe what you see when asked about an image.
|
||||
- You can read and analyze PDF documents that users send. Summarize content and answer questions about them.
|
||||
- You can generate images when asked — use the generate_image tool for any image creation, drawing, or illustration requests.
|
||||
- You can search the web using the web_search tool. Use it when users ask about current events, facts, or anything that needs up-to-date information.
|
||||
- You can search Confluence and Jira using tools. When users ask about documentation, wiki pages, tickets, or tasks, use the appropriate tool. Use confluence_recent_pages FIRST to show recently edited pages before searching.
|
||||
- When creating Jira issues, always confirm the project key and summary with the user before creating.
|
||||
- If a user's Atlassian account is not connected, tell them to connect it at matrixhost.eu/settings and provide the link.
|
||||
@@ -268,7 +270,23 @@ ATLASSIAN_TOOLS = [
|
||||
},
|
||||
]
|
||||
|
||||
ALL_TOOLS = IMAGE_GEN_TOOLS + ATLASSIAN_TOOLS
|
||||
WEB_SEARCH_TOOLS = [{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "web_search",
|
||||
"description": "Search the web for current information. Use when the user asks about recent events, facts, or anything that needs up-to-date information from the internet.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"query": {"type": "string", "description": "Search query"},
|
||||
"count": {"type": "integer", "description": "Number of results (default 5)", "default": 5},
|
||||
},
|
||||
"required": ["query"],
|
||||
},
|
||||
},
|
||||
}]
|
||||
|
||||
ALL_TOOLS = IMAGE_GEN_TOOLS + WEB_SEARCH_TOOLS + ATLASSIAN_TOOLS
|
||||
|
||||
ATLASSIAN_NOT_CONNECTED_MSG = (
|
||||
"Your Atlassian account is not connected. "
|
||||
@@ -1923,6 +1941,30 @@ class Bot:
|
||||
finally:
|
||||
self._pending_connects.pop(sender, None)
|
||||
|
||||
async def _brave_search(self, query: str, count: int = 5) -> str:
|
||||
"""Call Brave Search API and return formatted results."""
|
||||
if not BRAVE_API_KEY:
|
||||
return "Web search unavailable (no API key configured)."
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
resp = await client.get(
|
||||
"https://api.search.brave.com/res/v1/web/search",
|
||||
headers={"Accept": "application/json", "X-Subscription-Token": BRAVE_API_KEY},
|
||||
params={"q": query, "count": count, "text_decorations": False},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
results = data.get("web", {}).get("results", [])
|
||||
if not results:
|
||||
return "No results found."
|
||||
lines = []
|
||||
for r in results[:count]:
|
||||
lines.append(f"- {r.get('title', '')}: {r.get('description', '')} ({r.get('url', '')})")
|
||||
return "\n".join(lines)
|
||||
except Exception as exc:
|
||||
logger.warning("Brave search error: %s", exc)
|
||||
return f"Search failed: {exc}"
|
||||
|
||||
async def _execute_tool(self, tool_name: str, args: dict, sender: str, room_id: str) -> str:
|
||||
"""Execute a tool call and return the result as a string."""
|
||||
# Image generation — no Atlassian token needed
|
||||
@@ -1930,6 +1972,10 @@ class Bot:
|
||||
await self._generate_and_send_image(room_id, args.get("prompt", ""))
|
||||
return "Image generated and sent to the room."
|
||||
|
||||
# Web search — no auth needed
|
||||
if tool_name == "web_search":
|
||||
return await self._brave_search(args.get("query", ""), args.get("count", 5))
|
||||
|
||||
# Atlassian tools — need per-user token
|
||||
token = await self.atlassian.get_token(sender) if sender else None
|
||||
if not token:
|
||||
|
||||
Reference in New Issue
Block a user