exa-policy-guardrails
Implement Exa lint rules, policy enforcement, and automated guardrails. Use when setting up code quality rules for Exa integrations, implementing pre-commit hooks, or configuring CI policy checks for Exa best practices. Trigger with phrases like "exa policy", "exa lint", "exa guardrails", "exa best practices check", "exa eslint".
Install
mkdir -p .claude/skills/exa-policy-guardrails && curl -L -o skill.zip "https://mcp.directory/api/skills/download/4822" && unzip -o skill.zip -d .claude/skills/exa-policy-guardrails && rm skill.zipInstalls to .claude/skills/exa-policy-guardrails
About this skill
Exa Policy Guardrails
Overview
Policy enforcement for Exa neural search integrations. Exa searches the open web, so results may include unreliable sources, competitor content, or inappropriate material. This skill covers domain allowlists/blocklists (via Exa's includeDomains/excludeDomains), content moderation, query sanitization, freshness policies, and per-user budget enforcement.
Prerequisites
exa-jsinstalled and configured- Content policy requirements defined
- Redis for per-user quota tracking (optional)
Instructions
Step 1: Domain Filtering (Built-in Exa Feature)
import Exa from "exa-js";
const exa = new Exa(process.env.EXA_API_KEY);
// Exa supports up to 1200 domains in includeDomains/excludeDomains
const TRUSTED_SOURCES = {
medical: [
"pubmed.ncbi.nlm.nih.gov", "who.int", "cdc.gov",
"nejm.org", "nature.com", "thelancet.com",
],
technical: [
"github.com", "stackoverflow.com", "developer.mozilla.org",
"docs.python.org", "nodejs.org", "arxiv.org",
],
news: [
"reuters.com", "apnews.com", "bbc.com",
"techcrunch.com", "arstechnica.com",
],
};
const BLOCKED_DOMAINS = [
"competitor1.com", "competitor2.io",
"spam-farm.com", "content-mill.net",
];
async function policySearch(
query: string,
category: keyof typeof TRUSTED_SOURCES | "general"
) {
const opts: any = {
type: "auto",
numResults: 10,
text: { maxCharacters: 1000 },
moderation: true, // Exa's built-in content moderation
};
if (category !== "general" && TRUSTED_SOURCES[category]) {
opts.includeDomains = TRUSTED_SOURCES[category];
} else {
opts.excludeDomains = BLOCKED_DOMAINS;
}
return exa.searchAndContents(query, opts);
}
Step 2: Query Content Policy
const BLOCKED_PATTERNS = [
/how to (hack|exploit|attack|ddos)/i,
/(buy|purchase|order)\s+(drugs|weapons|firearms)/i,
/personal.*(address|phone|ssn|social security)/i,
/generate.*(malware|ransomware|virus)/i,
];
function validateQuery(input: string): string {
for (const pattern of BLOCKED_PATTERNS) {
if (pattern.test(input)) {
throw new PolicyViolation("Query blocked by content policy");
}
}
// Sanitize
return input
.replace(/[<>{}]/g, "") // strip HTML/template chars
.replace(/\0/g, "") // remove null bytes
.trim()
.substring(0, 500); // cap query length
}
class PolicyViolation extends Error {
constructor(message: string) {
super(message);
this.name = "PolicyViolation";
}
}
Step 3: Freshness Policy
// Enforce minimum recency for time-sensitive use cases
function applyFreshnessPolicy(
opts: any,
maxAgeDays: number
): any {
const cutoff = new Date(Date.now() - maxAgeDays * 24 * 60 * 60 * 1000);
return {
...opts,
startPublishedDate: cutoff.toISOString(),
};
}
// Usage: only return results from the last 90 days
const results = await exa.searchAndContents("AI regulation updates",
applyFreshnessPolicy(
{ type: "neural", numResults: 10, text: true },
90 // max 90 days old
)
);
Step 4: Per-User Budget Enforcement
class ExaUsagePolicy {
private usage = new Map<string, { count: number; resetAt: number }>();
private limits: Record<string, number>;
constructor(limits: Record<string, number> = {
"free": 10,
"pro": 100,
"enterprise": 1000,
}) {
this.limits = limits;
}
checkQuota(userId: string, tier: string): void {
const limit = this.limits[tier] || this.limits["free"] || 10;
const now = Date.now();
const hourKey = `${userId}:${new Date().toISOString().substring(0, 13)}`;
let entry = this.usage.get(hourKey);
if (!entry || entry.resetAt < now) {
entry = { count: 0, resetAt: now + 3600 * 1000 };
}
if (entry.count >= limit) {
throw new PolicyViolation(
`Hourly search quota exceeded: ${entry.count}/${limit}`
);
}
entry.count++;
this.usage.set(hourKey, entry);
}
}
const usagePolicy = new ExaUsagePolicy();
Step 5: Combined Policy Enforcement
async function enforcedSearch(
userId: string,
userTier: string,
rawQuery: string,
category: keyof typeof TRUSTED_SOURCES | "general" = "general",
maxAgeDays?: number
) {
// 1. Check quota
usagePolicy.checkQuota(userId, userTier);
// 2. Validate and sanitize query
const query = validateQuery(rawQuery);
// 3. Build options with domain policy
let opts: any = {
type: "auto",
numResults: 10,
text: { maxCharacters: 1000 },
moderation: true,
};
if (category !== "general" && TRUSTED_SOURCES[category]) {
opts.includeDomains = TRUSTED_SOURCES[category];
} else {
opts.excludeDomains = BLOCKED_DOMAINS;
}
// 4. Apply freshness policy
if (maxAgeDays) {
opts = applyFreshnessPolicy(opts, maxAgeDays);
}
// 5. Execute search
return exa.searchAndContents(query, opts);
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Competitor content in results | No domain filtering | Apply excludeDomains blocklist |
| Harmful query accepted | No content policy | Validate queries against blocked patterns |
| Stale results displayed | No freshness check | Apply startPublishedDate filter |
| API cost overrun | No usage limits | Implement per-user/tier quotas |
| Blocked policy query | False positive | Review and adjust BLOCKED_PATTERNS |
Resources
Next Steps
For architecture decisions, see exa-architecture-variants. For cost control, see exa-cost-tuning.
More by jeremylongshore
View all skills by jeremylongshore →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversManage and optimize feature flags, experiments, and environments in GrowthBook with AI-driven tools for targeting rules
Discover Modus Design System: comprehensive docs, specs, and guides for React UI library and component implementation in
Break down complex problems with Sequential Thinking, a structured tool and step by step math solver for dynamic, reflec
Build persistent semantic networks for enterprise & engineering data management. Enable data persistence and memory acro
Boost productivity with Task Master: an AI-powered tool for project management and agile development workflows, integrat
Unlock seamless Figma to code: streamline Figma to HTML with Framelink MCP Server for fast, accurate design-to-code work
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.