# Dexter Web Search Tools: How the AI Agent Searches the Internet

> Discover Dexter's AI web search tools. Learn how Dexter dynamically chooses between Exa, Perplexity, and Tavily based on your API key configuration for efficient internet searches.

- Repository: [Virat Singh/dexter](https://github.com/virattt/dexter)
- Tags: how-to-guide
- Published: 2026-02-16

---

**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](https://github.com/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`](https://github.com/virattt/dexter/blob/main/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`](https://github.com/virattt/dexter/blob/main/src/tools/search/exa.ts), where the `exaSearch` tool is created at line 25:

```typescript
// 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`](https://github.com/virattt/dexter/blob/main/src/tools/search/perplexity.ts) at line 51:

```typescript
// 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`](https://github.com/virattt/dexter/blob/main/src/tools/search/tavily.ts) starting at line 17:

```typescript
// 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`](https://github.com/virattt/dexter/blob/main/src/tools/registry.ts)

The decision logic that determines which web search tool to activate is centralized in [`src/tools/registry.ts`](https://github.com/virattt/dexter/blob/main/src/tools/registry.ts) (lines 58-77). The registry checks environment variables in strict priority order: **Exa → Perplexity → Tavily**.

```typescript
// 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:

```bash

# 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:

```bash

# 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:

```typescript
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_search`** tool 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.ts`](https://github.com/virattt/dexter/blob/main/src/tools/registry.ts) based on the presence of `EXASEARCH_API_KEY`, `PERPLEXITY_API_KEY`, or `TAVILY_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`](https://github.com/virattt/dexter/blob/main/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`](https://github.com/virattt/dexter/blob/main/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`](https://github.com/virattt/dexter/blob/main/exa.ts) for Exa integration, [`perplexity.ts`](https://github.com/virattt/dexter/blob/main/perplexity.ts) for Perplexity integration, and [`tavily.ts`](https://github.com/virattt/dexter/blob/main/tavily.ts) for Tavily integration. The runtime selection and registration logic resides in [`src/tools/registry.ts`](https://github.com/virattt/dexter/blob/main/src/tools/registry.ts).