Exa Search logo

Exa Search

Organization
exa-labs
exa-search

Call Exa Search directly with cURL or raw HTTP. Use when an agent needs Exa semantic web retrieval from POST /search without an SDK, including ranked results, domain or category filters, freshness-aware result content, highlights or text extraction, structured output, or streaming search responses.

Overview

Publisherexa-labs
Repositoryagent-skills
Skill nameexa-search
Stars
65
Forks
6
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by exa-labs on GitHub. Read the source before you install it.

Installation

Install the Exa Search AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/exa-labs/agent-skills/tree/main/skills/exa-search
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/exa-labs/agent-skills.git /tmp/agent-skills
mkdir -p .claude/skills
cp -r /tmp/agent-skills/skills/exa-search .claude/skills/exa-search
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Exa Search in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Exa Search on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Exa Search is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Exa Search

Requires API key: Get one at https://dashboard.exa.ai/api-keys

Header: x-api-key: $EXA_API_KEY

Use POST https://api.exa.ai/search for semantic web retrieval, ranked results, and optional result-level extraction in one raw HTTP call. Start with type: "auto" for general retrieval. Add contents only when the caller needs page text, highlights, summaries, freshness-controlled crawling, subpages, or extracted links.

Quick Start (cURL)

Basic search

bash
curl -sS -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "latest developments in LLMs",
    "type": "auto",
    "numResults": 10
  }'

Search with highlights

bash
curl -sS -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "latest developments in LLMs",
    "type": "auto",
    "numResults": 5,
    "contents": {
      "highlights": true
    }
  }'

With filters and freshness

bash
curl -sS -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "AI regulation policy updates",
    "type": "auto",
    "category": "news",
    "numResults": 10,
    "includeDomains": ["reuters.com", "bbc.com"],
    "startPublishedDate": "2025-01-01",
    "contents": {
      "text": {
        "maxCharacters": 2000
      },
      "maxAgeHours": 24,
      "livecrawlTimeout": 12000
    }
  }'

Deep search

bash
curl -sS -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "map the major technical and commercial tradeoffs in sodium-ion batteries for grid storage",
    "type": "deep",
    "numResults": 8
  }'

Endpoint

text
POST https://api.exa.ai/search

Authentication: x-api-key: <API_KEY> header. Exa also accepts Authorization: Bearer <API_KEY>, but prefer x-api-key in cURL examples for consistency.

Use this endpoint when the agent needs search results. If the agent already has URLs and only needs extraction, use POST /contents instead.

Parameters

Core request parameters

ParameterTypeRequiredDefaultDescription
querystringYes-Natural-language search query. Long, semantically rich descriptions work well.
typestringNoautoSearch method: auto, lite, deep-lite, deep, or deep-reasoning.
numResultsintegerNo10Number of results to return. Use small values for agent loops; maximum is 100.
categorystringNo-Specialized result type: company, people, research paper, news, personal site, or financial report.
includeDomainsstring[]No-Only return results from these domains, paths, or wildcard patterns. Max 1200.
excludeDomainsstring[]No-Exclude these domains, paths, or wildcard patterns. Max 1200.
startPublishedDatestringNo-ISO 8601 lower bound for result publication date.
endPublishedDatestringNo-ISO 8601 upper bound for result publication date.
userLocationstringNo-Two-letter ISO country code such as US or GB.
moderationbooleanNofalseFilter unsafe content from results.
additionalQueriesstring[]No-Extra query variants for deep-search variants. Use alongside the main query.
systemPromptstringNo-Instructions for synthesized output and deep-search planning, such as source preferences.
outputSchemaobjectNo-JSON Schema controlling output.content. Adds synthesized output and grounding.
streambooleanNofalseIf true, returns SSE instead of a single JSON response.
compliancestringNo-Enterprise-only compliance mode, such as hipaa, when enabled for the account.

Content parameters nested under contents

On /search, text, highlights, and summary must be nested under contents.

ParameterTypeRequiredDefaultDescription
contents.textboolean or objectNo-Return full page text as markdown. Object form supports maxCharacters, includeHtmlTags, verbosity, includeSections, and excludeSections.
contents.highlightsboolean or objectNo-Return query-relevant excerpts. Prefer true for agent workflows unless a fixed character budget is required.
contents.summaryboolean or objectNo-Return per-result LLM summaries. Use sparingly because each result adds synthesis work.
contents.maxAgeHoursintegerNo-Freshness control. 0 always live crawls; -1 uses cache only; omit for default cache-first behavior with crawl fallback.
contents.livecrawlTimeoutintegerNo10000Timeout for live crawling in milliseconds. Use 10000 to 15000 for most freshness-sensitive calls.
contents.subpagesintegerNo0Number of linked subpages to crawl per result.
contents.subpageTargetstring or string[]No-Terms used to prioritize which subpages matter, such as ["api", "pricing"].
contents.extras.linksintegerNo0Number of links to extract from each result page.
contents.extras.imageLinksintegerNo0Number of image URLs to extract from each result page.

Text object options

ParameterTypeDefaultDescription
maxCharactersinteger-Character limit for returned text. Use this instead of tokensNum.
includeHtmlTagsbooleanfalsePreserve HTML tags in output.
verbositystringcompactcompact, standard, or full. Pair fresh section-aware extraction with contents.maxAgeHours: 0.
includeSectionsstring[]-Only include selected sections: header, navigation, banner, body, sidebar, footer, metadata.
excludeSectionsstring[]-Exclude selected sections from the same section list.

Highlights object options

Prefer contents.highlights: true for the highest-quality default. Only use object form when the agent needs a custom focus or budget.

ParameterTypeDefaultDescription
querystring-Custom query guiding which excerpts are returned.
maxCharactersinteger-Cap highlight characters per URL. Omit unless the caller has a strict budget.

Summary object options

ParameterTypeDefaultDescription
querystring-Custom query for the summary.
schemaobject-JSON Schema for structured per-result summaries.

Search Types

Search type controls the retrieval and synthesis mode. Pick the mode for the workflow, not just the output format. Use auto or a deep variant for outputSchema, not lite. Use deeper modes when the search process itself needs more planning, synthesis, or reasoning.

TypeBest forTradeoff
autoGeneral default search and most new integrationsBalances speed and quality without requiring the caller to tune retrieval strategy.
liteLow-latency, low-cost chat, voice, autocomplete, and agent loopsCached retrieval with a reduced parameter set
deep-liteLightweight research or synthesisAdds more planning and synthesis than auto while staying lighter than full deep.
deepMulti-step research, comparisons, and synthesis-heavy retrievalHigher latency; better when the query needs exploration across several sources.
deep-reasoningHard research tasks with high ambiguity or complex tradeoffsHighest latency and reasoning depth.

With type: "lite", supported parameters are query (a single string), objective, userIdentifier, metadata, category, numResults, contents.highlights, contents.text, contents.snapshotAsOf, userLocation, includeDomains, excludeDomains, startPublishedDate, endPublishedDate, moderation, and compliance. Other documented search parameters are rejected, including outputSchema, systemPrompt, stream, and freshness options such as contents.maxAgeHours. Lite serves cached content without fetching pages at query time.

Use auto unless latency or reasoning depth is the primary constraint. Use lite for time-sensitive or cost-sensitive calls. Use deep, deep-lite, or deep-reasoning when the query needs multi-step source discovery, comparison, or synthesis.

Mode-only examples

json
{
  "query": "recent product launches from major AI chip companies",
  "type": "lite",
  "numResults": 5
}
json
{
  "query": "compare competing explanations for the recent rise in grid-scale battery deployments",
  "type": "deep",
  "numResults": 8
}

Structured Output

Use systemPrompt for behavior and outputSchema for shape. Keep the schema compact: a handful of named fields, shallow nesting, arrays that declare items. The example below is about as wide as /search wants. If you need more columns, drop the least important ones rather than grow the schema.

bash
curl -sS -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "compare the latest frontier AI model releases",
    "type": "deep",
    "systemPrompt": "Prefer official sources and avoid duplicate results.",
    "outputSchema": {
      "type": "object",
      "properties": {
        "models": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "notable_claims": {
                "type": "array",
                "items": { "type": "string" }
              }
            },
            "required": ["name", "notable_claims"]
          }
        }
      },
      "required": ["models"]
    },
    "contents": {
      "highlights": true
    }
  }'

Keep schemas compact and bounded. Do not add citation fields to the schema; grounding is returned separately in output.grounding.

Streaming

Streaming applies to synthesized output, so include outputSchema along with -N, Accept: text/event-stream, and stream: true. Without outputSchema, the endpoint returns the normal JSON search response even when stream is true.

bash
curl -sS -N -X POST "https://api.exa.ai/search" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -H "x-api-key: $EXA_API_KEY" \
  -d '{
    "query": "recent grid-scale battery deployments",
    "type": "deep",
    "stream": true,
    "outputSchema": {
      "type": "object",
      "properties": {
        "summary": { "type": "string" }
      },
      "required": ["summary"]
    },
    "contents": {
      "highlights": true
    }
  }'

Treat streaming as SSE rather than JSON. Each data: frame contains an OpenAI-compatible chat completion chunk; read partial text from choices[0].delta.content and handle completion or error frames defensively.

Response Fields

FieldTypeDescription
requestIdstringUnique request identifier.
resultsarrayRanked result objects.
results[].titlestringPage title.
results[].urlstringPage URL.
results[].publishedDatestring or nullEstimated publication date when available.
results[].authorstring or nullAuthor when available.
results[].textstringReturned when contents.text is requested.
results[].highlightsstring[]Returned when contents.highlights is requested.
results[].highlightScoresnumber[]Similarity scores for highlights.
results[].summarystringReturned when contents.summary is requested.
results[].subpagesarrayNested result objects from subpage crawling.
results[].extras.linksstring[]Extracted links when requested.
output.contentstring or objectSynthesized output when outputSchema is provided.
output.groundingarrayCitations and confidence labels for synthesized fields.
costDollars.totalnumberTotal request cost when returned.
searchTimenumberSearch latency when returned.

Critical Pitfalls

  • Keep text, highlights, and summary inside contents on /search.
  • Do not send top-level text, highlights, or summary; that shape belongs to /contents.
  • Do not send tokensNum; use contents.text.maxCharacters to cap extracted text.
  • Do not use useAutoprompt, numSentences, or highlightsPerUrl in new requests.
  • Use contents.maxAgeHours instead of livecrawl.
  • Use documented categories only: company, people, research paper, news, personal site, and financial report.
  • Avoid invalid category/filter combinations. company and people do not support startPublishedDate or endPublishedDate. company supports excludeDomains; people does not, and people only accepts LinkedIn domains in includeDomains.
  • Pick one of contents.highlights, contents.text, or contents.summary by default. Stack modes only when the caller truly needs multiple views of each page.
  • Expect SSE only when stream: true is paired with outputSchema; otherwise /search returns its normal JSON response.

Frequently asked questions

What does the Exa Search AI skill do?

Call Exa Search directly with cURL or raw HTTP. Use when an agent needs Exa semantic web retrieval from POST /search without an SDK, including ranked results, domain or category filters, freshness-aware result content, highlights or text extraction, structured output, or streaming search responses.

Why use Exa Search on TypingMind?

Because you install it once and use it with any model. Exa Search is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Exa Search in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/exa-labs/agent-skills/tree/main/skills/exa-search. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Exa Search?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Exa Search?

As many as you like. As long as a model supports skills, you can use Exa Search with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Exa Search AI skill free?

Yes. It is published on GitHub by exa-labs under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇