Skip to main content

Exa Search Plugin

The Exa plugin provides AI-native search and content extraction through the Exa API. It supports neural (semantic) search, keyword search, and an auto mode that selects the best approach for each query. The plugin also doubles as a content extractor, pulling clean text from web pages.

Source: packages/plugins/exa/src/exa.plugin.ts

Overview

PropertyValue
Plugin IDexa
Categorysearch
Capabilitiessearch, content-extractor
Version1.0.0
Configuration Modehybrid
Auto-enableNo
SDKexa-js

The plugin implements three interfaces: IPlugin, ISearchPlugin, and IContentExtractorPlugin.

Architecture

Configuration

Settings Schema

SettingTypeRequiredDefaultEnv VariableDescription
apiKeystringYes--PLUGIN_EXA_API_KEYYour Exa API key. Marked as secret.
searchTypestringNoauto--Search mode: auto, neural, or keyword.
maxResultsnumberNo10--Default max results per search. Range: 1--100.
categorystringNo""--Category filter for results (see below).

Search Types

ModeDescription
autoExa chooses the best approach per query. Recommended for general use.
neuralSemantic search that understands meaning, not just keywords. Best for conceptual queries.
keywordTraditional keyword matching. Best for exact phrases or technical terms.

Category Filters

Restrict results to a specific content type:

CategoryDescription
companyCompany websites and pages
research paperAcademic papers and research
newsNews articles
tweetTwitter/X posts
personal sitePersonal blogs and portfolios
githubGitHub repositories and pages

Leave empty for unrestricted search across all categories.

Search Capability

SearchOptions Mapping

SearchOptions FieldExa SDK ParameterNotes
queryFirst argumentRequired search query.
limitnumResultsFalls back to settings.maxResults or 10.
settings.searchTypetypeauto, neural, or keyword.
settings.categorycategoryOptional content category filter.
includeDomainsincludeDomainsRestrict results to these domains.
excludeDomainsexcludeDomainsExclude results from these domains.
timeRangestartPublishedDateConverted to ISO date relative to now.

Time Range Conversion

const TIME_RANGE_DAYS: Record<string, number> = {
day: 1,
week: 7,
month: 30,
year: 365
};
// Converted to: new Date(Date.now() - days * 86400000).toISOString()

Response Format

Each SearchResult includes:

FieldSource
titleresult.title
urlresult.url
publishedDateresult.publishedDate
sourceresult.author
faviconUrlresult.favicon
position1-based index

Content Extraction Capability

The Exa plugin implements IContentExtractorPlugin, providing two extraction methods.

Single URL Extraction

const result = await exaPlugin.extract({
url: 'https://example.com/article',
settings: { apiKey: 'exa-...' }
});
// result.content contains the extracted text

The extract() method calls client.getContents() with text: true and livecrawl: 'fallback'. The livecrawl option uses live crawling as a backup when cached content is unavailable.

Batch Extraction

const results = await exaPlugin.extractBatch(['https://example.com/page1', 'https://example.com/page2'], {
settings: { apiKey: 'exa-...' }
});

Batch extraction sends all URLs in a single API call. On failure, it returns error results for every URL rather than throwing.

Supported Formats

The content extractor returns text format only:

getSupportedFormats(): readonly ('text' | 'html' | 'markdown')[] {
return ['text'];
}

URL Validation

The canExtract() method accepts any http: or https: URL.

Error Handling

ScenarioBehavior
Missing API keyThrows Error with message pointing to settings or PLUGIN_EXA_API_KEY.
Search failureLogs error via context logger, re-throws to caller.
Extraction failure (single)Returns { success: false, error: '...' } instead of throwing.
Extraction failure (batch)Returns error results for all URLs in the batch.

Client Instantiation

A new Exa client is created for each operation using the API key from settings:

private getClient(settings?: PluginSettings): Exa {
const apiKey = settings?.apiKey as string;
if (!apiKey) {
throw new Error(API_KEY_ERROR);
}
return new Exa(apiKey);
}

This per-request approach ensures that user-scoped API keys are always applied correctly.

Lifecycle

MethodBehavior
onLoad(context)Stores plugin context for logging.
onUnload()Clears stored context.
healthCheck()Returns healthy (actual availability depends on a valid API key).
isAvailable()Always returns true.

Usage in the Platform

Exa serves dual roles during work generation:

  1. Search provider -- Finds semantically relevant information about work items using neural search.
  2. Content extractor -- Pulls clean text from discovered web pages to enrich work descriptions.

Rate Limits

Rate limit tracking is not performed client-side (getRateLimitInfo() returns -1 for both fields). Exa enforces limits at the API level based on your account plan.