Exa Python SDK
The official Python SDK for Exa, the web search API for AI.
Install
pip install exa-py
Requires Python 3.9+
Quick Start
from exa_py import Exa
exa = Exa(api_key="your-api-key")
# Search the web
results = exa.search(
"blog post about artificial intelligence",
type="auto",
contents={"highlights": True}
)
# Ask a question
response = exa.answer("What is the capital of France?")
Search
results = exa.search(
"machine learning startups",
contents={"highlights": True}
)
results = exa.search(
"climate tech news",
num_results=20,
start_published_date="2024-01-01",
include_domains=["techcrunch.com", "wired.com"],
contents={"highlights": True}
)
results = exa.search(
"What are the latest battery breakthroughs?",
type="auto",
system_prompt="Prefer official sources and avoid duplicate results",
output_schema={
"type": "object",
"properties": {
"summary": {"type": "string"},
"key_companies": {"type": "array", "items": {"type": "string"}},
},
"required": ["summary", "key_companies"],
},
)
print(results.output.content if results.output else None)
for chunk in exa.stream_search(
"What are the latest battery breakthroughs?",
type="auto",
):
if chunk.content:
print(chunk.content, end="", flush=True)
Search output_schema modes:
{"type": "text", "description": "..."}: return plain text inoutput.content{"type": "object", ...}: return structured JSON inoutput.content
system_prompt and output_schema are supported on every search type.
Search streaming is available via stream_search(...), which yields OpenAI-style chat completion chunks.
For type: "object", search currently enforces:
- max nesting depth:
2 - max total properties:
10
Deep search variants that also support additional_queries:
deep-litedeepdeep-reasoning
Contents
results = exa.get_contents(
["https://docs.exa.ai"],
text=True
)
results = exa.get_contents(
["https://arxiv.org/abs/2303.08774"],
highlights=True
)
Answer
response = exa.answer("What caused the 2008 financial crisis?")
print(response.answer)
for chunk in exa.stream_answer("Explain quantum computing"):
print(chunk, end="", flush=True)
Agent API
The Agent API is available without a beta header.
run = exa.agent.runs.create(
query="Find engineering leaders at AI infrastructure companies that raised a Series A or B in the last 6 months.",
output_schema={
"type": "object",
"properties": {
"people": {
"type": "array",
"maxItems": 10,
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"contact_email": {"type": "string", "format": "email"},
"linkedin_url": {"type": "string", "format": "uri"},
},
"required": ["name", "linkedin_url"],
},
}
},
"required": ["people"],
},
effort="auto",
)
run = exa.agent.runs.poll_until_finished(run.id)
print(run.output.structured if run.output else None)
For Agent Max, use the beta namespace and pass the beta token explicitly:
from exa_py import Exa
from exa_py.agent import AGENT_MAX_EFFORT_BETA
exa = Exa()
run = exa.beta.agent.runs.create(
query="Find all companies building browser automation tools in the United States.",
effort="max",
budget={"maxCostDollars": 10},
betas=[AGENT_MAX_EFFORT_BETA],
)
Agent Monitors (Beta)
Agent Monitors use the beta namespace and require the AGENT_MONITORS_BETA_HEADER beta identifier (agent-monitors-2026-08-04).
An Agent Monitor keeps a table of entities × fields fresh on a cadence: static fields are answered once per entity over the live web, dynamic fields are tracked from news on every refresh.
from exa_py.agent import AGENT_MONITORS_BETA_HEADER
betas = [AGENT_MONITORS_BETA_HEADER]
# Create a monitor. Creation is async: it returns with status "creating"
# and becomes "active" once the first refresh completes.
monitor = exa.beta.agent.monitors.create(
betas=betas,
cadence="7d",
entities=[
{"name": "Acme Corp", "domain": "acme.com"},
{"name": "Globex", "domain": "globex.com"},
],
fields=[
{"name": "funding", "description": "New funding rounds"}, # dynamic by default
{"name": "ceo", "description": "The company's current CEO", "mode": "static"},
],
idempotency_key="my-monitor-1", # safe retries: same key returns the same monitor
)
# Page the monitor's current entities and their contents.
for view in exa.beta.agent.monitors.entities.list_all(monitor.id, betas=betas):
print(view.entity.name, view.contents)
# Follow the content change feed (resume later from the page's next_cursor).
changes = exa.beta.agent.monitors.changes.list(
monitor.id,
betas=betas,
since="2026-01-01T00:00:00Z",
)
# One-shot stateless snapshot of a past news window — no monitor created.
snapshot = exa.beta.agent.monitors.snapshots.create_and_wait(
betas=betas,
entities=[{"name": "Acme Corp", "domain": "acme.com"}],
fields=[{"name": "funding", "description": "New funding rounds"}], # dynamic by default
start_date="2026-01-01",
end_date="2026-01-08",
)
print(snapshot.data)
# Add entities, inspect refresh progress, clean up.
exa.beta.agent.monitors.entities.add(
monitor.id,
betas=betas,
entities=[{"name": "Initech", "domain": "initech.com"}],
)
current = exa.beta.agent.monitors.get(monitor.id, betas=betas)
print(current.status, current.refresh, current.usage)
exa.beta.agent.monitors.delete(monitor.id, betas=betas)
Async
from exa_py import AsyncExa
exa = AsyncExa(api_key="your-api-key")
results = await exa.search("async search example", contents={"highlights": True})
More
See the full documentation for all features including websets, filters, and advanced options.
Release files for exa-py 2.18.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| exa_py-2.18.1.tar.gz | 73.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| exa_py-2.18.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 175.9 kB
Release files / exa_py-2.18.1.tar.gz
| Download URL | exa_py-2.18.1.tar.gz |
|---|---|
| Size | 73.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f571f001ca8122b4432ef795b1c5c0afe97b5d20e84d4a1b769b9a888141e9c7
|
|
BLAKE2b-256 checksum How to use checksums |
583416d6d767889fdb86735d5be34dcc5db9f456870815bf3d0ddc8d5fdfbfec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Release files / exa_py-2.18.1-py3-none-any.whl
| Download URL | exa_py-2.18.1-py3-none-any.whl |
|---|---|
| Size | 102.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
98a43c8c598b0360ee8c1a014e7433ae92dcbf58af3d40cac701e145c6e2680e
|
|
BLAKE2b-256 checksum How to use checksums |
e15fbdd2230640e2792b3048e69bbb70ab65b8ddf8e51e2ef8880d8cce466a1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|