Implement Exa PII handling, data retention, and GDPR/CCPA compliance patterns.
Use when handling sensitive data, implementing data redaction, configuring retention policies,
or ensuring compliance with privacy regulations for Exa integrations.
Trigger with phrases like "exa data", "exa PII",
"exa GDPR", "exa data retention", "exa privacy", "exa CCPA".
Manage search result data from Exa's neural search API. Covers content extraction scope control (text vs highlights vs summary), result caching with TTL, citation deduplication, token budget management for LLM context windows, and structured summary extraction.
Prerequisites
exa-js SDK installed and configured
Optional: lru-cache for in-memory caching, ioredis for Redis
Understanding of Exa content options (text, highlights, summary)
Instructions
Step 1: Control Content Extraction Scope
import Exa from "exa-js";
const exa = new Exa(process.env.EXA_API_KEY);
// Tier 1: Metadata only (cheapest, fastest)
async function searchMetadataOnly(query: string) {
return exa.search(query, {
type: "auto",
numResults: 10,
// No content options — returns URLs, titles, scores only
});
}
// Tier 2: Highlights only (balanced cost/value)
async function searchWithHighlights(query: string) {
return exa.searchAndContents(query, {
numResults: 10,
highlights: {
maxCharacters: 500,
query: query, // focus highlights on the original query
},
});
}
// Tier 3: Full text with character limit
async function searchWithText(query: string, maxChars = 2000) {
return exa.searchAndContents(query, {
numResults: 5,
text: { maxCharacters: maxChars },
highlights: { maxCharacters: 300 },
});
}
// Tier 4: Structured summary (LLM-generated per result)
async function searchWithSummary(query: string) {
return exa.searchAndContents(query, {
numResults: 5,
summary: { query: query },
// summary returns a concise LLM-generated summary per result
});
}
function deduplicateResults(results: any[]): any[] {
const seen = new Map<string, any>();
for (const result of results) {
const domain = new URL(result.url).hostname;
const key = `${domain}:${result.title}`;
if (!seen.has(key) || result.score > seen.get(key).score) {
seen.set(key, result);
}
}
return Array.from(seen.values());
}
Step 5: Structured Summary Extraction
// Use summary.schema for structured data extraction
const results = await exa.searchAndContents(
"YC-backed AI startups Series A 2025",
{
numResults: 10,
category: "company",
summary: {
query: "company name, funding amount, what they do",
// schema can define JSON structure for the summary output
},
}
);
// Each result.summary contains a structured summary
for (const r of results.results) {
console.log(`${r.title}: ${r.summary}`);
}