Dexter Web Search Tools: How the AI Agent Searches the Internet
Dexter uses a single web_search tool that dynamically selects between Exa, Perplexity, or Tavily based on which API key is configured in your environment.
The open-source AI agent framework virattt/dexter provides intelligent web search capabilities through a unified interface. Rather than hardcoding a specific search provider, Dexter's web search tools adapt at runtime to whichever third-party API credentials you provide.
How Dexter Implements Web Search Tools
Dexter abstracts web search functionality behind a single tool name: web_search. This abstraction allows the LLM to request internet searches without knowing which specific provider will handle the query.
The concrete implementation is injected at runtime by the tool registry located in src/tools/registry.ts. This registry checks for environment variables in a specific priority order and instantiates the corresponding search provider.
The Three Web Search Providers
Dexter supports three distinct web search backends, selected automatically based on API key availability.
Exa (Primary)
When EXASEARCH_API_KEY is present in your environment, Dexter uses Exa as its web search provider. Exa provides fast, indexed web search with structured data retrieval.
The implementation resides in src/tools/search/exa.ts, where the exaSearch tool is created at line 25:
// src/tools/search/exa.ts (lines 25-33)
export const exaSearch = tool(
async ({ query }) => {
// Exa search implementation
},
{
name: "web_search",
description: WEB_SEARCH_DESCRIPTION,
schema: z.object({ query: z.string() }),
}
);
Perplexity (Fallback)
If no Exa key is found but PERPLEXITY_API_KEY is set, Dexter falls back to Perplexity. This provider offers LLM-backed search with built-in citation support.
The implementation is defined in src/tools/search/perplexity.ts at line 51:
// src/tools/search/perplexity.ts (lines 51-57)
export const perplexitySearch = tool(
async ({ query }) => {
// Perplexity API integration
},
{
name: "web_search",
description: WEB_SEARCH_DESCRIPTION,
schema: z.object({ query: z.string() }),
}
);
Tavily (Default)
When neither Exa nor Perplexity keys are available, Dexter uses Tavily if TAVILY_API_KEY is configured. Tavily provides a lightweight web search API optimized for AI agents.
The implementation lives in src/tools/search/tavily.ts starting at line 17:
// src/tools/search/tavily.ts (lines 17-25)
export const tavilySearch = tool(
async ({ query }) => {
// Tavily search execution
},
{
name: "web_search",
description: WEB_SEARCH_DESCRIPTION,
schema: z.object({ query: z.string() }),
}
);
Runtime Selection Logic in src/tools/registry.ts
The decision logic that determines which web search tool to activate is centralized in src/tools/registry.ts (lines 58-77). The registry checks environment variables in strict priority order: Exa → Perplexity → Tavily.
// src/tools/registry.ts (excerpt)
if (process.env.EXASEARCH_API_KEY) {
tools.push({ name: 'web_search', tool: exaSearch, description: WEB_SEARCH_DESCRIPTION });
} else if (process.env.PERPLEXITY_API_KEY) {
tools.push({ name: 'web_search', tool: perplexitySearch, description: WEB_SEARCH_DESCRIPTION });
} else if (process.env.TAVILY_API_KEY) {
tools.push({ name: 'web_search', tool: tavilySearch, description: WEB_SEARCH_DESCRIPTION });
}
Only the first matching provider is registered as the web_search tool. This ensures deterministic behavior while allowing flexibility in deployment configurations.
Configuring Web Search Tools in Dexter
To enable web search functionality, set one of the following environment variables before starting Dexter:
# Option 1: Exa (recommended)
export EXASEARCH_API_KEY=your_exa_api_key
# Option 2: Perplexity
export PERPLEXITY_API_KEY=your_perplexity_api_key
# Option 3: Tavily
export TAVILY_API_KEY=your_tavily_api_key
Once configured, the Dexter CLI automatically uses the web_search tool when processing queries that require current information:
# Start Dexter
bun run start
# Query that triggers web search
> What are today's top headlines in artificial intelligence?
Programmatic Usage
If embedding Dexter as a library, you can access the configured web search tool directly through the registry:
import { getToolRegistry } from '@/tools/registry';
// Retrieve the tool registry (automatically selects provider based on env vars)
const tools = getToolRegistry('gpt-4o');
const webSearch = tools.find(t => t.name === 'web_search')?.tool;
if (webSearch) {
const result = await webSearch.invoke({
query: 'latest developments in quantum computing'
});
console.log(result); // Contains search results with URLs and snippets
}
Summary
- Dexter exposes a unified
web_searchtool to the LLM, abstracting the underlying provider. - Three search providers are supported: Exa (primary), Perplexity (fallback), and Tavily (default).
- Runtime selection occurs in
src/tools/registry.tsbased on the presence ofEXASEARCH_API_KEY,PERPLEXITY_API_KEY, orTAVILY_API_KEY. - Only one provider is active at a time, determined by priority order: Exa → Perplexity → Tavily.
Frequently Asked Questions
Which web search tool does Dexter use by default?
Dexter does not have a hardcoded default; it selects the first available provider based on environment variable priority. If EXASEARCH_API_KEY is set, it uses Exa. If not, it checks for PERPLEXITY_API_KEY for Perplexity. Only if neither is present will it use Tavily when TAVILY_API_KEY is configured.
Can I use multiple web search providers simultaneously in Dexter?
No. The architecture in src/tools/registry.ts registers only one implementation of the web_search tool. The selection logic uses if-else chains that stop at the first match, ensuring deterministic behavior and preventing tool name collisions in the LLM context.
How does Dexter decide when to perform a web search?
The decision is driven by the LLM based on the system prompt description defined in src/tools/descriptions/web-search.ts. When a user query requires current information not present in the model's training data—such as recent news, current stock prices, or real-time events—the LLM invokes the web_search tool automatically.
What file contains the web search tool implementations?
The implementations are split across three provider-specific files in the src/tools/search/ directory: exa.ts for Exa integration, perplexity.ts for Perplexity integration, and tavily.ts for Tavily integration. The runtime selection and registration logic resides in src/tools/registry.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →