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.
Scanned 5/27/2026
Install via CLI
openskills install mnlt/teleport---
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
```bash
[ -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)
```bash
# 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**
```bash
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).`
No comments yet. Be the first to comment!