---
source_url: "https://docs.bswen.com/blog/2026-03-24-openclaw-web-search-plugins/"
title: "How to Use Exa, Tavily, and Firecrawl in OpenClaw | BSWEN"
mirrored_at: 2026-08-14T01:04:28.728Z
host: docs.bswen.com
cited_in_42a: true
mirror_canonical: "https://index.42a.ai/docs.bswen.com/blog/2026-03-24-openclaw-web-search-plugins/index"
---

> **Original source:** https://docs.bswen.com/blog/2026-03-24-openclaw-web-search-plugins/

Mar 24, 2026

## Problem

When I built research agents in OpenClaw, I had to manually install and configure web search plugins. Each plugin had different APIs, configuration formats, and dependency issues. The setup was painful.

OpenClaw 2026.3.22-beta.1 solved this by bundling Exa, Tavily, and Firecrawl as first-class plugins. But now I faced a different question: which of these three should I use, and when?

This post shows how to use OpenClaw’s bundled web search plugins. The key point is matching each plugin to its strength.

## What Changed in OpenClaw 2026.3.22-beta.1

The release notes said:

> “Exa added with native date filters, search-mode selection, and optional content extraction.” “Tavily added with dedicated tavily\_search and tavily\_extract tools.” “Firecrawl added with firecrawl\_search and firecrawl\_scrape tools.”

This means three serious web-search options are now bundled and first-class. No manual plugin install required - they work out of the box. Each has its own config namespace so I can run them alongside each other.

Research agents just got more capable out of the box.

## When to Use Each Plugin

After testing all three, I found each excels at different tasks:

Plugin

Best For

Key Feature

**Exa**

Semantic search with recency

Native date filtering

**Tavily**

Structured data extraction

Clean JSON output

**Firecrawl**

Full page scraping

JavaScript rendering

Let me show you how I use each one.

## Exa: Semantic Search with Date Filters

I use Exa when I need AI-native search that understands meaning, not just keywords. Its date filtering is unique among the three.

### When I Use Exa

-   Finding recent articles (last 7 days, last month)
-   Semantic research where keyword search fails
-   Finding related content through meaning
-   Agentic research loops where search quality matters

### Configuration

```
plugins:  exa:    apiKey: "your-exa-api-key"    defaultSearchMode: "auto"  # auto | keyword | neural    defaultNumResults: 10
```

### Basic Semantic Search

```
// Exa search with semantic understandingconst results = await exa.search({  query: "latest developments in AI agent frameworks",  numResults: 10,  useAutoprompt: true})// Results are ranked by semantic relevance, not just keyword matchresults.results.forEach(result => {  console.log(result.title)  console.log(result.url)  console.log(result.score)  // Relevance score})
```

### Date-Filtered Search

I use this feature constantly for news and recent developments:

```
// Find articles from last 7 daysconst lastWeek = new Date()lastWeek.setDate(lastWeek.getDate() - 7)const recentResults = await exa.search({  query: "OpenClaw release updates",  numResults: 5,  startPublishedDate: lastWeek.toISOString(),  endPublishedDate: new Date().toISOString()})
```

### Search with Content Extraction

```
// Search and extract full content in one callconst searchWithContent = await exa.search({  query: "LangGraph tutorial",  numResults: 5,  contents: {    text: { maxCharacters: 1000 },    highlights: { numSentences: 3 }  }})// Each result now includes extracted textsearchWithContent.results.forEach(result => {  console.log(result.text)  // Extracted content  console.log(result.highlights)  // Key highlights})
```

I use Tavily when I need clean, structured data from web searches. Its output is optimized for agent consumption.

### When I Use Tavily

-   Building knowledge bases from web content
-   Extracting specific data points from multiple pages
-   Research agents that need structured input
-   Follow-up extraction after initial discovery

### Configuration

```
plugins:  tavily:    apiKey: "your-tavily-api-key"    includeRawContent: false    maxResults: 5
```

### Basic Search with AI Answer

```
// Tavily search with structured outputconst results = await tavily.search({  query: "best practices for MCP server development",  maxResults: 5,  includeAnswer: true  // Get AI-generated answer})console.log(results.answer)  // AI-generated summaryconsole.log(results.results)  // Structured results
```

```
// Extract from specific URLsconst extracted = await tavily.extract({  urls: [    "https://docs.openclaw.ai/plugins/overview",    "https://docs.openclaw.ai/mcp/integration"  ],  extractDepth: "advanced"  // basic | advanced})// Get structured data from each URLextracted.forEach(page => {  console.log(page.url)  console.log(page.rawContent)  // Cleaned content  console.log(page.metadata)  // Page metadata})
```

### Search Specific Domains

```
// I use this for documentation-only searchesconst domainResults = await tavily.search({  query: "agent orchestration patterns",  maxResults: 10,  includeDomains: ["docs.anthropic.com", "python.langchain.com"]})
```

## Firecrawl: Full Page Scraping

I use Firecrawl when I need complete page content, especially for JavaScript-rendered pages or documentation ingestion.

### When I Use Firecrawl

-   Documentation ingestion
-   Full article/blog content extraction
-   Pages requiring JavaScript rendering
-   Converting web content to LLM-friendly format

### Configuration

```
plugins:  firecrawl:    apiKey: "your-firecrawl-api-key"    formats: ["markdown"]    waitForEvent: "load"
```

### Full Page Scrape

```
// Scrape a single page with markdown outputconst page = await firecrawl.scrape({  url: "https://docs.openclaw.ai/getting-started",  formats: ["markdown", "html"]})console.log(page.markdown)  // LLM-friendly markdownconsole.log(page.html)  // Original HTMLconsole.log(page.metadata)  // Page metadata
```

### Search and Scrape Combined

```
// Search and get full content in one callconst results = await firecrawl.search({  query: "OpenClaw browser automation guide",  limit: 5})// Each result includes full scraped contentresults.forEach(result => {  console.log(result.markdown)  // Full content})
```

### Handle JavaScript-Rendered Pages

This is Firecrawl’s superpower - it handles dynamic content:

```
// Scrape JavaScript-rendered pagesconst dynamicPage = await firecrawl.scrape({  url: "https://example.com/spa-page",  formats: ["markdown"],  waitFor: 2000,  // Wait 2 seconds for JS to render  actions: [    { type: "scroll", direction: "down" }  ]})// Get content that would be invisible to simple scrapersconsole.log(dynamicPage.markdown)
```

## Combining Plugins in a Research Agent

The real power comes from chaining these plugins together. Here’s how I built a research agent:

```
async function researchTopic(topic: string) {  // 1. Use Exa for semantic discovery with recency  const discoveries = await exa.search({    query: topic,    numResults: 10,    startPublishedDate: getLastWeekISOString(),    useAutoprompt: true  })  // 2. Use Tavily for structured extraction from top results  const topUrls = discoveries.results.slice(0, 3).map(r => r.url)  const structured = await tavily.extract({    urls: topUrls,    extractDepth: "advanced"  })  // 3. Use Firecrawl for full content if needed  if (needsFullContent(structured)) {    const fullContent = await firecrawl.scrape({      url: topUrls[0],      formats: ["markdown"]    })    return { discoveries, structured, fullContent }  }  return { discoveries, structured }}function getLastWeekISOString(): string {  const date = new Date()  date.setDate(date.getDate() - 7)  return date.toISOString()}function needsFullContent(structured: any): boolean {  // Check if we need more detail  return structured.some(page => page.rawContent.length < 500)}
```

## Common Mistakes

### Mistake 1: Using One Plugin for Everything

Each plugin is optimized for different tasks. Don’t force Firecrawl to do semantic search, or Exa to do full-page scraping. Match the tool to the job.

```
// WRONG: Using Firecrawl for semantic searchconst results = await firecrawl.search({  query: "AI agent frameworks",  limit: 10})// Firecrawl's search is basic, not semantic// CORRECT: Use Exa for semantic searchconst results = await exa.search({  query: "AI agent frameworks",  numResults: 10,  useAutoprompt: true})
```

### Mistake 2: Ignoring API Keys

While bundled, each plugin still requires its own API key:

```
# WRONG: Missing API keysplugins:  exa:    defaultSearchMode: "auto"  # No apiKey - will fail# CORRECT: Configure keysplugins:  exa:    apiKey: "your-exa-api-key"    defaultSearchMode: "auto"
```

### Mistake 3: Not Chaining Tools

The power comes from combining plugins:

```
// WRONG: Using only one toolconst results = await exa.search({ query: topic })// CORRECT: Chain tools for better resultsconst discoveries = await exa.search({ query: topic })const structured = await tavily.extract({  urls: discoveries.results.map(r => r.url)})
```

### Mistake 4: Overlooking Date Filters in Exa

Exa’s date filtering is unique among the three:

```
// WRONG: Ignoring date filtersconst results = await exa.search({  query: "OpenClaw updates"})// Gets old, potentially outdated results// CORRECT: Use date filters for recent contentconst lastMonth = new Date()lastMonth.setMonth(lastMonth.getMonth() - 1)const results = await exa.search({  query: "OpenClaw updates",  startPublishedDate: lastMonth.toISOString()})
```

### Mistake 5: Forgetting Rate Limits

Each service has its own rate limits:

```
// WRONG: No rate limitingfor (const url of urls) {  await firecrawl.scrape({ url })}// CORRECT: Add delaysfor (const url of urls) {  await firecrawl.scrape({ url })  await sleep(1000)  // Respect rate limits}
```

## Plugin Comparison

Here’s my quick reference for choosing:

Feature

Exa

Tavily

Firecrawl

**Primary Use**

Semantic search

Structured extraction

Full scraping

**Search Quality**

AI-native, semantic

Keyword-based

Basic search

**Date Filtering**

Yes (unique)

No

No

**Content Depth**

Optional extraction

Structured data

Full markdown

**JS Rendering**

No

Limited

Yes

**Rate Limits**

Per API plan

Per API plan

Per API plan

**Best For**

Research discovery

Data extraction

Documentation

## Summary

In this post, I showed how to use OpenClaw’s bundled web search plugins. The key point is matching each plugin to its strength:

-   **Use Exa** when you need semantic search with date filtering - ideal for finding recent, relevant content
-   **Use Tavily** when you need structured, clean data extraction - ideal for building knowledge bases
-   **Use Firecrawl** when you need complete page content - ideal for documentation ingestion and JS-rendered pages

All three can be configured independently and used together in research workflows. Configure your API keys, understand each plugin’s strengths, and chain them together for powerful research agents.

## Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: [Email me](https://docs.bswen.com/cdn-cgi/l/email-protection#bfddccc8dad1decfcfffd8d2ded6d391dcd0d2)

Here are also the most important links from this article along with some further resources that will help you in this scope:

-   👨‍💻 [Exa API Documentation](https://docs.exa.ai/)
-   👨‍💻 [Tavily Documentation](https://docs.tavily.com/)
-   👨‍💻 [Firecrawl Documentation](https://docs.firecrawl.dev/)
-   👨‍💻 [Reddit Discussion: OpenClaw Release Notes](https://www.reddit.com/r/OpenClaw/)

Oh, and if you found these resources useful, don’t forget to support me by [starring the repo on GitHub](https://github.com/bswen/bswen-project)!