1import type Anthropic from "@anthropic-ai/sdk";
2
3type Handler = (input: unknown) => Promise<unknown>;
4
5export async function runCalls(
6 reply: Anthropic.Message,
7 handlers: Record<string, Handler>,
8): Promise<Anthropic.MessageParam> {
9 const calls = reply.content.filter((block) => block.type === "tool_use");
10
11 // Independent lookups can run at the same time.
12 const results = await Promise.all(
13 calls.map(async (call): Promise<Anthropic.ToolResultBlockParam> => {
14 const handler = handlers[call.name];
15 try {
16 if (!handler) throw new Error(`Unknown tool "${call.name}".`);
17 const output = await handler(call.input);
18 return { type: "tool_result", tool_use_id: call.id, content: JSON.stringify(output) };
19 } catch (error) {
20 // A failed call still gets an answer, marked as an error.
21 const message = error instanceof Error ? error.message : String(error);
22 return { type: "tool_result", tool_use_id: call.id, content: message, is_error: true };
23 }
24 }),
25 );
26
27 // Every result in ONE user message.
28 return { role: "user", content: results };
29}