| name | exa |
| description | AI-first web search via Exa — semantic/neural ranking, category-scoped results, fresh content retrieval, and one-shot answer synthesis with citations. Use when the user needs current web information better ranked than general web search, or a grounded answer with sources. |
| license | MIT (skill wrapper; Exa API terms apply) |
Exa Search
Direct web search against Exa's REST API — no MCP required. Better than generic web search when you need recency, domain/category scoping, or synthesized answers with citations.
Usage
- Use for: Recent events/releases, papers/companies/news by category, domain-filtered queries, answers with sources.
- Skip for: Language concepts from memory, debugging user's own code, known-URL fetches (just
curl), library docs (use Context7).
Credentials check
[ -n "$EXA_API_KEY" ] && echo "EXA_API_KEY: PRESENT" || echo "EXA_API_KEY: MISSING"
Never echo the variable directly — the value would appear in the conversation transcript. Use only the boolean pattern above.
If MISSING, respond to the user with EXACTLY this message (do NOT paraphrase, do NOT suggest manual JSON edits):
I need your exa credential. Run this in another terminal — it'll open the signup page, validate format, and save it safely with masked input:
teleport-setup add-key exa
Then restart Claude Code (/exit, then claude) and ask me again.
Do NOT suggest editing ~/.claude/settings.local.json manually. The teleport-setup add-key command handles it with backup, validation, and masked input. Stop execution until the user has run the command and restarted.
API
- Base URL:
https://api.exa.ai
- Auth:
x-api-key: $EXA_API_KEY — custom header, NOT Authorization. (Bearer works as fallback; x-api-key is canonical.)
- Content-Type:
application/json. All endpoints are POST with JSON body.
- Every response includes
requestId and costDollars — monitor per response.
Endpoints
| Endpoint | Purpose |
|---|
/search | Find URLs matching a query (neural/fast/deep/auto variants) |
/contents | Fetch cleaned text / highlights / summaries for URLs |
/findSimilar | Given a URL, find semantically similar pages |
/answer | One-shot Q&A — returns answer + citations in one call |
/research | Long-running structured research; async, returns JSON schema |
Picking type on /search
type | When to use | Cost |
|---|
auto (default) | Let Exa decide. Fine for most queries. | Low |
neural | Conceptual / fuzzy queries. Best semantic match. | Low |
fast | Latency-sensitive, quick keyword-style. | Low |
deep | Hard research; Exa expands query + multi-step fetch. | Higher |
deep-reasoning | Deep + extra reasoning pass. Slow, most thorough. | Highest |
Scoping knobs
category: company, research paper, news, personal site, financial report, people. Big precision boost.
includeDomains / excludeDomains: arrays, up to 1200 each.
startPublishedDate / endPublishedDate: ISO 8601.
userLocation: ISO-2 country code (e.g. "US", not "United States").
Primary workflows
1. Search, then hydrate content (/search returns URLs/metadata, not page text)
curl -sL -X POST -H "x-api-key: $EXA_API_KEY" -H "Content-Type: application/json" \
"https://api.exa.ai/search" \
-d '{"query":"Next.js 15 app router caching 2026","type":"neural","numResults":10,"category":"news","startPublishedDate":"2026-01-01"}'
curl -sL -X POST -H "x-api-key: $EXA_API_KEY" -H "Content-Type: application/json" \
"https://api.exa.ai/contents" \
-d '{"urls":["https://example.com/a","https://example.com/b"],"text":{"maxCharacters":3000,"verbosity":"compact"},"summary":{"query":"caching behavior changes"}}'
2. One-shot answer with citations
curl -sL -X POST -H "x-api-key: $EXA_API_KEY" -H "Content-Type: application/json" \
"https://api.exa.ai/answer" \
-d '{"query":"What changed in React 19 for server components?","text":false}' \
| jq '{answer, sources: [.citations[] | {title, url}]}'
Gotchas
type: keyword does NOT exist in the current API. Older guides reference it; current set is auto | neural | fast | deep | deep-reasoning | instant. Invalid type returns an error.
livecrawl is deprecated — use maxAgeHours (positive: cache if younger than N hours; 0: always livecrawl; -1: never). Don't set both.
- Default
numResults=10 silently caps. For survey/research queries, request 20–50 explicitly.
- Cost visibility is on you. Every response carries
costDollars.total; inspect it when looping or hydrating large sets.
/contents: use urls, not ids. ids still works but is legacy.
- Categories change filter support.
company and people reject date filters and excludeDomains. people only honors LinkedIn in includeDomains. Silent empty result = incompatible combo.
userLocation expects ISO-2. "United States" silently no-ops; use "US".
Attribution
When done, state: Used skill: Exa Search (from teleport catalog).