Skip to content

Commit 78a50a5

Browse files
authored
Add TavilySearchTool (#1001)
1 parent 8af17ca commit 78a50a5

File tree

7 files changed

+226
-1
lines changed

7 files changed

+226
-1
lines changed

docs/api/common_tools.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# `pydantic_ai.common_tools`
2+
3+
::: pydantic_ai.common_tools.duckduckgo
4+
5+
::: pydantic_ai.common_tools.tavily

docs/common_tools.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
1+
# Common Tools
2+
13
PydanticAI ships with native tools that can be used to enhance your agent's capabilities.
24

35
## DuckDuckGo Search Tool
46

57
The DuckDuckGo search tool allows you to search the web for information. It is built on top of the
68
[DuckDuckGo API](https://github.com/deedy5/duckduckgo_search).
79

10+
### Installation
11+
12+
To use [`duckduckgo_search_tool`][pydantic_ai.common_tools.duckduckgo.duckduckgo_search_tool], you need to install
13+
[`pydantic-ai-slim`](install.md#slim-install) with the `duckduckgo` optional group:
14+
15+
```bash
16+
pip/uv-add 'pydantic-ai-slim[duckduckgo]'
17+
```
18+
19+
### Usage
20+
21+
Here's an example of how you can use the DuckDuckGo search tool with an agent:
22+
823
```py {title="main.py" test="skip"}
924
from pydantic_ai import Agent
1025
from pydantic_ai.toolsets.duckduckgo import duckduckgo_search_tool
@@ -65,3 +80,62 @@ the 2025 year‑end box‑office tallies are in or to consult a regularly update
6580
Would you like help finding a current source or additional details on where to look for the complete updated list?
6681
"""
6782
```
83+
84+
## Tavily Search Tool
85+
86+
!!! info
87+
Tavily is a paid service, but they have free credits to explore their product.
88+
89+
You need to [sign up for an account](https://app.tavily.com/home) and get an API key to use the Tavily search tool.
90+
91+
The Tavily search tool allows you to search the web for information. It is built on top of the [Tavily API](https://tavily.com/).
92+
93+
### Installation
94+
95+
To use [`tavily_search_tool`][pydantic_ai.common_tools.tavily.tavily_search_tool], you need to install
96+
[`pydantic-ai-slim`](install.md#slim-install) with the `tavily` optional group:
97+
98+
```bash
99+
pip/uv-add 'pydantic-ai-slim[tavily]'
100+
```
101+
102+
### Usage
103+
104+
Here's an example of how you can use the Tavily search tool with an agent:
105+
106+
```py {title="main.py" test="skip"}
107+
import os
108+
109+
from pydantic_ai.agent import Agent
110+
from pydantic_ai.common_tools.tavily import tavily_search_tool
111+
112+
api_key = os.getenv('TAVILY_API_KEY')
113+
assert api_key is not None
114+
115+
116+
agent = Agent(
117+
'openai:o3-mini',
118+
tools=[tavily_search_tool(api_key)],
119+
system_prompt='Search Tavily for the given query and return the results.',
120+
)
121+
122+
result = agent.run_sync('Tell me the top news in the GenAI world, give me links.')
123+
print(result.data)
124+
"""
125+
Here are some of the top recent news articles related to GenAI:
126+
127+
1. How CLEAR users can improve risk analysis with GenAI – Thomson Reuters
128+
Read more: https://legal.thomsonreuters.com/blog/how-clear-users-can-improve-risk-analysis-with-genai/
129+
(This article discusses how CLEAR's new GenAI-powered tool streamlines risk analysis by quickly summarizing key information from various public data sources.)
130+
131+
2. TELUS Digital Survey Reveals Enterprise Employees Are Entering Sensitive Data Into AI Assistants More Than You Think – FT.com
132+
Read more: https://markets.ft.com/data/announce/detail?dockey=600-202502260645BIZWIRE_USPRX____20250226_BW490609-1
133+
(This news piece highlights findings from a TELUS Digital survey showing that many enterprise employees use public GenAI tools and sometimes even enter sensitive data.)
134+
135+
3. The Essential Guide to Generative AI – Virtualization Review
136+
Read more: https://virtualizationreview.com/Whitepapers/2025/02/SNOWFLAKE-The-Essential-Guide-to-Generative-AI.aspx
137+
(This guide provides insights into how GenAI is revolutionizing enterprise strategies and productivity, with input from industry leaders.)
138+
139+
Feel free to click on the links to dive deeper into each story!
140+
"""
141+
```

docs/install.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ pip/uv-add 'pydantic-ai-slim[openai]'
5353
* `groq` — installs `groq` [PyPI ↗](https://pypi.org/project/groq){:target="_blank"}
5454
* `mistral` — installs `mistralai` [PyPI ↗](https://pypi.org/project/mistralai){:target="_blank"}
5555
* `cohere` - installs `cohere` [PyPI ↗](https://pypi.org/project/cohere){:target="_blank"}
56+
* `duckduckgo` - installs `duckduckgo-search` [PyPI ↗](https://pypi.org/project/duckduckgo-search){:target="_blank"}
57+
* `tavily` - installs `tavily-python` [PyPI ↗](https://pypi.org/project/tavily-python){:target="_blank"}
5658

5759
See the [models](models.md) documentation for information on which optional dependencies are required for each model.
5860

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ nav:
4343
- API Reference:
4444
- api/agent.md
4545
- api/tools.md
46+
- api/common_tools.md
4647
- api/result.md
4748
- api/messages.md
4849
- api/exceptions.md
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from dataclasses import dataclass
2+
from typing import Literal, TypedDict
3+
4+
from pydantic import TypeAdapter
5+
6+
from pydantic_ai.tools import Tool
7+
8+
try:
9+
from tavily import AsyncTavilyClient
10+
except ImportError as _import_error:
11+
raise ImportError(
12+
'Please install `tavily-python` to use the Tavily search tool, '
13+
"you can use the `tavily` optional group — `pip install 'pydantic-ai-slim[tavily]'`"
14+
) from _import_error
15+
16+
__all__ = ('tavily_search_tool',)
17+
18+
19+
class TavilySearchResult(TypedDict):
20+
"""A Tavily search result.
21+
22+
See [Tavily Search Endpoint documentation](https://docs.tavily.com/api-reference/endpoint/search)
23+
for more information.
24+
"""
25+
26+
title: str
27+
"""The title of the search result."""
28+
url: str
29+
"""The URL of the search result.."""
30+
content: str
31+
"""A short description of the search result."""
32+
score: float
33+
"""The relevance score of the search result."""
34+
35+
36+
tavily_search_ta = TypeAdapter(list[TavilySearchResult])
37+
38+
39+
@dataclass
40+
class TavilySearchTool:
41+
"""The Tavily search tool."""
42+
43+
client: AsyncTavilyClient
44+
"""The Tavily search client."""
45+
46+
async def __call__(
47+
self,
48+
query: str,
49+
search_deep: Literal['basic', 'advanced'] = 'basic',
50+
topic: Literal['general', 'news'] = 'general',
51+
time_range: Literal['day', 'week', 'month', 'year', 'd', 'w', 'm', 'y'] | None = None,
52+
):
53+
"""Searches Tavily for the given query and returns the results.
54+
55+
Args:
56+
query: The search query to execute with Tavily.
57+
search_deep: The depth of the search.
58+
topic: The category of the search.
59+
time_range: The time range back from the current date to filter results.
60+
61+
Returns:
62+
The search results.
63+
"""
64+
results = await self.client.search(query, search_depth=search_deep, topic=topic, time_range=time_range) # type: ignore[reportUnknownMemberType]
65+
if not results['results']:
66+
raise RuntimeError('No search results found.')
67+
return tavily_search_ta.validate_python(results['results'])
68+
69+
70+
def tavily_search_tool(api_key: str):
71+
"""Creates a Tavily search tool.
72+
73+
Args:
74+
api_key: The Tavily API key.
75+
76+
You can get one by signing up at [https://app.tavily.com/home](https://app.tavily.com/home).
77+
"""
78+
return Tool(
79+
TavilySearchTool(client=AsyncTavilyClient(api_key)).__call__,
80+
name='tavily_search',
81+
description='Searches Tavily for the given query and returns the results.',
82+
)

pydantic_ai_slim/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ groq = ["groq>=0.12.0"]
5353
mistral = ["mistralai>=1.2.5"]
5454
# Tools
5555
duckduckgo = ["duckduckgo-search>=7.0.0"]
56+
tavily = ["tavily-python>=0.5.0"]
5657

5758
[dependency-groups]
5859
dev = [

uv.lock

Lines changed: 61 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)