# pydantic\_ai.common\_tools

### DuckDuckGoResult

**Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)

A DuckDuckGo search result.

#### Attributes

##### title

The title of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### href

The URL of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### body

The body of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

### DuckDuckGoSearchTool

The DuckDuckGo search tool.

#### Attributes

##### client

The DuckDuckGo search client.

**Type:** `DDGS`

##### max\_results

The maximum number of results. If None, returns results only from the first response.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None)

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(query: str) -> list[DuckDuckGoResult]
```

Searches DuckDuckGo for the given query and returns the results.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[`DuckDuckGoResult`\] -- The search results.

###### Parameters

**`query`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The query to search for.

### duckduckgo\_search\_tool

```python
def duckduckgo_search_tool(
    duckduckgo_client: DDGS | None = None,
    max_results: int | None = None,
)
```

Creates a DuckDuckGo search tool.

#### Parameters

**`duckduckgo_client`** : `DDGS` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The DuckDuckGo search client.

**`max_results`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The maximum number of results. If None, returns results only from the first response.

Exa tools for Pydantic AI agents.

Provides web search, content retrieval, and AI-powered answer capabilities using the Exa API, a neural search engine that finds high-quality, relevant results across billions of web pages.

### ExaSearchResult

**Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)

An Exa search result with content.

See [Exa Search API documentation](https://docs.exa.ai/reference/search) for more information.

#### Attributes

##### title

The title of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### url

The URL of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### published\_date

The published date of the content, if available.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)

##### author

The author of the content, if available.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)

##### text

The text content of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

### ExaAnswerResult

**Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)

An Exa answer result with citations.

See [Exa Answer API documentation](https://docs.exa.ai/reference/answer) for more information.

#### Attributes

##### answer

The AI-generated answer to the query.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### citations

Citations supporting the answer.

**Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\]

### ExaContentResult

**Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)

Content retrieved from a URL.

See [Exa Contents API documentation](https://docs.exa.ai/reference/get-contents) for more information.

#### Attributes

##### url

The URL of the content.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### title

The title of the page.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### text

The text content of the page.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### author

The author of the content, if available.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)

##### published\_date

The published date of the content, if available.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)

### ExaSearchTool

The Exa search tool.

#### Attributes

##### client

The Exa async client.

**Type:** `AsyncExa`

##### num\_results

The number of results to return.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int)

##### max\_characters

Maximum characters of text content per result, or None for no limit.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None)

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(
    query: str,
    search_type: Literal['auto', 'keyword', 'neural', 'fast', 'deep'] = 'auto',
) -> list[ExaSearchResult]
```

Searches Exa for the given query and returns the results with content.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[`ExaSearchResult`\] -- The search results with text content.

###### Parameters

**`query`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The search query to execute with Exa.

**`search_type`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['auto', 'keyword', 'neural', 'fast', 'deep'\] _Default:_ `'auto'`

The type of search to perform. 'auto' automatically chooses the best search type, 'keyword' for exact matches, 'neural' for semantic search, 'fast' for speed-optimized search, 'deep' for comprehensive multi-query search.

### ExaFindSimilarTool

The Exa find similar tool.

#### Attributes

##### client

The Exa async client.

**Type:** `AsyncExa`

##### num\_results

The number of results to return.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int)

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(url: str, exclude_source_domain: bool = True) -> list[ExaSearchResult]
```

Finds pages similar to the given URL and returns them with content.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[`ExaSearchResult`\] -- Similar pages with text content.

###### Parameters

**`url`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The URL to find similar pages for.

**`exclude_source_domain`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True`

Whether to exclude results from the same domain as the input URL. Defaults to True.

### ExaGetContentsTool

The Exa get contents tool.

#### Attributes

##### client

The Exa async client.

**Type:** `AsyncExa`

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(urls: list[str]) -> list[ExaContentResult]
```

Gets the content of the specified URLs.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[`ExaContentResult`\] -- The content of each URL.

###### Parameters

**`urls`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\]

A list of URLs to get content for.

### ExaAnswerTool

The Exa answer tool.

#### Attributes

##### client

The Exa async client.

**Type:** `AsyncExa`

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(query: str) -> ExaAnswerResult
```

Generates an AI-powered answer to the query with citations.

###### Returns

`ExaAnswerResult` -- An answer with supporting citations from web sources.

###### Parameters

**`query`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The question to answer.

### ExaToolset

**Bases:** [`FunctionToolset`](/docs/ai/api/pydantic-ai/toolsets/#pydantic_ai.toolsets.FunctionToolset)

A toolset that provides Exa search tools with a shared client.

This is more efficient than creating individual tools when using multiple Exa tools, as it shares a single API client across all tools.

Example:

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

toolset = ExaToolset(api_key='your-api-key')
agent = Agent('openai:gpt-5.2', toolsets=[toolset])
```

#### Methods

##### \_\_init\_\_

```python
def __init__(
    api_key: str,
    num_results: int = 5,
    max_characters: int | None = None,
    include_search: bool = True,
    include_find_similar: bool = True,
    include_get_contents: bool = True,
    include_answer: bool = True,
    id: str | None = None,
)
```

Creates an Exa toolset with a shared client.

###### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The Exa API key.

You can get one by signing up at [https://dashboard.exa.ai](https://dashboard.exa.ai).

**`num_results`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `5`

The number of results to return for search and find\_similar. Defaults to 5.

**`max_characters`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Maximum characters of text content per result. Use this to limit token usage. Defaults to None (no limit).

**`include_search`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True`

Whether to include the search tool. Defaults to True.

**`include_find_similar`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True`

Whether to include the find\_similar tool. Defaults to True.

**`include_get_contents`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True`

Whether to include the get\_contents tool. Defaults to True.

**`include_answer`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True`

Whether to include the answer tool. Defaults to True.

**`id`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Optional ID for the toolset, used for durable execution environments.

### exa\_search\_tool

```python
def exa_search_tool(
    api_key: str,
    num_results: int = 5,
    max_characters: int | None = None,
) -> Tool[Any]
def exa_search_tool(
    client: AsyncExa,
    num_results: int = 5,
    max_characters: int | None = None,
) -> Tool[Any]
```

Creates an Exa search tool.

#### Returns

[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

#### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The Exa API key. Required if `client` is not provided.

You can get one by signing up at [https://dashboard.exa.ai](https://dashboard.exa.ai).

**`client`** : `AsyncExa` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

An existing AsyncExa client. If provided, `api_key` is ignored. This is useful for sharing a client across multiple tools.

**`num_results`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `5`

The number of results to return. Defaults to 5.

**`max_characters`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

Maximum characters of text content per result. Use this to limit token usage. Defaults to None (no limit).

### exa\_find\_similar\_tool

```python
def exa_find_similar_tool(api_key: str, num_results: int = 5) -> Tool[Any]
def exa_find_similar_tool(client: AsyncExa, num_results: int = 5) -> Tool[Any]
```

Creates an Exa find similar tool.

#### Returns

[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

#### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The Exa API key. Required if `client` is not provided.

You can get one by signing up at [https://dashboard.exa.ai](https://dashboard.exa.ai).

**`client`** : `AsyncExa` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

An existing AsyncExa client. If provided, `api_key` is ignored. This is useful for sharing a client across multiple tools.

**`num_results`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `5`

The number of similar results to return. Defaults to 5.

### exa\_get\_contents\_tool

```python
def exa_get_contents_tool(api_key: str) -> Tool[Any]
def exa_get_contents_tool(client: AsyncExa) -> Tool[Any]
```

Creates an Exa get contents tool.

#### Returns

[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

#### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The Exa API key. Required if `client` is not provided.

You can get one by signing up at [https://dashboard.exa.ai](https://dashboard.exa.ai).

**`client`** : `AsyncExa` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

An existing AsyncExa client. If provided, `api_key` is ignored. This is useful for sharing a client across multiple tools.

### exa\_answer\_tool

```python
def exa_answer_tool(api_key: str) -> Tool[Any]
def exa_answer_tool(client: AsyncExa) -> Tool[Any]
```

Creates an Exa answer tool.

#### Returns

[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

#### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The Exa API key. Required if `client` is not provided.

You can get one by signing up at [https://dashboard.exa.ai](https://dashboard.exa.ai).

**`client`** : `AsyncExa` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

An existing AsyncExa client. If provided, `api_key` is ignored. This is useful for sharing a client across multiple tools.

### TavilySearchResult

**Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)

A Tavily search result.

See [Tavily Search Endpoint documentation](https://docs.tavily.com/api-reference/endpoint/search) for more information.

#### Attributes

##### title

The title of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### url

The URL of the search result..

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### content

A short description of the search result.

**Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str)

##### score

The relevance score of the search result.

**Type:** [`float`](https://docs.python.org/3/library/functions.html#float)

### TavilySearchTool

The Tavily search tool.

#### Attributes

##### client

The Tavily search client.

**Type:** `AsyncTavilyClient`

##### max\_results

The maximum number of results. If None, the Tavily default is used.

**Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None`

#### Methods

##### \_\_call\_\_

`@async`

```python
def __call__(
    query: str,
    search_depth: Literal['basic', 'advanced', 'fast', 'ultra-fast'] = 'basic',
    topic: Literal['general', 'news', 'finance'] = 'general',
    time_range: Literal['day', 'week', 'month', 'year'] | None = None,
    include_domains: list[str] | None = None,
    exclude_domains: list[str] | None = None,
) -> list[TavilySearchResult]
```

Searches Tavily for the given query and returns the results.

###### Returns

[`list`](https://docs.python.org/3/glossary.html#term-list)\[`TavilySearchResult`\] -- A list of search results from Tavily.

###### Parameters

**`query`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str)

The search query to execute with Tavily.

**`search_depth`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['basic', 'advanced', 'fast', 'ultra-fast'\] _Default:_ `'basic'`

The depth of the search.

**`topic`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['general', 'news', 'finance'\] _Default:_ `'general'`

The category of the search.

**`time_range`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['day', 'week', 'month', 'year'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The time range back from the current date to filter results.

**`include_domains`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

List of domains to specifically include in the search results.

**`exclude_domains`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

List of domains to specifically exclude from the search results.

### tavily\_search\_tool

```python
def tavily_search_tool(
    api_key: str,
    max_results: int | None = None,
    search_depth: Literal['basic', 'advanced', 'fast', 'ultra-fast'] = _UNSET,
    topic: Literal['general', 'news', 'finance'] = _UNSET,
    time_range: Literal['day', 'week', 'month', 'year'] | None = _UNSET,
    include_domains: list[str] | None = _UNSET,
    exclude_domains: list[str] | None = _UNSET,
) -> Tool[Any]
def tavily_search_tool(
    client: AsyncTavilyClient,
    max_results: int | None = None,
    search_depth: Literal['basic', 'advanced', 'fast', 'ultra-fast'] = _UNSET,
    topic: Literal['general', 'news', 'finance'] = _UNSET,
    time_range: Literal['day', 'week', 'month', 'year'] | None = _UNSET,
    include_domains: list[str] | None = _UNSET,
    exclude_domains: list[str] | None = _UNSET,
) -> Tool[Any]
```

Creates a Tavily search tool.

`max_results` is always developer-controlled and does not appear in the LLM tool schema. Other parameters, when provided, are fixed for all searches and hidden from the LLM's tool schema. Parameters left unset remain available for the LLM to set per-call.

#### Returns

[`Tool`](/docs/ai/api/pydantic-ai/tools/#pydantic_ai.tools.Tool)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]

#### Parameters

**`api_key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The Tavily API key. Required if `client` is not provided.

You can get one by signing up at [https://app.tavily.com/home](https://app.tavily.com/home).

**`client`** : `AsyncTavilyClient` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

An existing AsyncTavilyClient. If provided, `api_key` is ignored. This is useful for sharing a client across multiple tool instances.

**`max_results`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None`

The maximum number of results. If None, the Tavily default is used.

**`search_depth`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['basic', 'advanced', 'fast', 'ultra-fast'\] _Default:_ `_UNSET`

The depth of the search.

**`topic`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['general', 'news', 'finance'\] _Default:_ `_UNSET`

The category of the search.

**`time_range`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['day', 'week', 'month', 'year'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_UNSET`

The time range back from the current date to filter results.

**`include_domains`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_UNSET`

List of domains to specifically include in the search results.

**`exclude_domains`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_UNSET`

List of domains to specifically exclude from the search results.