If you’re an LLM, read LLMs.txtOpen in playgroundOpen in playgroundRead the guideOpen in playgroundOpen in playgroundOpen in playground
Add Exa to your agent
Get started in under a minute
Examples
from exa_py import Exa
exa = Exa()
result = exa.search(
"companies selling AI voice agents to dental practices",
contents={"highlights": True},
)
for hit in result.results:
print(hit.title, hit.url)
print(hit.highlights)
import Exa from "exa-js";
const exa = new Exa();
const result = await exa.search(
"companies selling AI voice agents to dental practices",
{ contents: { highlights: true } },
);
for (const hit of result.results) {
console.log(hit.title, hit.url);
console.log(hit.highlights);
}
curl -s -X POST "https://api.exa.ai/search" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d '{
"query": "companies selling AI voice agents to dental practices",
"contents": { "highlights": true }
}'
from exa_py import Exa
exa = Exa()
result = exa.search(
"Who is Anthropic's CEO, when was the company founded, and where is it headquartered?",
type="deep",
output_schema={
"type": "object",
"required": ["company", "ceo", "founded_year", "headquarters"],
"properties": {
"company": {"type": "string"},
"ceo": {"type": "string"},
"founded_year": {"type": "number"},
"headquarters": {"type": "string"},
},
},
)
print(result.output.content)
import Exa from "exa-js";
const exa = new Exa();
const result = await exa.search(
"Who is Anthropic's CEO, when was the company founded, and where is it headquartered?",
{
type: "deep",
outputSchema: {
type: "object",
required: ["company", "ceo", "founded_year", "headquarters"],
properties: {
company: { type: "string" },
ceo: { type: "string" },
founded_year: { type: "number" },
headquarters: { type: "string" },
},
},
},
);
console.log(result.output?.content);
curl -s -X POST "https://api.exa.ai/search" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d '{
"query": "Who is Anthropic'\''s CEO, when was the company founded, and where is it headquartered?",
"type": "deep",
"outputSchema": {
"type": "object",
"required": ["company", "ceo", "founded_year", "headquarters"],
"properties": {
"company": { "type": "string" },
"ceo": { "type": "string" },
"founded_year": { "type": "number" },
"headquarters": { "type": "string" }
}
}
}'
from exa_py import Exa
from openai import OpenAI
exa = Exa()
openai = OpenAI()
messages = [{"role": "user", "content": "What's the latest on AI chips?"}]
completion = openai.chat.completions.create(
model="gpt-5.6",
messages=messages,
tools=[exa.openai.web_search(), exa.openai.get_contents()],
)
message = completion.choices[0].message
messages.append(message)
messages += exa.openai.handle_tool_calls(message)
completion = openai.chat.completions.create(model="gpt-5.6", messages=messages)
print(completion.choices[0].message.content)
import Exa from "exa-js";
import { OpenAI } from "openai";
const exa = new Exa();
const openai = new OpenAI();
const messages = [{ role: "user", content: "What's the latest on AI chips?" }];
let completion = await openai.chat.completions.create({
model: "gpt-5.6",
messages,
tools: [exa.openai.webSearch(), exa.openai.getContents()],
});
const message = completion.choices[0].message;
messages.push(message, ...(await exa.openai.handleToolCalls(message)));
completion = await openai.chat.completions.create({ model: "gpt-5.6", messages });
console.log(completion.choices[0].message.content);
# 1. Offer the model an Exa search tool and let it pick the query.
USER_MSG='{ "role": "user", "content": "What'\''s the latest on AI chips?" }'
TOOLS='[{ "type": "function", "function": {
"name": "web_search",
"description": "Search the web and return the most relevant pages.",
"parameters": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] }
}}]'
ASSISTANT="$(curl -s "https://api.openai.com/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d "{ \"model\": \"gpt-5.6\", \"messages\": [$USER_MSG], \"tools\": $TOOLS }" \
| python3 -c 'import json,sys; print(json.dumps(json.load(sys.stdin)["choices"][0]["message"]))')"
# 2. Run the tool call against Exa.
SEARCH_BODY="$(echo "$ASSISTANT" | python3 -c '
import json, sys
args = json.loads(json.load(sys.stdin)["tool_calls"][0]["function"]["arguments"])
print(json.dumps({"query": args["query"], "contents": {"highlights": True}}))')"
RESULTS="$(curl -s -X POST "https://api.exa.ai/search" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d "$SEARCH_BODY")"
# 3. Hand the results back to the model for the final answer.
TOOL_MSG="$(echo "$ASSISTANT" | python3 -c '
import json, sys
assistant = json.load(sys.stdin)
print(json.dumps({"role": "tool", "tool_call_id": assistant["tool_calls"][0]["id"], "content": sys.argv[1]}))' "$RESULTS")"
curl -s "https://api.openai.com/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d "{ \"model\": \"gpt-5.6\", \"messages\": [$USER_MSG, $ASSISTANT, $TOOL_MSG] }" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["choices"][0]["message"]["content"])'
from exa_py import Exa
exa = Exa()
result = exa.get_contents(
["https://www.anthropic.com/pricing"],
highlights={"query": "enterprise plan features and pricing"},
)
print(result.results[0].highlights)
import Exa from "exa-js";
const exa = new Exa();
const result = await exa.getContents(
["https://www.anthropic.com/pricing"],
{
highlights: {
query: "enterprise plan features and pricing",
},
},
);
console.log(result.results[0].highlights);
curl -s -X POST "https://api.exa.ai/contents" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d '{
"ids": ["https://www.anthropic.com/pricing"],
"highlights": {
"query": "enterprise plan features and pricing"
}
}'
import json
from exa_py import Exa
exa = Exa()
run = exa.agent.runs.create(
query="Find 10 seed-stage companies building infrastructure for AI coding agents.",
output_schema={
"type": "object",
"required": ["companies"],
"properties": {
"companies": {
"type": "array",
"maxItems": 10,
"items": {
"type": "object",
"required": ["name", "website"],
"properties": {
"name": {"type": "string"},
"website": {"type": "string", "format": "uri"},
},
},
}
},
},
effort="auto",
)
run = exa.agent.runs.poll_until_finished(run.id)
print(json.dumps(run.output.structured if run.output else None, indent=2))
import Exa from "exa-js";
const exa = new Exa();
const run = await exa.agent.runs.create({
query:
"Find 10 seed-stage companies building infrastructure for AI coding agents.",
outputSchema: {
type: "object",
required: ["companies"],
properties: {
companies: {
type: "array",
maxItems: 10,
items: {
type: "object",
required: ["name", "website"],
properties: {
name: { type: "string" },
website: { type: "string", format: "uri" },
},
},
},
},
},
effort: "auto",
});
const completedRun = await exa.agent.runs.pollUntilFinished(run.id);
console.log(JSON.stringify(completedRun.output?.structured, null, 2));
RUN_ID="$(curl -s -X POST "https://api.exa.ai/agent/runs" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d '{
"query": "Find 10 seed-stage companies building infrastructure for AI coding agents.",
"effort": "auto",
"outputSchema": {
"type": "object",
"required": ["companies"],
"properties": {
"companies": {
"type": "array",
"maxItems": 10,
"items": {
"type": "object",
"required": ["name", "website"],
"properties": {
"name": { "type": "string" },
"website": { "type": "string", "format": "uri" }
}
}
}
}
}
}' | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
while true; do
RUN_JSON="$(curl -s "https://api.exa.ai/agent/runs/$RUN_ID" \
-H "Authorization: Bearer $EXA_API_KEY")"
STATUS="$(printf '%s' "$RUN_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])')"
if [ "$STATUS" = "completed" ]; then
printf '%s' "$RUN_JSON" | python3 -c 'import json,sys; print(json.dumps(json.load(sys.stdin)["output"]["structured"], indent=2))'
break
elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
printf '%s' "$RUN_JSON"
break
fi
sleep 4
done
from exa_py import Exa
exa = Exa()
run = exa.agent.runs.create(
query=(
"Analyze how the EU AI Act affects startups selling AI products in Europe. "
"Cover key dates, obligations, and practical risks, citing official sources."
),
effort="medium",
)
run = exa.agent.runs.poll_until_finished(run.id)
print(run.output.text if run.output else None)
import Exa from "exa-js";
const exa = new Exa();
const run = await exa.agent.runs.create({
query:
"Analyze how the EU AI Act affects startups selling AI products in Europe. Cover key dates, obligations, and practical risks, citing official sources.",
effort: "medium",
});
const completedRun = await exa.agent.runs.pollUntilFinished(run.id);
console.log(completedRun.output?.text);
RUN_ID="$(curl -s -X POST "https://api.exa.ai/agent/runs" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EXA_API_KEY" \
-d '{
"query": "Analyze how the EU AI Act affects startups selling AI products in Europe. Cover key dates, obligations, and practical risks, citing official sources.",
"effort": "medium"
}' | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
while true; do
RUN_JSON="$(curl -s "https://api.exa.ai/agent/runs/$RUN_ID" \
-H "Authorization: Bearer $EXA_API_KEY")"
STATUS="$(printf '%s' "$RUN_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])')"
if [ "$STATUS" = "completed" ]; then
printf '%s' "$RUN_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["output"]["text"])'
break
elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
printf '%s' "$RUN_JSON"
break
fi
sleep 4
done