AgentStack
SKILL verified MIT Self-run

Exa Websets Search

skill-benjaminjackson-exa-skills-search · by benjaminjackson

Use for creating websets, running searches, importing CSV data, managing items, and adding enrichments to extract structured data.

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add skill-benjaminjackson-exa-skills-search

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Exa Websets Search? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Exa Websets Search

Comprehensive webset management including creation, search, imports, items, and enrichments.

Use --help to see available commands and verify usage before running:

exa-ai  --help

Working with Complex Shell Commands

When using the Bash tool with complex shell syntax, follow these best practices for reliability:

  1. Run commands directly: Capture JSON output directly rather than nesting command substitutions
  2. Parse in subsequent steps: Use jq to parse output in a follow-up command if needed
  3. Avoid nested substitutions: Complex nested $(...) can be fragile; break into sequential steps

Example:

# Less reliable: nested command substitution
webset_id=$(exa-ai webset-create --search '{"query":"tech startups","count":1}' | jq -r '.webset_id')

# More reliable: run directly, then parse
exa-ai webset-create --search '{"query":"tech startups","count":1}'
# Then in a follow-up command if needed:
webset_id=$(cat output.json | jq -r '.webset_id')

Critical Requirements

Universal rules across all operations:

  1. Start with minimal counts (1-5 results): Initial searches are test spikes to validate quality. ALWAYS default to count:1 unless user explicitly requests more.
  2. Three-step workflow - Validate, Expand, Enrich: (1) Create with count:1 to test search quality, (2) Expand search count if results are good, (3) Add enrichments only after validated, expanded results.
  3. No enrichments during validation: Never add enrichments when testing with count:1. Validate search quality first, expand count second, add enrichments last.
  4. Avoid --wait flag: Do NOT use --wait flag in commands. It's designed for human interactive use, not automated workflows.
  5. Maintain query AND criteria consistency: When scaling up or appending searches, use the EXACT same query AND criteria that you validated. Omitting criteria causes Exa to regenerate them on-the-fly, producing inconsistent results.

Credit Costs

Pricing: $50/month = 8,000 credits ($0.00625 per credit)

Cost per operation:

  • Each webset item: 10 credits ($0.0625)
  • Standard enrichment: 2 credits ($0.0125)
  • Email enrichment: 5 credits ($0.03125)

Why start with count:1: Testing with 1 result costs 10 credits ($0.0625). A failed search with count:100 wastes 1,000 credits ($6.25) - 100x more expensive.

Why enrich last: Enriching bad results wastes credits. Always validate first, expand second, enrich last.

Quick Command Reference

exa-ai --help

Output Formats

All exa-ai webset commands support output formats:

  • JSON (default): Pipe to jq to extract specific fields (e.g., | jq -r '.webset_id')
  • toon: Compact, readable format for direct viewing
  • pretty: Human-friendly formatted output
  • text: Plain text output

Webset Management

Core operations for managing webset collections.

Entity Types

  • company: Companies and organizations
  • person: Individual people
  • article: News articles and blog posts
  • research_paper: Academic papers
  • custom: Custom entity types (define with --entity-description)

Create Webset from Search

webset_id=$(exa-ai webset-create \
  --search '{"query":"AI startups in San Francisco","count":1}' | jq -r '.webset_id')

Create with Detailed Search Criteria

exa-ai webset-create \
  --search '{
    "query": "Technology companies focused on developer tools",
    "count": 1,
    "entity": {
      "type": "company"
    },
    "criteria": [
      {
        "description": "Companies with 50-500 employees indicating growth stage"
      },
      {
        "description": "Primary product is developer tools, APIs, or infrastructure"
      }
    ]
  }'

Create with Custom Entity

exa-ai webset-create \
  --search '{
    "query": "Nonprofits focused on economic justice",
    "count": 1,
    "entity": {
      "type": "custom",
      "description": "nonprofit"
    },
    "criteria": [
      {
        "description": "Primary focus on economic justice"
      },
      {
        "description": "Annual operating budget between $1M and $10M"
      }
    ]
  }'

Create from CSV Import

import_id=$(exa-ai import-create companies.csv \
  --count 100 \
  --title "Companies" \
  --format csv \
  --entity-type company | jq -r '.import_id')

exa-ai webset-create --import $import_id

Three-Step Workflow: Validate → Expand → Enrich

Step 1: VALIDATE - Create with count:1 (NO enrichments)

webset_id=$(exa-ai webset-create \
  --search '{"query":"tech startups","count":1}' | jq -r '.webset_id')

exa-ai webset-item-list $webset_id

⚠️ REQUIRED: Manually verify the result is relevant before continuing. If not, adjust the query and start over.


Step 2: EXPAND - Gradually increase count with verification at each stage

# Expand to 2 results (use same query and criteria from validation)
exa-ai webset-search-create $webset_id \
  --query "tech startups" \
  --behavior override \
  --count 2

exa-ai webset-item-list $webset_id

⚠️ REQUIRED: Check quality at this scale. Repeat with larger counts (5, 10, 25, 50, 100) until you reach your target.

Loop this step: Keep expanding gradually (2 → 5 → 10 → 25 → 50 → 100) with verification between each expansion.


Step 3: ENRICH - Add enrichments only after confirming quality

exa-ai enrichment-create $webset_id \
  --description "Company website" --format url --title "Website"

exa-ai enrichment-create $webset_id \
  --description "Employee count" --format text --title "Team Size"

Interpreting Criterion Success Rates

CRITICAL: Criteria are evaluated conditionally - when one criterion fails, others may not run. A low success rate doesn't indicate that criterion is restrictive; it means OTHER criteria are filtering results first. Only interpret a low success rate as "restrictive" when OTHER criteria have high success rates (>80%).

Manage Websets

exa-ai webset-list
exa-ai webset-get ws_abc123
exa-ai webset-update ws_abc123 --metadata '{"status":"active","owner":"team"}'
exa-ai webset-delete ws_abc123

Search Operations

Run searches within a webset to add new items.

Search Behavior

Control how new search results are combined with existing items:

  • append (default): Add new items to existing collection
  • Requires previous search results to exist
  • Error if webset has no previous search: "No previous search found"
  • Default behavior when --behavior is omitted
  • override: Replace entire collection with search results
  • REQUIRED for first search on a webset
  • Use when starting fresh or completely replacing results

CRITICAL - First search requirement: The first webset-search-create on a webset MUST explicitly use --behavior override. Since the default is append, omitting --behavior will fail with "No previous search found" error. Subsequent searches can omit the flag (defaults to append).

Query and Criteria Consistency

CRITICAL: When appending or scaling up searches, maintain IDENTICAL query and criteria from your validated search.

Why This Matters

Using different criteria causes Exa to generate new search parameters on-the-fly, which:

  • Violates consistency and produces mismatched results
  • Reduces result quality compared to validated criteria
  • Makes it impossible to reproduce or debug issues

Complete Example

# Step 1: Test search with criteria (MUST use override for first search)
exa-ai webset-search-create ws_abc123 \
  --query "Progressive nonprofits in California" \
  --behavior override \
  --count 1 \
  --criteria '[
    {"description": "Annual budget between $1M and $10M"},
    {"description": "Primary focus on economic justice, affordability, living wages, or worker power"},
    {"description": "Established communications, narrative strategy, or messaging function"}
  ]'

# Verify quality, then append MORE results with IDENTICAL query and criteria
exa-ai webset-search-create ws_abc123 \
  --query "Progressive nonprofits in California" \
  --behavior append \
  --count 5 \
  --criteria '[
    {"description": "Annual budget between $1M and $10M"},
    {"description": "Primary focus on economic justice, affordability, living wages, or worker power"},
    {"description": "Established communications, narrative strategy, or messaging function"}
  ]'

Best Practice: Save Criteria to File

# Create criteria file once
cat > criteria.json  industries.json 

## Schema Design

### MUST: Use object wrapper for schemas

**Applies to**: answer, search, find-similar, get-contents

When using schema parameters (`--output-schema` or `--summary-schema`), always wrap properties in an object:

```json
{"type":"object","properties":{"field_name":{"type":"string"}}}

DO NOT use bare properties without the object wrapper:

{"properties":{"field_name":{"type":"string"}}}  // ❌ Missing "type":"object"

Why: The Exa API requires a valid JSON Schema with an object type at the root level. Omitting this causes validation errors.

Examples:

# ✅ CORRECT - object wrapper included
exa-ai search "AI news" \
  --summary-schema '{"type":"object","properties":{"headline":{"type":"string"}}}'

# ❌ WRONG - missing object wrapper
exa-ai search "AI news" \
  --summary-schema '{"properties":{"headline":{"type":"string"}}}'

Output Format Selection

MUST NOT: Mix toon format with jq

Applies to: answer, context, search, find-similar, get-contents

toon format produces YAML-like output, not JSON. DO NOT pipe toon output to jq for parsing:

# ❌ WRONG - toon is not JSON
exa-ai search "query" --output-format toon | jq -r '.results'

# ✅ CORRECT - use JSON (default) with jq
exa-ai search "query" | jq -r '.results[].title'

# ✅ CORRECT - use toon for direct reading only
exa-ai search "query" --output-format toon

Why: jq expects valid JSON input. toon format is designed for human readability and produces YAML-like output that jq cannot parse.

SHOULD: Choose one output approach

Applies to: answer, context, search, find-similar, get-contents

Pick one strategy and stick with it throughout your workflow:

  1. Approach 1: toon only - Compact YAML-like output for direct reading
  • Use when: Reading output directly, no further processing needed
  • Token savings: ~40% reduction vs JSON
  • Example: exa-ai search "query" --output-format toon
  1. Approach 2: JSON + jq - Extract specific fields programmatically
  • Use when: Need to extract specific fields or pipe to other commands
  • Token savings: ~80-90% reduction (extracts only needed fields)
  • Example: exa-ai search "query" | jq -r '.results[].title'
  1. Approach 3: Schemas + jq - Structured data extraction with validation
  • Use when: Need consistent structured output across multiple queries
  • Token savings: ~85% reduction + consistent schema
  • Example: exa-ai search "query" --summary-schema '{...}' | jq -r '.results[].summary | fromjson'

Why: Mixing approaches increases complexity and token usage. Choosing one approach optimizes for your use case.


Shell Command Best Practices

MUST: Run commands directly, parse separately

Applies to: monitor, search (websets), research, and all skills using complex commands

When using the Bash tool with complex shell syntax, run commands directly and parse output in separate steps:

# ❌ WRONG - nested command substitution
webset_id=$(exa-ai webset-create --search '{"query":"..."}' | jq -r '.webset_id')

# ✅ CORRECT - run directly, then parse
exa-ai webset-create --search '{"query":"..."}'
# Then in a follow-up command:
webset_id=$(cat output.json | jq -r '.webset_id')

Why: Complex nested $(...) command substitutions can fail unpredictably in shell environments. Running commands directly and parsing separately improves reliability and makes debugging easier.

MUST NOT: Use nested command substitutions

Applies to: All skills when using complex multi-step operations

Avoid nesting multiple levels of command substitution:

# ❌ WRONG - deeply nested
result=$(exa-ai search "$(cat query.txt | tr '\n' ' ')" --num-results $(cat config.json | jq -r '.count'))

# ✅ CORRECT - sequential steps
query=$(cat query.txt | tr '\n' ' ')
count=$(cat config.json | jq -r '.count')
exa-ai search "$query" --num-results $count

Why: Nested command substitutions are fragile and hard to debug when they fail. Sequential steps make each operation explicit and easier to troubleshoot.

SHOULD: Break complex commands into sequential steps

Applies to: All skills when working with multi-step workflows

For readability and reliability, break complex operations into clear sequential steps:

# ❌ Less maintainable - everything in one line
exa-ai webset-create --search '{"query":"startups","count":1}' | jq -r '.webset_id' | xargs -I {} exa-ai webset-search-create {} --query "AI" --behavior override

# ✅ More maintainable - clear steps
exa-ai webset-create --search '{"query":"startups","count":1}'
webset_id=$(jq -r '.webset_id'

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [benjaminjackson](https://github.com/benjaminjackson)
- **Source:** [benjaminjackson/exa-skills](https://github.com/benjaminjackson/exa-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.