Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
728f634
feat: add Exa tools integration
10ishq Dec 15, 2025
b84063b
refactor(exa): migrate exa_search_tool from search_and_contents() to …
10ishq Dec 16, 2025
573e47a
refactor(exa): migrate exa_find_similar_tool from find_similar_and_co…
10ishq Dec 16, 2025
07acf21
feat(exa): add 'fast' and 'deep' search types to exa_search_tool
10ishq Dec 16, 2025
76eaff6
feat(exa): add max_characters param to exa_search_tool for token control
10ishq Dec 16, 2025
034e70e
chore(exa): require exa-py>=2.0.0 for new API
10ishq Dec 16, 2025
757039a
refactor(exa): use list comprehensions per review feedback
10ishq Dec 16, 2025
281516d
feat(exa): add ExaToolset with shared client per review feedback
10ishq Dec 16, 2025
4acc796
docs(exa): add Exa tools to common-tools.md per review feedback
10ishq Dec 16, 2025
58b1da4
fix(exa): add type ignore comments for pyright compatibility
10ishq Dec 17, 2025
e978675
fix(exa): add exa-py to dev deps and type ignores for CI compatibility
10ishq Dec 17, 2025
7b99546
fix(exa): add more type ignores and update lockfile for CI
10ishq Dec 17, 2025
e4e7547
refactor(exa): dedupe factory functions and update docs per review
10ishq Dec 18, 2025
a2ca0dc
fix(exa): update pyright ignores for exa-py partial types
10ishq Dec 18, 2025
5f6a2e5
style(exa): apply ruff formatting
10ishq Dec 18, 2025
0f0e0e1
feat(exa): add @overload for type safety and update API docs
10ishq Dec 21, 2025
b31c889
fix(exa): add pragma no cover for CI coverage
10ishq Dec 22, 2025
6d434c5
fix(exa): omit exa.py from coverage (follows ext/aci.py pattern)
10ishq Dec 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api/common_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

::: pydantic_ai.common_tools.duckduckgo

::: pydantic_ai.common_tools.exa

::: pydantic_ai.common_tools.tavily
82 changes: 82 additions & 0 deletions docs/common-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,85 @@ Here are some of the top recent news articles related to GenAI:
Feel free to click on the links to dive deeper into each story!
"""
```

## Exa Search Tool

!!! info
Exa is a paid service with free credits to explore their product.

You need to [sign up for an account](https://dashboard.exa.ai) and get an API key to use the Exa tools.

Exa is a neural search engine that finds high-quality, relevant results across billions of web pages.
It provides several tools including web search, finding similar pages, content retrieval, and AI-powered answers.

### Installation

To use Exa tools, you need to install [`pydantic-ai-slim`](install.md#slim-install) with the `exa` optional group:

```bash
pip/uv-add "pydantic-ai-slim[exa]"
```

### Usage

You can use Exa tools individually or as a toolset. The following tools are available:

- [`exa_search_tool`][pydantic_ai.common_tools.exa.exa_search_tool]: Search the web with various search types (auto, keyword, neural, fast, deep)
- [`exa_find_similar_tool`][pydantic_ai.common_tools.exa.exa_find_similar_tool]: Find pages similar to a given URL
- [`exa_get_contents_tool`][pydantic_ai.common_tools.exa.exa_get_contents_tool]: Get full text content from URLs
- [`exa_answer_tool`][pydantic_ai.common_tools.exa.exa_answer_tool]: Get AI-powered answers with citations
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make these links work we need to update docs/api/common_tools.md

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Added ::: pydantic_ai.common_tools.exa to docs/api/common_tools.md so the mkdocs cross-references resolve correctly.


#### Using Individual Tools

```py {title="exa_search.py" test="skip"}
import os

from pydantic_ai import Agent
from pydantic_ai.common_tools.exa import exa_search_tool

api_key = os.getenv('EXA_API_KEY')
assert api_key is not None

agent = Agent(
'openai:gpt-4o',
tools=[exa_search_tool(api_key, num_results=5, max_characters=1000)],
system_prompt='Search the web for information using Exa.',
)

result = agent.run_sync('What are the latest developments in quantum computing?')
print(result.output)
```

#### Using ExaToolset

For better efficiency when using multiple Exa tools, use [`ExaToolset`][pydantic_ai.common_tools.exa.ExaToolset]
which shares a single API client across all tools. You can configure which tools to include:

```py {title="exa_toolset.py" test="skip"}
import os

from pydantic_ai import Agent
from pydantic_ai.common_tools.exa import ExaToolset

api_key = os.getenv('EXA_API_KEY')
assert api_key is not None

toolset = ExaToolset(
api_key,
num_results=5,
max_characters=1000, # Limit text content to control token usage
include_search=True, # Include the search tool (default: True)
include_find_similar=True, # Include the find_similar tool (default: True)
include_get_contents=False, # Exclude the get_contents tool
include_answer=True, # Include the answer tool (default: True)
)

agent = Agent(
'openai:gpt-4o',
toolsets=[toolset],
system_prompt='You have access to Exa search tools to find information on the web.',
)

result = agent.run_sync('Find recent AI research papers and summarize the key findings.')
print(result.output)
```
1 change: 1 addition & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pip/uv-add "pydantic-ai-slim[openai]"
* `outlines-vllm-offline` - installs [Outlines Model](models/outlines.md) dependencies `outlines` [PyPI ↗](https://pypi.org/project/outlines){:target="_blank"} and `vllm` [PyPI ↗](https://pypi.org/project/vllm){:target="_blank"}
* `duckduckgo` - installs [DuckDuckGo Search Tool](common-tools.md#duckduckgo-search-tool) dependency `ddgs` [PyPI ↗](https://pypi.org/project/ddgs){:target="_blank"}
* `tavily` - installs [Tavily Search Tool](common-tools.md#tavily-search-tool) dependency `tavily-python` [PyPI ↗](https://pypi.org/project/tavily-python){:target="_blank"}
* `exa` - installs [Exa Search Tool](common-tools.md#exa-search-tool) dependency `exa-py` [PyPI ↗](https://pypi.org/project/exa-py){:target="_blank"}
* `cli` - installs [CLI](cli.md) dependencies `rich` [PyPI ↗](https://pypi.org/project/rich){:target="_blank"}, `prompt-toolkit` [PyPI ↗](https://pypi.org/project/prompt-toolkit){:target="_blank"}, and `argcomplete` [PyPI ↗](https://pypi.org/project/argcomplete){:target="_blank"}
* `mcp` - installs [MCP](mcp/client.md) dependency `mcp` [PyPI ↗](https://pypi.org/project/mcp){:target="_blank"}
* `fastmcp` - installs [FastMCP](mcp/fastmcp-client.md) dependency `fastmcp` [PyPI ↗](https://pypi.org/project/fastmcp){:target="_blank"}
Expand Down
Loading