Slack Assistant Exa Web Search Integration
Context
The Exa integration provides real-time web intelligence for the Slack Assistant. It handles external research queries — competitor analysis, company lookups, industry news, and people search. The integration was migrated from Exa’s legacy GET API to the current POST API, and the auth header was fixed from a non-functional Authorization: Bearer to x-api-key.
Guidance
API Format: POST with x-api-key
The Exa search API uses a non-standard auth header:
const response = await fetch('https://api.exa.ai/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey, // NOT Authorization: Bearer
},
body: JSON.stringify({
query: 'who is John Doe',
type: 'auto',
numResults: 5,
contents: { highlights: { maxCharacters: 4000 } },
}),
});Critical: Exa uses x-api-key header, not Authorization: Bearer. Using the wrong header returns a 401 that is silent in logs unless error handling inspects the response body.
Category Classification
The integration auto-classifies queries into Exa categories for better results:
const classifyCategory = (text: string) => {
if (/\bwho is\b/.test(text)) return 'people';
if (/\b(founder|ceo|cto|...)/.test(text)) return 'people';
if (/\bcompany\b/.test(text)) return 'company';
if (/\b(startup|enterprise)/.test(text)) return 'company';
return undefined; // auto-detect
};This improves result relevance without requiring users to specify categories.
Intent Gating
Exa is only called when the user prompt matches certain patterns (see shouldSearchWeb in assistant.ts). This prevents wasting API calls on non-search queries like “what deals do I have” or “find me the OAuth code.” The gate is conservative — it misses semantic queries like “what’s happening in AI this week” but avoids false positives.
Highlight Extraction
Results include highlights (relevant snippets) rather than full page text:
contents: { highlights: { maxCharacters: 4000 } }This reduces token usage in the LLM context while surfacing the most relevant portions. Each result is truncated to 300 characters in the final context assembly.
Result Formatting
Results are formatted as numbered entries with title, snippet, and source URL:
Exa web search (query: "latest AI developments"):
[1] Anthropic releases Claude 4
New model features extended context window...
Source: https://techcrunch.com/...
[2] OpenAI announces GPT-5
...
Source: https://...
Why This Matters
Web search is the only integration that brings external (non-company) data into the assistant. It turns the assistant from an internal knowledge tool into a research assistant. The keyword gate is deliberately conservative — users who need web data can use explicit trigger words (“search the web for X”), and users who don’t won’t pay the latency cost.
When to Apply
- Any assistant that needs real-time external information
- People/company research bots
- Competitive intelligence tools
Examples
Correcting the Auth Header
Before (broken):
headers: { Authorization: `Bearer ${apiKey}` }
// Returns 401 silentlyAfter (working):
headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }Related
apps/slack-apps/brainforge-assistant/src/exa.tsapps/slack-apps/brainforge-assistant/src/assistant.ts(shouldSearchWeb gate)apps/slack-apps/brainforge-assistant/src/config.ts(EXA_API_KEY)docs/solutions/architecture-patterns/slack-assistant-v2-hybrid-ai-pipeline-2026-04-28.md