1import { Type } from "@sinclair/typebox";
2import type { AgentTool } from "@mariozechner/pi-agent-core";
3import { search } from "kagi-ken";
4import { FetchError, ToolInputError } from "../../util/errors.js";
5
6const SearchSchema = Type.Object({
7 query: Type.String({ description: "Search query" }),
8});
9
10export const createWebSearchTool = (sessionToken: string): AgentTool => ({
11 name: "web_search",
12 label: "Web Search",
13 description: "Search the web using Kagi (session token required).",
14 parameters: SearchSchema as any,
15 execute: async (_toolCallId: string, params: any) => {
16 if (!sessionToken) {
17 throw new ToolInputError("Missing Kagi session token");
18 }
19
20 try {
21 const result = await search(params.query, sessionToken);
22 return {
23 content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
24 details: { query: params.query, resultCount: result?.data?.length ?? 0 },
25 };
26 } catch (error: any) {
27 throw new FetchError(
28 `kagi:search?q=${encodeURIComponent(params.query)}`,
29 error?.message ?? String(error),
30 );
31 }
32 },
33});