# Exa Search

`ExaToolkit` gives an agent four related tools powered by the [Exa](https://exa.ai/) neural search engine: web search, find-similar, content retrieval, and AI-powered answers — all sharing a single client.

Note

Requires the `exa-py` package and an API key: `pip install "exa-py>=2.12.1,<3"`

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>``` | ```<br>import os<br>from autogen.beta import Agent<br>from autogen.beta.config import AnthropicConfig<br>from autogen.beta.extensions.tools.search import ExaToolkit<br>agent = Agent(<br>    "researcher",<br>    config=AnthropicConfig(model="claude-sonnet-4-6"),<br>    tools=[ExaToolkit(api_key=os.environ["EXA_API_KEY"])],<br>)<br>``` |

If `api_key` is omitted, the Exa SDK reads `EXA_API_KEY` from the environment automatically.

## Tools

| Tool | Description |
| --- | --- |
| `exa_search` | Neural web search with filters (domains, dates, type, category) |
| `exa_find_similar` | Find pages similar to a given URL |
| `exa_get_contents` | Fetch full text content for specific URLs |
| `exa_answer` | Get an AI-generated answer with citations |

## Shared defaults

`num_results` and `max_characters` on the constructor are applied to the default `exa_search` and `exa_find_similar` tools:

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>``` | ```<br>toolkit = ExaToolkit(<br>    api_key=...,<br>    num_results=10,         # applies to search & find_similar<br>    max_characters=2000,    # per-result text cap for search; None = metadata-only<br>)<br>``` |

## Picking a subset of tools

Each tool is exposed as a factory method on the toolkit (`toolkit.search()`, `toolkit.find_similar()`, `toolkit.get_contents()`, `toolkit.answer()`). Call the method to get a ready-to-use tool, then pass only the ones you need to the agent:

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>toolkit = ExaToolkit(api_key=...)<br>agent = Agent(<br>    "researcher",<br>    config=config,<br>    tools=[toolkit.search(), toolkit.answer()],<br>)<br>``` |

## Per-tool configuration

Per-call parameters (filters, domains, dates, `num_results`, `max_characters`, etc.) live on the factory methods, not on the toolkit itself:

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>``` | ```<br>toolkit = ExaToolkit(api_key=...)<br>search_tool = toolkit.search(<br>    num_results=5,<br>    max_characters=2000,           # triggers search_and_contents for full text<br>    search_type="neural",          # "neural" | "keyword" | "hybrid" | "auto" | "fast" | "deep"<br>    category="research paper",     # e.g. "news", "github", "pdf", ...<br>    include_domains=["arxiv.org"],<br>    exclude_domains=["medium.com"],<br>    start_published_date="2024-01-01",<br>    end_published_date="2024-12-31",<br>    use_autoprompt=True,<br>    livecrawl="always",            # "never" | "fallback" | "always" | "preferred"<br>)<br>agent = Agent("researcher", config=config, tools=[search_tool, toolkit.answer()])<br>``` |

When `max_characters` is set, `exa_search` calls Exa's `search_and_contents` endpoint so each result carries `text`. When `max_characters` is `None`, only metadata is returned (cheaper and faster).

All runtime parameters accept `Variable` for deferred context resolution.
