Problem Statement
AI agents can only query the connected database. No way to search the web for context, documentation, or external data sources. Users cannot get answers that require external information.
Proposed Solution
Add web search capability to the AI agent, allowing it to search for documentation, error explanations, and external context when answering questions.
Acceptance Criteria
Technical Approach
Backend Changes
1. Web search service (backend/app/services/web_search.py):
import httpx
from typing import Optional
class WebSearchService:
def __init__(self, provider: str = "duckduckgo", api_key: Optional[str] = None):
self.provider = provider
self.api_key = api_key
self.cache = {}
async def search(self, query: str, num_results: int = 5) -> list[dict]:
"""Search the web and return results."""
# Check cache
cache_key = f"{query}:{num_results}"
if cache_key in self.cache:
return self.cache[cache_key]
# Execute search based on provider
if self.provider == "google":
results = await self._google_search(query, num_results)
elif self.provider == "bing":
results = await self._bing_search(query, num_results)
else:
results = await self._duckduckgo_search(query, num_results)
# Cache results
self.cache[cache_key] = results
return results
async def _duckduckgo_search(self, query: str, num_results: int) -> list[dict]:
"""Search using DuckDuckGo."""
async with httpx.AsyncClient() as client:
response = await client.get(
"https://api.duckduckgo.com/",
params={"q": query, "format": "json", "no_redirect": "1"}
)
data = response.json()
results = []
for result in data.get("RelatedTopics", [])[:num_results]:
if "Text" in result:
results.append({
"title": result.get("Text", "")[:100],
"snippet": result.get("Text", ""),
"url": result.get("FirstURL", ""),
"source": "DuckDuckGo"
})
return results
async def _google_search(self, query: str, num_results: int) -> list[dict]:
"""Search using Google Custom Search API."""
async with httpx.AsyncClient() as client:
response = await client.get(
"https://www.googleapis.com/customsearch/v1",
params={
"key": self.api_key,
"cx": "your_search_engine_id",
"q": query,
"num": num_results
}
)
data = response.json()
results = []
for item in data.get("items", [])[:num_results]:
results.append({
"title": item.get("title"),
"snippet": item.get("snippet"),
"url": item.get("link"),
"source": "Google"
})
return results
2. Search trigger logic (backend/app/services/search_trigger.py):
class SearchTrigger:
def __init__(self, web_search: WebSearchService):
self.web_search = web_search
def should_search(self, question: str, context: dict) -> bool:
"""Determine if web search would help answer the question."""
question_lower = question.lower()
# Trigger for error explanations
if any(word in question_lower for word in ["error", "exception", "why", "explain"]):
return True
# Trigger for documentation lookup
if any(word in question_lower for word in ["how to", "documentation", "docs"]):
return True
# Trigger for external data
if any(word in question_lower for word in ["weather", "news", "stock", "price"]):
return True
return False
async def enhance_context(self, question: str, context: dict) -> dict:
"""Add web search results to context."""
if not self.should_search(question, context):
return context
search_results = await self.web_search.search(question, num_results=3)
context["web_search_results"] = search_results
return context
3. Search integration in prompt (backend/app/llm.py):
def build_sql_system_prompt(schema_text, dialect, context=None):
base_prompt = "...existing prompt..."
# Add web search results if available
if context and context.get("web_search_results"):
search_context = "\n\nWeb Search Results (for context only, do not use in SQL):\n"
for i, result in enumerate(context["web_search_results"], 1):
search_context += f"{i}. {result['title']}: {result['snippet']}\n"
search_context += f" Source: {result['url']}\n"
base_prompt += search_context
return base_prompt
4. API routes (backend/app/routes/search.py):
POST /api/search - Execute web search
GET /api/search/preferences - Get search preferences
PATCH /api/search/preferences - Update preferences
Frontend Changes
1. Search preferences (frontend/src/routes/settings/search/+page.svelte):
<script>
export let preferences;
let provider = preferences.provider || 'duckduckgo';
let apiKey = preferences.api_key || '';
let privacyMode = preferences.privacy_mode || false;
async function savePreferences() {
await apiCall('/api/search/preferences', {
method: 'PATCH',
body: JSON.stringify({
provider,
api_key: apiKey,
privacy_mode: privacyMode
})
});
}
</script>
<div class="search-settings">
<h1>Web Search Settings</h1>
<section>
<h2>Search Provider</h2>
<select bind:value={provider}>
<option value="duckduckgo">DuckDuckGo (Free)</option>
<option value="google">Google Custom Search</option>
<option value="bing">Bing Search</option>
</select>
{#if provider !== 'duckduckgo'}
<label>
API Key
<input bind:value={apiKey} type="password" />
</label>
{/if}
</section>
<section>
<h2>Privacy</h2>
<label>
<input type="checkbox" bind:checked={privacyMode} />
Enable Privacy Mode (no search logging)
</label>
</section>
<button on:click={savePreferences}>Save Preferences</button>
</div>
2. Search results display - Show web search context in chat
3. Source citations - Link to web sources in responses
Key Files
backend/app/services/web_search.py - Search service (new)
backend/app/services/search_trigger.py - Trigger logic (new)
backend/app/llm.py - Prompt integration
backend/app/routes/search.py - API routes (new)
frontend/src/routes/settings/search/+page.svelte - Settings
Related Issues
Problem Statement
AI agents can only query the connected database. No way to search the web for context, documentation, or external data sources. Users cannot get answers that require external information.
Proposed Solution
Add web search capability to the AI agent, allowing it to search for documentation, error explanations, and external context when answering questions.
Acceptance Criteria
Technical Approach
Backend Changes
1. Web search service (
backend/app/services/web_search.py):2. Search trigger logic (
backend/app/services/search_trigger.py):3. Search integration in prompt (
backend/app/llm.py):4. API routes (
backend/app/routes/search.py):POST /api/search- Execute web searchGET /api/search/preferences- Get search preferencesPATCH /api/search/preferences- Update preferencesFrontend Changes
1. Search preferences (
frontend/src/routes/settings/search/+page.svelte):2. Search results display - Show web search context in chat
3. Source citations - Link to web sources in responses
Key Files
backend/app/services/web_search.py- Search service (new)backend/app/services/search_trigger.py- Trigger logic (new)backend/app/llm.py- Prompt integrationbackend/app/routes/search.py- API routes (new)frontend/src/routes/settings/search/+page.svelte- SettingsRelated Issues