diff --git a/docs/ar/tools/search-research/tavilyextractortool.mdx b/docs/ar/tools/search-research/tavilyextractortool.mdx index e251f7e9a..3b5eb1aed 100644 --- a/docs/ar/tools/search-research/tavilyextractortool.mdx +++ b/docs/ar/tools/search-research/tavilyextractortool.mdx @@ -12,7 +12,7 @@ mode: "wide" لاستخدام `TavilyExtractorTool`، تحتاج إلى تثبيت مكتبة `tavily-python`: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` تحتاج أيضاً إلى تعيين مفتاح Tavily API كمتغير بيئة: diff --git a/docs/ar/tools/search-research/tavilyresearchtool.mdx b/docs/ar/tools/search-research/tavilyresearchtool.mdx new file mode 100644 index 000000000..34fdc8c66 --- /dev/null +++ b/docs/ar/tools/search-research/tavilyresearchtool.mdx @@ -0,0 +1,125 @@ +--- +title: "Tavily Research Tool" +description: "Run multi-step research tasks and get cited reports using the Tavily Research API" +icon: "flask" +mode: "wide" +--- + +The `TavilyResearchTool` lets CrewAI agents kick off Tavily research tasks, returning a synthesized, cited report (or a stream of progress events) instead of raw search results. Use it when an agent needs an investigative answer rather than a single web search. + +## Installation + +To use the `TavilyResearchTool`, install the `tavily-python` library alongside `crewai-tools`: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Set your Tavily API key: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +Get an API key at [https://app.tavily.com/](https://app.tavily.com/) (sign up, then create a key). + +## Example Usage + +```python +import os +from crewai import Agent, Crew, Task +from crewai_tools import TavilyResearchTool + +# Ensure TAVILY_API_KEY is set in your environment +# os.environ["TAVILY_API_KEY"] = "YOUR_API_KEY" + +tavily_tool = TavilyResearchTool() + +researcher = Agent( + role="Research Analyst", + goal="Investigate questions and produce concise, well-cited briefings.", + backstory=( + "You are a meticulous analyst who delegates web research to the Tavily " + "Research tool, then synthesizes the findings into short briefings." + ), + tools=[tavily_tool], + verbose=True, +) + +research_task = Task( + description=( + "Investigate notable open-source agent orchestration frameworks released " + "in the last six months and summarize their differentiators." + ), + expected_output="A bulleted briefing with citations.", + agent=researcher, +) + +crew = Crew(agents=[researcher], tasks=[research_task]) +print(crew.kickoff()) +``` + +## Configuration Options + +The `TavilyResearchTool` accepts the following arguments — all can be set on the tool instance (defaults for every call) or per-call via the agent's tool input: + +- `input` (str): **Required.** The research task or question to investigate. +- `model` (Literal["mini", "pro", "auto"]): The Tavily research model. `"auto"` lets Tavily pick; `"mini"` is faster/cheaper; `"pro"` is the most capable. Defaults to `"auto"`. +- `output_schema` (dict | None): Optional JSON Schema that structures the research output. Useful when you want strictly typed results. +- `stream` (bool): When `True`, the tool returns an iterator of SSE chunks emitting research progress and the final result instead of a single string. Defaults to `False`. +- `citation_format` (Literal["numbered", "mla", "apa", "chicago"]): Citation format for the report. Defaults to `"numbered"`. + +## Advanced Usage + +### Configure defaults on the tool instance + +```python +from crewai_tools import TavilyResearchTool + +tavily_tool = TavilyResearchTool( + model="pro", # use Tavily's most capable research model + citation_format="apa", # APA-style citations +) +``` + +### Stream research progress + +When `stream=True`, the tool returns a generator (or async generator from `_arun`) of SSE chunks so your application can surface incremental progress: + +```python +tavily_tool = TavilyResearchTool(stream=True) + +for chunk in tavily_tool.run(input="Summarize recent advances in retrieval-augmented generation."): + print(chunk) +``` + +### Structured output via JSON Schema + +Pass an `output_schema` when you need a typed result instead of a free-form report: + +```python +output_schema = { + "type": "object", + "properties": { + "summary": {"type": "string"}, + "key_points": {"type": "array", "items": {"type": "string"}}, + "sources": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["summary", "key_points", "sources"], +} + +tavily_tool = TavilyResearchTool(output_schema=output_schema) +``` + +## Features + +- **End-to-end research**: Returns a synthesized, cited report rather than raw search hits. +- **Model selection**: Trade off cost, speed, and depth via `mini`, `pro`, or `auto`. +- **Streaming**: Stream incremental progress and results as SSE chunks for responsive UIs. +- **Structured output**: Coerce results to a JSON Schema you define. +- **Multiple citation styles**: Choose from numbered, MLA, APA, or Chicago citations. +- **Sync and async**: Use either `_run` or `_arun` depending on your application's runtime. + +Refer to the [Tavily API documentation](https://docs.tavily.com/) for full details on the Research API. diff --git a/docs/ar/tools/search-research/tavilysearchtool.mdx b/docs/ar/tools/search-research/tavilysearchtool.mdx index e7ef712e4..bc2c52e72 100644 --- a/docs/ar/tools/search-research/tavilysearchtool.mdx +++ b/docs/ar/tools/search-research/tavilysearchtool.mdx @@ -12,7 +12,7 @@ mode: "wide" لاستخدام `TavilySearchTool`، تحتاج إلى تثبيت مكتبة `tavily-python`: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` ## متغيرات البيئة diff --git a/docs/docs.json b/docs/docs.json index 76d43b4e3..743cef205 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -247,6 +247,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -1199,6 +1200,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -1675,6 +1677,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -2151,6 +2154,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -2627,6 +2631,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -3102,6 +3107,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -3576,6 +3582,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -4050,6 +4057,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -4524,6 +4532,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -5000,6 +5009,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -5475,6 +5485,7 @@ "en/tools/search-research/youtubevideosearchtool", "en/tools/search-research/tavilysearchtool", "en/tools/search-research/tavilyextractortool", + "en/tools/search-research/tavilyresearchtool", "en/tools/search-research/arxivpapertool", "en/tools/search-research/serpapi-googlesearchtool", "en/tools/search-research/serpapi-googleshoppingtool", @@ -11512,6 +11523,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -12454,6 +12466,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -12925,6 +12938,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -13396,6 +13410,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -13867,6 +13882,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -14337,6 +14353,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -14807,6 +14824,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -15277,6 +15295,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -15746,6 +15765,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -16215,6 +16235,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -16685,6 +16706,7 @@ "ko/tools/search-research/youtubevideosearchtool", "ko/tools/search-research/tavilysearchtool", "ko/tools/search-research/tavilyextractortool", + "ko/tools/search-research/tavilyresearchtool", "ko/tools/search-research/arxivpapertool", "ko/tools/search-research/serpapi-googlesearchtool", "ko/tools/search-research/serpapi-googleshoppingtool", @@ -17186,6 +17208,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -18128,6 +18151,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -18599,6 +18623,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -19070,6 +19095,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -19541,6 +19567,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -20011,6 +20038,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -20481,6 +20509,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -20951,6 +20980,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -21420,6 +21450,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -21889,6 +21920,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", @@ -22359,6 +22391,7 @@ "ar/tools/search-research/youtubevideosearchtool", "ar/tools/search-research/tavilysearchtool", "ar/tools/search-research/tavilyextractortool", + "ar/tools/search-research/tavilyresearchtool", "ar/tools/search-research/arxivpapertool", "ar/tools/search-research/serpapi-googlesearchtool", "ar/tools/search-research/serpapi-googleshoppingtool", diff --git a/docs/en/tools/search-research/tavilyextractortool.mdx b/docs/en/tools/search-research/tavilyextractortool.mdx index 4b1d4b091..1530d54a9 100644 --- a/docs/en/tools/search-research/tavilyextractortool.mdx +++ b/docs/en/tools/search-research/tavilyextractortool.mdx @@ -12,7 +12,7 @@ The `TavilyExtractorTool` allows CrewAI agents to extract structured content fro To use the `TavilyExtractorTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` You also need to set your Tavily API key as an environment variable: diff --git a/docs/en/tools/search-research/tavilyresearchtool.mdx b/docs/en/tools/search-research/tavilyresearchtool.mdx new file mode 100644 index 000000000..34fdc8c66 --- /dev/null +++ b/docs/en/tools/search-research/tavilyresearchtool.mdx @@ -0,0 +1,125 @@ +--- +title: "Tavily Research Tool" +description: "Run multi-step research tasks and get cited reports using the Tavily Research API" +icon: "flask" +mode: "wide" +--- + +The `TavilyResearchTool` lets CrewAI agents kick off Tavily research tasks, returning a synthesized, cited report (or a stream of progress events) instead of raw search results. Use it when an agent needs an investigative answer rather than a single web search. + +## Installation + +To use the `TavilyResearchTool`, install the `tavily-python` library alongside `crewai-tools`: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Set your Tavily API key: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +Get an API key at [https://app.tavily.com/](https://app.tavily.com/) (sign up, then create a key). + +## Example Usage + +```python +import os +from crewai import Agent, Crew, Task +from crewai_tools import TavilyResearchTool + +# Ensure TAVILY_API_KEY is set in your environment +# os.environ["TAVILY_API_KEY"] = "YOUR_API_KEY" + +tavily_tool = TavilyResearchTool() + +researcher = Agent( + role="Research Analyst", + goal="Investigate questions and produce concise, well-cited briefings.", + backstory=( + "You are a meticulous analyst who delegates web research to the Tavily " + "Research tool, then synthesizes the findings into short briefings." + ), + tools=[tavily_tool], + verbose=True, +) + +research_task = Task( + description=( + "Investigate notable open-source agent orchestration frameworks released " + "in the last six months and summarize their differentiators." + ), + expected_output="A bulleted briefing with citations.", + agent=researcher, +) + +crew = Crew(agents=[researcher], tasks=[research_task]) +print(crew.kickoff()) +``` + +## Configuration Options + +The `TavilyResearchTool` accepts the following arguments — all can be set on the tool instance (defaults for every call) or per-call via the agent's tool input: + +- `input` (str): **Required.** The research task or question to investigate. +- `model` (Literal["mini", "pro", "auto"]): The Tavily research model. `"auto"` lets Tavily pick; `"mini"` is faster/cheaper; `"pro"` is the most capable. Defaults to `"auto"`. +- `output_schema` (dict | None): Optional JSON Schema that structures the research output. Useful when you want strictly typed results. +- `stream` (bool): When `True`, the tool returns an iterator of SSE chunks emitting research progress and the final result instead of a single string. Defaults to `False`. +- `citation_format` (Literal["numbered", "mla", "apa", "chicago"]): Citation format for the report. Defaults to `"numbered"`. + +## Advanced Usage + +### Configure defaults on the tool instance + +```python +from crewai_tools import TavilyResearchTool + +tavily_tool = TavilyResearchTool( + model="pro", # use Tavily's most capable research model + citation_format="apa", # APA-style citations +) +``` + +### Stream research progress + +When `stream=True`, the tool returns a generator (or async generator from `_arun`) of SSE chunks so your application can surface incremental progress: + +```python +tavily_tool = TavilyResearchTool(stream=True) + +for chunk in tavily_tool.run(input="Summarize recent advances in retrieval-augmented generation."): + print(chunk) +``` + +### Structured output via JSON Schema + +Pass an `output_schema` when you need a typed result instead of a free-form report: + +```python +output_schema = { + "type": "object", + "properties": { + "summary": {"type": "string"}, + "key_points": {"type": "array", "items": {"type": "string"}}, + "sources": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["summary", "key_points", "sources"], +} + +tavily_tool = TavilyResearchTool(output_schema=output_schema) +``` + +## Features + +- **End-to-end research**: Returns a synthesized, cited report rather than raw search hits. +- **Model selection**: Trade off cost, speed, and depth via `mini`, `pro`, or `auto`. +- **Streaming**: Stream incremental progress and results as SSE chunks for responsive UIs. +- **Structured output**: Coerce results to a JSON Schema you define. +- **Multiple citation styles**: Choose from numbered, MLA, APA, or Chicago citations. +- **Sync and async**: Use either `_run` or `_arun` depending on your application's runtime. + +Refer to the [Tavily API documentation](https://docs.tavily.com/) for full details on the Research API. diff --git a/docs/en/tools/search-research/tavilysearchtool.mdx b/docs/en/tools/search-research/tavilysearchtool.mdx index 0d3af2ba3..58c88a1ec 100644 --- a/docs/en/tools/search-research/tavilysearchtool.mdx +++ b/docs/en/tools/search-research/tavilysearchtool.mdx @@ -12,7 +12,7 @@ The `TavilySearchTool` provides an interface to the Tavily Search API, enabling To use the `TavilySearchTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` ## Environment Variables diff --git a/docs/ko/tools/search-research/tavilyextractortool.mdx b/docs/ko/tools/search-research/tavilyextractortool.mdx index 17a6d3df2..21211e9fd 100644 --- a/docs/ko/tools/search-research/tavilyextractortool.mdx +++ b/docs/ko/tools/search-research/tavilyextractortool.mdx @@ -12,7 +12,7 @@ mode: "wide" `TavilyExtractorTool`을 사용하려면 `tavily-python` 라이브러리를 설치해야 합니다: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` 또한 Tavily API 키를 환경 변수로 설정해야 합니다: diff --git a/docs/ko/tools/search-research/tavilyresearchtool.mdx b/docs/ko/tools/search-research/tavilyresearchtool.mdx new file mode 100644 index 000000000..34fdc8c66 --- /dev/null +++ b/docs/ko/tools/search-research/tavilyresearchtool.mdx @@ -0,0 +1,125 @@ +--- +title: "Tavily Research Tool" +description: "Run multi-step research tasks and get cited reports using the Tavily Research API" +icon: "flask" +mode: "wide" +--- + +The `TavilyResearchTool` lets CrewAI agents kick off Tavily research tasks, returning a synthesized, cited report (or a stream of progress events) instead of raw search results. Use it when an agent needs an investigative answer rather than a single web search. + +## Installation + +To use the `TavilyResearchTool`, install the `tavily-python` library alongside `crewai-tools`: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Set your Tavily API key: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +Get an API key at [https://app.tavily.com/](https://app.tavily.com/) (sign up, then create a key). + +## Example Usage + +```python +import os +from crewai import Agent, Crew, Task +from crewai_tools import TavilyResearchTool + +# Ensure TAVILY_API_KEY is set in your environment +# os.environ["TAVILY_API_KEY"] = "YOUR_API_KEY" + +tavily_tool = TavilyResearchTool() + +researcher = Agent( + role="Research Analyst", + goal="Investigate questions and produce concise, well-cited briefings.", + backstory=( + "You are a meticulous analyst who delegates web research to the Tavily " + "Research tool, then synthesizes the findings into short briefings." + ), + tools=[tavily_tool], + verbose=True, +) + +research_task = Task( + description=( + "Investigate notable open-source agent orchestration frameworks released " + "in the last six months and summarize their differentiators." + ), + expected_output="A bulleted briefing with citations.", + agent=researcher, +) + +crew = Crew(agents=[researcher], tasks=[research_task]) +print(crew.kickoff()) +``` + +## Configuration Options + +The `TavilyResearchTool` accepts the following arguments — all can be set on the tool instance (defaults for every call) or per-call via the agent's tool input: + +- `input` (str): **Required.** The research task or question to investigate. +- `model` (Literal["mini", "pro", "auto"]): The Tavily research model. `"auto"` lets Tavily pick; `"mini"` is faster/cheaper; `"pro"` is the most capable. Defaults to `"auto"`. +- `output_schema` (dict | None): Optional JSON Schema that structures the research output. Useful when you want strictly typed results. +- `stream` (bool): When `True`, the tool returns an iterator of SSE chunks emitting research progress and the final result instead of a single string. Defaults to `False`. +- `citation_format` (Literal["numbered", "mla", "apa", "chicago"]): Citation format for the report. Defaults to `"numbered"`. + +## Advanced Usage + +### Configure defaults on the tool instance + +```python +from crewai_tools import TavilyResearchTool + +tavily_tool = TavilyResearchTool( + model="pro", # use Tavily's most capable research model + citation_format="apa", # APA-style citations +) +``` + +### Stream research progress + +When `stream=True`, the tool returns a generator (or async generator from `_arun`) of SSE chunks so your application can surface incremental progress: + +```python +tavily_tool = TavilyResearchTool(stream=True) + +for chunk in tavily_tool.run(input="Summarize recent advances in retrieval-augmented generation."): + print(chunk) +``` + +### Structured output via JSON Schema + +Pass an `output_schema` when you need a typed result instead of a free-form report: + +```python +output_schema = { + "type": "object", + "properties": { + "summary": {"type": "string"}, + "key_points": {"type": "array", "items": {"type": "string"}}, + "sources": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["summary", "key_points", "sources"], +} + +tavily_tool = TavilyResearchTool(output_schema=output_schema) +``` + +## Features + +- **End-to-end research**: Returns a synthesized, cited report rather than raw search hits. +- **Model selection**: Trade off cost, speed, and depth via `mini`, `pro`, or `auto`. +- **Streaming**: Stream incremental progress and results as SSE chunks for responsive UIs. +- **Structured output**: Coerce results to a JSON Schema you define. +- **Multiple citation styles**: Choose from numbered, MLA, APA, or Chicago citations. +- **Sync and async**: Use either `_run` or `_arun` depending on your application's runtime. + +Refer to the [Tavily API documentation](https://docs.tavily.com/) for full details on the Research API. diff --git a/docs/ko/tools/search-research/tavilysearchtool.mdx b/docs/ko/tools/search-research/tavilysearchtool.mdx index 183fc0549..264652708 100644 --- a/docs/ko/tools/search-research/tavilysearchtool.mdx +++ b/docs/ko/tools/search-research/tavilysearchtool.mdx @@ -12,7 +12,7 @@ mode: "wide" `TavilySearchTool`을 사용하려면 `tavily-python` 라이브러리를 설치해야 합니다: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` ## 환경 변수 diff --git a/docs/pt-BR/tools/search-research/tavilyextractortool.mdx b/docs/pt-BR/tools/search-research/tavilyextractortool.mdx index ed384de44..55030845c 100644 --- a/docs/pt-BR/tools/search-research/tavilyextractortool.mdx +++ b/docs/pt-BR/tools/search-research/tavilyextractortool.mdx @@ -12,7 +12,7 @@ The `TavilyExtractorTool` allows CrewAI agents to extract structured content fro To use the `TavilyExtractorTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` You also need to set your Tavily API key as an environment variable: diff --git a/docs/pt-BR/tools/search-research/tavilyresearchtool.mdx b/docs/pt-BR/tools/search-research/tavilyresearchtool.mdx new file mode 100644 index 000000000..34fdc8c66 --- /dev/null +++ b/docs/pt-BR/tools/search-research/tavilyresearchtool.mdx @@ -0,0 +1,125 @@ +--- +title: "Tavily Research Tool" +description: "Run multi-step research tasks and get cited reports using the Tavily Research API" +icon: "flask" +mode: "wide" +--- + +The `TavilyResearchTool` lets CrewAI agents kick off Tavily research tasks, returning a synthesized, cited report (or a stream of progress events) instead of raw search results. Use it when an agent needs an investigative answer rather than a single web search. + +## Installation + +To use the `TavilyResearchTool`, install the `tavily-python` library alongside `crewai-tools`: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Set your Tavily API key: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +Get an API key at [https://app.tavily.com/](https://app.tavily.com/) (sign up, then create a key). + +## Example Usage + +```python +import os +from crewai import Agent, Crew, Task +from crewai_tools import TavilyResearchTool + +# Ensure TAVILY_API_KEY is set in your environment +# os.environ["TAVILY_API_KEY"] = "YOUR_API_KEY" + +tavily_tool = TavilyResearchTool() + +researcher = Agent( + role="Research Analyst", + goal="Investigate questions and produce concise, well-cited briefings.", + backstory=( + "You are a meticulous analyst who delegates web research to the Tavily " + "Research tool, then synthesizes the findings into short briefings." + ), + tools=[tavily_tool], + verbose=True, +) + +research_task = Task( + description=( + "Investigate notable open-source agent orchestration frameworks released " + "in the last six months and summarize their differentiators." + ), + expected_output="A bulleted briefing with citations.", + agent=researcher, +) + +crew = Crew(agents=[researcher], tasks=[research_task]) +print(crew.kickoff()) +``` + +## Configuration Options + +The `TavilyResearchTool` accepts the following arguments — all can be set on the tool instance (defaults for every call) or per-call via the agent's tool input: + +- `input` (str): **Required.** The research task or question to investigate. +- `model` (Literal["mini", "pro", "auto"]): The Tavily research model. `"auto"` lets Tavily pick; `"mini"` is faster/cheaper; `"pro"` is the most capable. Defaults to `"auto"`. +- `output_schema` (dict | None): Optional JSON Schema that structures the research output. Useful when you want strictly typed results. +- `stream` (bool): When `True`, the tool returns an iterator of SSE chunks emitting research progress and the final result instead of a single string. Defaults to `False`. +- `citation_format` (Literal["numbered", "mla", "apa", "chicago"]): Citation format for the report. Defaults to `"numbered"`. + +## Advanced Usage + +### Configure defaults on the tool instance + +```python +from crewai_tools import TavilyResearchTool + +tavily_tool = TavilyResearchTool( + model="pro", # use Tavily's most capable research model + citation_format="apa", # APA-style citations +) +``` + +### Stream research progress + +When `stream=True`, the tool returns a generator (or async generator from `_arun`) of SSE chunks so your application can surface incremental progress: + +```python +tavily_tool = TavilyResearchTool(stream=True) + +for chunk in tavily_tool.run(input="Summarize recent advances in retrieval-augmented generation."): + print(chunk) +``` + +### Structured output via JSON Schema + +Pass an `output_schema` when you need a typed result instead of a free-form report: + +```python +output_schema = { + "type": "object", + "properties": { + "summary": {"type": "string"}, + "key_points": {"type": "array", "items": {"type": "string"}}, + "sources": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["summary", "key_points", "sources"], +} + +tavily_tool = TavilyResearchTool(output_schema=output_schema) +``` + +## Features + +- **End-to-end research**: Returns a synthesized, cited report rather than raw search hits. +- **Model selection**: Trade off cost, speed, and depth via `mini`, `pro`, or `auto`. +- **Streaming**: Stream incremental progress and results as SSE chunks for responsive UIs. +- **Structured output**: Coerce results to a JSON Schema you define. +- **Multiple citation styles**: Choose from numbered, MLA, APA, or Chicago citations. +- **Sync and async**: Use either `_run` or `_arun` depending on your application's runtime. + +Refer to the [Tavily API documentation](https://docs.tavily.com/) for full details on the Research API. diff --git a/docs/pt-BR/tools/search-research/tavilysearchtool.mdx b/docs/pt-BR/tools/search-research/tavilysearchtool.mdx index 3252e82ac..1207562cc 100644 --- a/docs/pt-BR/tools/search-research/tavilysearchtool.mdx +++ b/docs/pt-BR/tools/search-research/tavilysearchtool.mdx @@ -12,7 +12,7 @@ The `TavilySearchTool` provides an interface to the Tavily Search API, enabling To use the `TavilySearchTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` ## Environment Variables diff --git a/lib/crewai-tools/pyproject.toml b/lib/crewai-tools/pyproject.toml index d900f859b..ec1bb518b 100644 --- a/lib/crewai-tools/pyproject.toml +++ b/lib/crewai-tools/pyproject.toml @@ -69,7 +69,7 @@ linkup-sdk = [ "linkup-sdk>=0.2.2", ] tavily-python = [ - "tavily-python>=0.5.4", + "tavily-python~=0.7.14", ] hyperbrowser = [ "hyperbrowser>=0.18.0", diff --git a/lib/crewai-tools/src/crewai_tools/__init__.py b/lib/crewai-tools/src/crewai_tools/__init__.py index 2af540edc..3d5c23abd 100644 --- a/lib/crewai-tools/src/crewai_tools/__init__.py +++ b/lib/crewai-tools/src/crewai_tools/__init__.py @@ -197,6 +197,12 @@ from crewai_tools.tools.stagehand_tool.stagehand_tool import StagehandTool from crewai_tools.tools.tavily_extractor_tool.tavily_extractor_tool import ( TavilyExtractorTool, ) +from crewai_tools.tools.tavily_get_research_tool.tavily_get_research_tool import ( + TavilyGetResearchTool, +) +from crewai_tools.tools.tavily_research_tool.tavily_research_tool import ( + TavilyResearchTool, +) from crewai_tools.tools.tavily_search_tool.tavily_search_tool import TavilySearchTool from crewai_tools.tools.txt_search_tool.txt_search_tool import TXTSearchTool from crewai_tools.tools.vision_tool.vision_tool import VisionTool @@ -310,6 +316,8 @@ __all__ = [ "StagehandTool", "TXTSearchTool", "TavilyExtractorTool", + "TavilyGetResearchTool", + "TavilyResearchTool", "TavilySearchTool", "VisionTool", "WeaviateVectorSearchTool", diff --git a/lib/crewai-tools/src/crewai_tools/tools/__init__.py b/lib/crewai-tools/src/crewai_tools/tools/__init__.py index 7cf61c7a3..11309c87e 100644 --- a/lib/crewai-tools/src/crewai_tools/tools/__init__.py +++ b/lib/crewai-tools/src/crewai_tools/tools/__init__.py @@ -184,6 +184,12 @@ from crewai_tools.tools.stagehand_tool.stagehand_tool import StagehandTool from crewai_tools.tools.tavily_extractor_tool.tavily_extractor_tool import ( TavilyExtractorTool, ) +from crewai_tools.tools.tavily_get_research_tool.tavily_get_research_tool import ( + TavilyGetResearchTool, +) +from crewai_tools.tools.tavily_research_tool.tavily_research_tool import ( + TavilyResearchTool, +) from crewai_tools.tools.tavily_search_tool.tavily_search_tool import TavilySearchTool from crewai_tools.tools.txt_search_tool.txt_search_tool import TXTSearchTool from crewai_tools.tools.vision_tool.vision_tool import VisionTool @@ -293,6 +299,8 @@ __all__ = [ "StagehandTool", "TXTSearchTool", "TavilyExtractorTool", + "TavilyGetResearchTool", + "TavilyResearchTool", "TavilySearchTool", "VisionTool", "WeaviateVectorSearchTool", diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_extractor_tool/README.md b/lib/crewai-tools/src/crewai_tools/tools/tavily_extractor_tool/README.md index 8e2794dd1..64e85c92d 100644 --- a/lib/crewai-tools/src/crewai_tools/tools/tavily_extractor_tool/README.md +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_extractor_tool/README.md @@ -9,7 +9,7 @@ The `TavilyExtractorTool` allows CrewAI agents to extract structured content fro To use the `TavilyExtractorTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` You also need to set your Tavily API key as an environment variable: diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/README.md b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/README.md new file mode 100644 index 000000000..303121e0c --- /dev/null +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/README.md @@ -0,0 +1,44 @@ +# Tavily Get Research Tool + +## Description + +The `TavilyGetResearchTool` provides an interface to Tavily's research status endpoint through the Tavily Python SDK. It retrieves the current status and results of an existing Tavily research task by `request_id`. + +## Installation + +To use the `TavilyGetResearchTool`, you need to install the `tavily-python` library: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Ensure your Tavily API key is set as an environment variable: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +## Example + +```python +from crewai_tools import TavilyGetResearchTool + +tavily_get_research_tool = TavilyGetResearchTool() + +status_result = tavily_get_research_tool.run( + request_id="Your Request ID Here" +) +print(status_result) +``` + +## Arguments + +The `TavilyGetResearchTool` accepts the following arguments during initialization or when calling the `run` method: + +- `request_id` (str): Existing Tavily research request ID to retrieve. + +## Response Format + +The tool returns a JSON string containing the current research task status and any available results from Tavily. diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/__init__.py b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/__init__.py @@ -0,0 +1 @@ + diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/tavily_get_research_tool.py b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/tavily_get_research_tool.py new file mode 100644 index 000000000..c3d6787b3 --- /dev/null +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_get_research_tool/tavily_get_research_tool.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +import json +import os +from typing import Any + +from crewai.tools import BaseTool, EnvVar +from dotenv import load_dotenv +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr + + +load_dotenv() +try: + from tavily import AsyncTavilyClient, TavilyClient # type: ignore[import-untyped] + + TAVILY_AVAILABLE = True +except ImportError: + TAVILY_AVAILABLE = False + + +class TavilyGetResearchToolSchema(BaseModel): + """Input schema for TavilyGetResearchTool.""" + + request_id: str = Field( + ..., + description="Existing Tavily research request ID to fetch status and results for.", + ) + + +class TavilyGetResearchTool(BaseTool): + """Tool that uses the Tavily Research status endpoint to retrieve results.""" + + model_config = ConfigDict(arbitrary_types_allowed=True) + _client: Any | None = PrivateAttr(default=None) + _async_client: Any | None = PrivateAttr(default=None) + name: str = "Tavily Get Research" + description: str = ( + "A tool that retrieves the status and results of an existing Tavily " + "research task by request ID. It returns Tavily responses as JSON." + ) + args_schema: type[BaseModel] = TavilyGetResearchToolSchema + package_dependencies: list[str] = Field(default_factory=lambda: ["tavily-python"]) + env_vars: list[EnvVar] = Field( + default_factory=lambda: [ + EnvVar( + name="TAVILY_API_KEY", + description="API key for Tavily research service", + required=True, + ), + ] + ) + + def __init__(self, **kwargs: Any): + super().__init__(**kwargs) + if TAVILY_AVAILABLE: + api_key = os.getenv("TAVILY_API_KEY") + self._client = TavilyClient(api_key=api_key) + self._async_client = AsyncTavilyClient(api_key=api_key) + else: + try: + import subprocess + + import click + except ImportError as e: + raise ImportError( + "The 'tavily-python' package is required. 'click' and " + "'subprocess' are also needed to assist with installation " + "if the package is missing. Please install 'tavily-python' " + "manually (e.g., 'pip install tavily-python') and ensure " + "'click' and 'subprocess' are available." + ) from e + + if click.confirm( + "You are missing the 'tavily-python' package, which is required " + "for TavilyGetResearchTool. Would you like to install it?" + ): + try: + subprocess.run(["uv", "add", "tavily-python"], check=True) # noqa: S607 + raise ImportError( + "'tavily-python' has been installed. Please restart your " + "Python application to use the TavilyGetResearchTool." + ) + except subprocess.CalledProcessError as e: + raise ImportError( + f"Attempted to install 'tavily-python' but failed: {e}. " + "Please install it manually to use the TavilyGetResearchTool." + ) from e + else: + raise ImportError( + "The 'tavily-python' package is required to use the " + "TavilyGetResearchTool. Please install it with: uv add tavily-python" + ) + + @staticmethod + def _stringify_response(response: Any) -> str: + if isinstance(response, str): + return response + return json.dumps(response, indent=2) + + def _run(self, request_id: str) -> str: + """Synchronously retrieves Tavily research task status and results.""" + if not self._client: + raise ValueError( + "Tavily client is not initialized. Ensure 'tavily-python' is " + "installed and API key is set." + ) + + return self._stringify_response(self._client.get_research(request_id)) + + async def _arun(self, request_id: str) -> str: + """Asynchronously retrieves Tavily research task status and results.""" + if not self._async_client: + raise ValueError( + "Tavily async client is not initialized. Ensure 'tavily-python' is " + "installed and API key is set." + ) + + return self._stringify_response( + await self._async_client.get_research(request_id) + ) diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/README.md b/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/README.md new file mode 100644 index 000000000..13e730e62 --- /dev/null +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/README.md @@ -0,0 +1,132 @@ +# Tavily Research Tool + +## Description + +The `TavilyResearchTool` provides an interface to Tavily Research through the Tavily Python SDK. It creates research tasks from an `input` prompt and can optionally stream Server-Sent Events (SSE) when `stream=True`. + +## Installation + +To use the `TavilyResearchTool`, you need to install the `tavily-python` library: + +```shell +uv add 'crewai[tools]' tavily-python +``` + +## Environment Variables + +Ensure your Tavily API key is set as an environment variable: + +```bash +export TAVILY_API_KEY='your_tavily_api_key' +``` + +## Example + +Here's how to initialize and use the `TavilyResearchTool` within a CrewAI agent: + +```python +from crewai import Agent, Task, Crew +from crewai_tools import TavilyResearchTool + +# Initialize the tool +tavily_research_tool = TavilyResearchTool() + +# Create an agent that uses the tool +researcher = Agent( + role="Research Analyst", + goal="Produce structured research reports", + backstory="An expert analyst who uses Tavily Research for deep web research.", + tools=[tavily_research_tool], + verbose=True, +) + +# Create a task for the agent +research_task = Task( + description="Research the latest developments in AI infrastructure startups.", + expected_output="A detailed report with citations and supporting sources.", + agent=researcher, +) + +# Run the crew +crew = Crew( + agents=[researcher], + tasks=[research_task], + verbose=2, +) + +result = crew.kickoff() +print(result) + +# Direct tool usage: create a structured research task +structured_result = tavily_research_tool.run( + input="Research the latest developments in AI infrastructure startups.", + model="pro", + output_schema={ + "properties": { + "summary": { + "type": "string", + "description": "A concise summary of the research findings", + }, + "key_trends": { + "type": "array", + "description": "The major trends identified in the research", + "items": {"type": "string"}, + }, + "companies": { + "type": "array", + "description": "Notable companies mentioned in the research", + "items": { + "type": "object", + "description": "A company entry", + "properties": { + "name": { + "type": "string", + "description": "The company name", + }, + "focus": { + "type": "string", + "description": "The company's main area of focus", + }, + "notable_update": { + "type": "string", + "description": "A notable recent update about the company", + }, + }, + "required": ["name", "focus", "notable_update"], + }, + }, + }, + "required": ["summary", "key_trends", "companies"], + }, + citation_format="apa", +) +print(structured_result) + +# Direct tool usage: stream research updates +stream = tavily_research_tool.run( + input="Research the latest developments in AI infrastructure startups.", + model="mini", + stream=True, +) +for chunk in stream: + print(chunk.decode("utf-8", errors="replace"), end="") +``` + +## Arguments + +The `TavilyResearchTool` accepts the following arguments during initialization or when calling the `run` method: + +- `input` (str): The research task or question to investigate. +- `model` (Literal["mini", "pro", "auto"], optional): The Tavily research model to use. Defaults to `"auto"`. +- `output_schema` (dict[str, Any], optional): A JSON Schema used to structure the research output. Tavily expects top-level `properties` and optional `required` keys, and each property should include a `description`. +- `stream` (bool, optional): Whether to return Tavily's streaming SSE chunk generator. Defaults to `False`. +- `citation_format` (Literal["numbered", "mla", "apa", "chicago"], optional): Citation format for the report. Defaults to `"numbered"`. + +## Response Format + +The tool returns: + +- A JSON string when creating a non-streaming research task +- A byte generator of SSE chunks when `stream=True` + +Refer to the Tavily Research API documentation for the full response structure and streaming event format. diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/__init__.py b/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/tavily_research_tool.py b/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/tavily_research_tool.py new file mode 100644 index 000000000..084fefdf1 --- /dev/null +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_research_tool/tavily_research_tool.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from collections.abc import AsyncGenerator, Generator +import json +import os +from typing import Any, Literal, cast + +from crewai.tools import BaseTool, EnvVar +from dotenv import load_dotenv +from pydantic import BaseModel, ConfigDict, Field, PrivateAttr + + +load_dotenv() +try: + from tavily import ( # type: ignore[import-untyped, import-not-found, unused-ignore] + AsyncTavilyClient, + TavilyClient, + ) + + TAVILY_AVAILABLE = True +except ImportError: + TAVILY_AVAILABLE = False + + +class TavilyResearchToolSchema(BaseModel): + """Input schema for TavilyResearchTool.""" + + input: str = Field( + ..., + description="The research task or question to investigate.", + ) + model: Literal["mini", "pro", "auto"] = Field( + default="auto", + description="The model used by the Tavily research agent.", + ) + output_schema: dict[str, Any] | None = Field( + default=None, + description="Optional JSON Schema that structures the research output.", + ) + stream: bool = Field( + default=False, + description="Whether to stream research progress and results as SSE chunks.", + ) + citation_format: Literal["numbered", "mla", "apa", "chicago"] = Field( + default="numbered", + description="Citation format for the research report.", + ) + + +class TavilyResearchTool(BaseTool): + """Tool that uses the Tavily Research API to create research tasks.""" + + model_config = ConfigDict(arbitrary_types_allowed=True) + _client: Any | None = PrivateAttr(default=None) + _async_client: Any | None = PrivateAttr(default=None) + name: str = "Tavily Research" + description: str = ( + "A tool that creates Tavily research tasks and can stream research " + "progress and results. It returns Tavily responses as JSON or SSE chunks." + ) + args_schema: type[BaseModel] = TavilyResearchToolSchema + model: Literal["mini", "pro", "auto"] = Field( + default="auto", + description="Default model used for new Tavily research tasks.", + ) + output_schema: dict[str, Any] | None = Field( + default=None, + description="Default JSON Schema used to structure research output.", + ) + stream: bool = Field( + default=False, + description="Whether new Tavily research tasks should stream responses by default.", + ) + citation_format: Literal["numbered", "mla", "apa", "chicago"] = Field( + default="numbered", + description="Default citation format for Tavily research results.", + ) + package_dependencies: list[str] = Field(default_factory=lambda: ["tavily-python"]) + env_vars: list[EnvVar] = Field( + default_factory=lambda: [ + EnvVar( + name="TAVILY_API_KEY", + description="API key for Tavily research service", + required=True, + ), + ] + ) + + def __init__(self, **kwargs: Any): + super().__init__(**kwargs) + if TAVILY_AVAILABLE: + api_key = os.getenv("TAVILY_API_KEY") + self._client = TavilyClient(api_key=api_key) + self._async_client = AsyncTavilyClient(api_key=api_key) + else: + try: + import subprocess + + import click + except ImportError as e: + raise ImportError( + "The 'tavily-python' package is required. 'click' and " + "'subprocess' are also needed to assist with installation " + "if the package is missing. Please install 'tavily-python' " + "manually (e.g., 'pip install tavily-python') and ensure " + "'click' and 'subprocess' are available." + ) from e + + if click.confirm( + "You are missing the 'tavily-python' package, which is required " + "for TavilyResearchTool. Would you like to install it?" + ): + try: + subprocess.run(["uv", "add", "tavily-python"], check=True) # noqa: S607 + raise ImportError( + "'tavily-python' has been installed. Please restart your " + "Python application to use the TavilyResearchTool." + ) + except subprocess.CalledProcessError as e: + raise ImportError( + f"Attempted to install 'tavily-python' but failed: {e}. " + "Please install it manually to use the TavilyResearchTool." + ) from e + else: + raise ImportError( + "The 'tavily-python' package is required to use the " + "TavilyResearchTool. Please install it with: uv add tavily-python" + ) + + @staticmethod + def _stringify_response(response: Any) -> str: + if isinstance(response, str): + return response + return json.dumps(response, indent=2) + + def _run( + self, + input: str, + model: Literal["mini", "pro", "auto"] | None = None, + output_schema: dict[str, Any] | None = None, + stream: bool | None = None, + citation_format: Literal["numbered", "mla", "apa", "chicago"] | None = None, + ) -> str | Generator[bytes, None, None]: + """Synchronously creates Tavily research tasks or streams results.""" + if not self._client: + raise ValueError( + "Tavily client is not initialized. Ensure 'tavily-python' is " + "installed and API key is set." + ) + + use_stream = self.stream if stream is None else stream + result = self._client.research( + input=input, + model=self.model if model is None else model, + output_schema=self.output_schema + if output_schema is None + else output_schema, + stream=use_stream, + citation_format=( + self.citation_format if citation_format is None else citation_format + ), + ) + + if use_stream: + return cast(Generator[bytes, None, None], result) + + return self._stringify_response(result) + + async def _arun( + self, + input: str, + model: Literal["mini", "pro", "auto"] | None = None, + output_schema: dict[str, Any] | None = None, + stream: bool | None = None, + citation_format: Literal["numbered", "mla", "apa", "chicago"] | None = None, + ) -> str | AsyncGenerator[bytes, None]: + """Asynchronously creates Tavily research tasks or streams results.""" + if not self._async_client: + raise ValueError( + "Tavily async client is not initialized. Ensure 'tavily-python' is " + "installed and API key is set." + ) + + use_stream = self.stream if stream is None else stream + result = await self._async_client.research( + input=input, + model=self.model if model is None else model, + output_schema=self.output_schema + if output_schema is None + else output_schema, + stream=use_stream, + citation_format=( + self.citation_format if citation_format is None else citation_format + ), + ) + + if use_stream: + return cast(AsyncGenerator[bytes, None], result) + + return self._stringify_response(result) diff --git a/lib/crewai-tools/src/crewai_tools/tools/tavily_search_tool/README.md b/lib/crewai-tools/src/crewai_tools/tools/tavily_search_tool/README.md index 185b19887..e3d8ca6c3 100644 --- a/lib/crewai-tools/src/crewai_tools/tools/tavily_search_tool/README.md +++ b/lib/crewai-tools/src/crewai_tools/tools/tavily_search_tool/README.md @@ -9,7 +9,7 @@ The `TavilySearchTool` provides an interface to the Tavily Search API, enabling To use the `TavilySearchTool`, you need to install the `tavily-python` library: ```shell -pip install 'crewai[tools]' tavily-python +uv add 'crewai[tools]' tavily-python ``` ## Environment Variables diff --git a/lib/crewai-tools/tool.specs.json b/lib/crewai-tools/tool.specs.json index c78dc2c1f..6a0bcc4c6 100644 --- a/lib/crewai-tools/tool.specs.json +++ b/lib/crewai-tools/tool.specs.json @@ -25039,6 +25039,243 @@ "type": "object" } }, + { + "description": "A tool that retrieves the status and results of an existing Tavily research task by request ID. It returns Tavily responses as JSON.", + "env_vars": [ + { + "default": null, + "description": "API key for Tavily research service", + "name": "TAVILY_API_KEY", + "required": true + } + ], + "humanized_name": "Tavily Get Research", + "init_params_schema": { + "$defs": { + "EnvVar": { + "properties": { + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Default" + }, + "description": { + "title": "Description", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "required": { + "default": true, + "title": "Required", + "type": "boolean" + } + }, + "required": [ + "name", + "description" + ], + "title": "EnvVar", + "type": "object" + } + }, + "description": "Tool that uses the Tavily Research status endpoint to retrieve results.", + "properties": {}, + "required": [], + "title": "TavilyGetResearchTool", + "type": "object" + }, + "name": "TavilyGetResearchTool", + "package_dependencies": [ + "tavily-python" + ], + "run_params_schema": { + "description": "Input schema for TavilyGetResearchTool.", + "properties": { + "request_id": { + "description": "Existing Tavily research request ID to fetch status and results for.", + "title": "Request Id", + "type": "string" + } + }, + "required": [ + "request_id" + ], + "title": "TavilyGetResearchToolSchema", + "type": "object" + } + }, + { + "description": "A tool that creates Tavily research tasks and can stream research progress and results. It returns Tavily responses as JSON or SSE chunks.", + "env_vars": [ + { + "default": null, + "description": "API key for Tavily research service", + "name": "TAVILY_API_KEY", + "required": true + } + ], + "humanized_name": "Tavily Research", + "init_params_schema": { + "$defs": { + "EnvVar": { + "properties": { + "default": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Default" + }, + "description": { + "title": "Description", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "required": { + "default": true, + "title": "Required", + "type": "boolean" + } + }, + "required": [ + "name", + "description" + ], + "title": "EnvVar", + "type": "object" + } + }, + "description": "Tool that uses the Tavily Research API to create research tasks.", + "properties": { + "citation_format": { + "default": "numbered", + "description": "Default citation format for Tavily research results.", + "enum": [ + "numbered", + "mla", + "apa", + "chicago" + ], + "title": "Citation Format", + "type": "string" + }, + "model": { + "default": "auto", + "description": "Default model used for new Tavily research tasks.", + "enum": [ + "mini", + "pro", + "auto" + ], + "title": "Model", + "type": "string" + }, + "output_schema": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Default JSON Schema used to structure research output.", + "title": "Output Schema" + }, + "stream": { + "default": false, + "description": "Whether new Tavily research tasks should stream responses by default.", + "title": "Stream", + "type": "boolean" + } + }, + "required": [], + "title": "TavilyResearchTool", + "type": "object" + }, + "name": "TavilyResearchTool", + "package_dependencies": [ + "tavily-python" + ], + "run_params_schema": { + "description": "Input schema for TavilyResearchTool.", + "properties": { + "citation_format": { + "default": "numbered", + "description": "Citation format for the research report.", + "enum": [ + "numbered", + "mla", + "apa", + "chicago" + ], + "title": "Citation Format", + "type": "string" + }, + "input": { + "description": "The research task or question to investigate.", + "title": "Input", + "type": "string" + }, + "model": { + "default": "auto", + "description": "The model used by the Tavily research agent.", + "enum": [ + "mini", + "pro", + "auto" + ], + "title": "Model", + "type": "string" + }, + "output_schema": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Optional JSON Schema that structures the research output.", + "title": "Output Schema" + }, + "stream": { + "default": false, + "description": "Whether to stream research progress and results as SSE chunks.", + "title": "Stream", + "type": "boolean" + } + }, + "required": [ + "input" + ], + "title": "TavilyResearchToolSchema", + "type": "object" + } + }, { "description": "A tool that performs web searches using the Tavily Search API. It returns a JSON object containing the search results.", "env_vars": [ diff --git a/uv.lock b/uv.lock index 202cf6e17..c2e8b55b2 100644 --- a/uv.lock +++ b/uv.lock @@ -13,7 +13,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-04-27T16:00:00Z" +exclude-newer = "2026-04-28T07:00:00Z" [manifest] members = [ @@ -1660,7 +1660,7 @@ requires-dist = [ { name = "sqlalchemy", marker = "extra == 'singlestore'", specifier = ">=2.0.40" }, { name = "sqlalchemy", marker = "extra == 'sqlalchemy'", specifier = ">=2.0.35" }, { name = "stagehand", marker = "extra == 'stagehand'", specifier = ">=0.4.1" }, - { name = "tavily-python", marker = "extra == 'tavily-python'", specifier = ">=0.5.4" }, + { name = "tavily-python", marker = "extra == 'tavily-python'", specifier = "~=0.7.14" }, { name = "tiktoken", specifier = ">=0.8.0,<0.13" }, { name = "unstructured", extras = ["all-docs", "local-inference"], marker = "extra == 'xml'", specifier = ">=0.17.2" }, { name = "weaviate-client", marker = "extra == 'weaviate-client'", specifier = ">=4.10.2" },