Exa
Use this skill for Exa SDK, API, and MCP work.
Requirement: EXA_API_KEY
Before any Exa call, verify that EXA_API_KEY is present without printing it:
test -n "${EXA_API_KEY:-}"
In OpenClaw, this skill declares primaryEnv: EXA_API_KEY, so prefer configuring skills.entries.exa.apiKey as a SecretRef. OpenClaw injects the key for the agent run.
For manual use outside OpenClaw, export EXA_API_KEY from your local secret manager or an untracked local env file. Do not write API keys into tracked repo files or echo them into logs.
First documentation step
Read references/llms.txt first.
That file is a full local snapshot of Exa's documentation index and points to:
- JavaScript SDK docs
- Exa MCP setup
- coding-agent search and contents guides
- vertical-specific references like code, company, news, and people search
- Exa-published agent skill templates
Important pages usually worth following from the index:
https://exa.ai/docs/sdks/javascript-sdk.mdhttps://exa.ai/docs/reference/search-api-guide-for-coding-agents.mdhttps://exa.ai/docs/reference/contents-api-guide-for-coding-agents.mdhttps://exa.ai/docs/reference/exa-mcp.mdhttps://exa.ai/docs/reference/code-search-claude-skill.md
If the task is to add a brand-new Exa integration to a project, Exa's coding-agent docs recommend using Dashboard Onboarding first:
https://dashboard.exa.ai/onboarding
Preferred in this repo
For repo-local automation, prefer this order:
- official JavaScript SDK (
exa-js) via a small Node helper - direct HTTP (
/search,/contents) for low-level debugging and inspection - MCP only when the user specifically wants tool-based agent integration
Operational note:
- if handwritten HTTP fails but the key should work, test the official SDK before concluding that the key is invalid
- official SDK behavior can succeed where a naive raw HTTP request fails due to request-shape or compatibility details
Known-good local helper pattern
This skill ships reusable helper examples at:
scripts/exa-search.mjsscripts/exa-contents.mjs
Use it as a starting point for repo-local helpers.
Recommended workflow:
- keep reusable Exa helpers in the target repo's
scripts/directory - install
exa-jslocally in the workspace; do not assume global npm access - if local tooling lives under
.tools/, resolve packages from there - rely on OpenClaw SecretRef skill injection when running inside OpenClaw
- for manual runs, load
EXA_API_KEYfrom an untracked local secret source - emit compact normalized JSON for downstream agent use
The bundled helper is designed to resolve exa-js from the current working directory or .tools/, so it works in restricted environments that do not allow global installs.
Known-good invocation patterns once copied into a repo:
node scripts/exa-search.mjs 'Altego AI founders' 3
node scripts/exa-contents.mjs 'https://altego.ai/about' highlights 2000
Recommended JSON shape for helper output:
- search helper:
querycountresults[].titleresults[].urlresults[].publishedDateresults[].highlights
- contents helper:
urlmoderesult.titleresult.urlresult.publishedDateresult.authorresult.highlightsresult.text
Decision rule: search vs contents
Use this default rule:
- use
exa.search()or/searchwhen discovering sources - use
exa.getContents()or/contentsonce you know the exact URL - request
highlightsfirst for token efficiency - request full
textonly when deeper reading is required
Minimal SDK usage
import Exa from "exa-js";
const exa = new Exa();
const result = await exa.search("latest developments in AI safety research", {
type: "auto",
numResults: 10,
contents: {
highlights: {
maxCharacters: 4000,
},
},
});
Minimal contents retrieval:
import Exa from "exa-js";
const exa = new Exa();
const { results } = await exa.getContents(["https://altego.ai/about"], {
text: true,
});
Minimal curl usage
Basic search request:
curl -fsS 'https://api.exa.ai/search' \
-H "x-api-key: $EXA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"query": "latest developments in AI safety research",
"type": "auto",
"numResults": 10,
"contents": {
"highlights": {
"maxCharacters": 4000
}
}
}'
Use type: "auto" by default unless the user explicitly needs a different search mode.
Known-good smoke test
To verify the key works against a real company lookup, use this two-step flow.
1. Search for the target
SDK/helper path:
node scripts/exa-search.mjs 'co-founders of altego.ai' 3
Raw HTTP path:
curl -fsS 'https://api.exa.ai/search' \
-H "x-api-key: $EXA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"query": "co-founders of altego.ai",
"type": "auto",
"numResults": 5,
"contents": {
"highlights": {
"maxCharacters": 1200
}
}
}'
This query works as a smoke test, but search results may include noisy AlterEgo matches.
2. Fetch the authoritative page contents
SDK/helper path:
node scripts/exa-contents.mjs 'https://altego.ai/about' text 5000
SDK path:
import Exa from "exa-js";
const exa = new Exa();
const { results } = await exa.getContents(["https://altego.ai/about"], {
text: { maxCharacters: 5000 },
});
Raw HTTP path:
curl -fsS 'https://api.exa.ai/contents' \
-H "x-api-key: $EXA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"urls": ["https://altego.ai/about"],
"text": {
"maxCharacters": 5000
}
}'
At the time this skill was created, that page identified the founders as:
- Mats Horn
- Fabian Linzberger
Use /contents when you already know the URL and want the cleanest answer from a known page.
MCP
Treat MCP as optional, not primary.
Base MCP URL:
https://mcp.exa.ai/mcp
If the client supports key-in-URL remote config:
https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY
Optional tool restriction example:
https://mcp.exa.ai/mcp?exaApiKey=YOUR_API_KEY&tools=web_search_exa,get_code_context_exa,people_search_exa
Codex example:
codex mcp add exa --url https://mcp.exa.ai/mcp
If tools do not appear after config changes, restart the MCP client.
API usage guidance
Prefer these defaults unless the task needs something else:
type: "auto"- compact
highlightsfor search-result evidence /contentsorexa.getContents()for known URLs- domain filters only when the user needs tighter source control
Typical categories:
companypeoplenewsresearch paperpersonal sitefinancial report
Common mistakes to avoid
Avoid outdated or incorrect parameter shapes.
Common mistakes called out in Exa docs include:
- using deprecated
useAutoprompt - using
includeUrlsorexcludeUrlsinstead of domain filters - putting
textorhighlightsat the top level of/searchinstead of undercontents - confusing
/searchpayload shape with/contentspayload shape
When unsure, read the relevant page from references/llms.txt and follow the current docs.