exa-tool

PreviousNext

A tool for searching and scraping the web using Exa.

Docs
simple-ailib

Preview

Loading preview…
./src/registry/ai/tools/exa-tool.ts
import { type InferUITool, tool } from "ai";
import Exa from "exa-js";
import { z } from "zod";

const exaParamsSchema = z.object({
	query: z.string().describe("The search query or URL to process"),
	mode: z
		.enum(["search", "retrieve", "find-similar"])
		.describe(
			"The mode of operation: 'search' for general queries, 'retrieve' to get content of a specific URL, 'find-similar' to find websites similar to a URL",
		),
	numResults: z
		.number()
		.min(1)
		.max(5)
		.optional()
		.default(2)
		.describe("Number of results to return (default: 2)"),
});

export type ExaParams = z.infer<typeof exaParamsSchema>;

const exaResultSchema = z.union([
	z.object({
		success: z.literal(true),
		data: z.any(),
	}),
	z.object({
		success: z.literal(false),
		error: z.string(),
	}),
]);

export type ExaResult = z.infer<typeof exaResultSchema>;

export const exaTool = tool({
	name: "exa",
	description:
		"Search the web, retrieve content, or find similar pages using Exa. Ideal for AI-powered research.",
	inputSchema: exaParamsSchema,
	outputSchema: exaResultSchema,
	execute: async ({ query, mode, numResults }) => {
		const apiKey = process.env.EXA_API_KEY;

		if (!apiKey) {
			return { success: false, error: "EXA_API_KEY is not set" };
		}

		try {
			const exa = new Exa(apiKey);

			let result: unknown;

			if (mode === "search") {
				// "auto" type uses Exa's decision logic to switch between keyword and neural search
				result = await exa.search(query, {
					type: "auto",
					numResults,
				});
			} else if (mode === "retrieve") {
				// Get content for specific URLs
				result = await exa.getContents([query], {
					text: true,
				});
			} else if (mode === "find-similar") {
				// Find pages similar to a given URL
				result = await exa.findSimilar(query, {
					numResults,
				});
			} else {
				return { success: false, error: "Invalid mode" };
			}

			return { success: true, data: result };
		} catch (error) {
			return {
				success: false,
				error:
					error instanceof Error
						? error.message
						: "Unknown error occurred",
			};
		}
	},
});

export type ExaTool = InferUITool<typeof exaTool>;

Installation

npx shadcn@latest add @simple-ai/exa-tool

Usage

import { ExaTool } from "@/lib/exa-tool"
ExaTool()