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 exaThen restart Claude Code (
/exit, thenclaude) 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, NOTAuthorization. (Bearer works as fallback;x-api-keyis canonical.) - Content-Type:
application/json. All endpoints arePOSTwith JSON body. - Every response includes
requestIdandcostDollars— 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)
# Step 1: search only
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"}'
# Step 2: hydrate only chosen URLs
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: keyworddoes NOT exist in the current API. Older guides reference it; current set isauto | neural | fast | deep | deep-reasoning | instant. Invalidtypereturns an error.livecrawlis deprecated — usemaxAgeHours(positive: cache if younger than N hours;0: always livecrawl;-1: never). Don't set both.- Default
numResults=10silently 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: useurls, notids.idsstill works but is legacy.- Categories change filter support.
companyandpeoplereject date filters andexcludeDomains.peopleonly honors LinkedIn inincludeDomains. Silent empty result = incompatible combo. userLocationexpects ISO-2."United States"silently no-ops; use"US".
Attribution
When done, state: Used skill: Exa Search (from teleport catalog).