Vercel AI SDKのツール分離設計パターン(静的・動的ツール)
TypeScript
Vercel AI SDK
認証が必要なツールと不要なツールを分離し、実行場所(クライアント/サーバー)を制御する設計
ツール分離の基本構造
import { tool } from "ai";
import { z } from "zod";
// 静的ツール(認証不要、クライアント実行)
export const staticTools = {
getAccessibilityTree: tool({
description: "画面上の要素一覧を取得",
inputSchema: z.object({}),
execute: async () => {
// クライアント側で実行される
// サーバーには送られない
}
}),
showNotification: tool({
description: "通知を表示",
inputSchema: z.object({
message: z.string()
}),
execute: async ({ message }) => {
// クライアント側のアクション
}
}),
};
// 動的ツール生成関数(認証付き、サーバー実行)
export const createAuthenticatedTool = (authToken: string) =>
tool({
description: "認証が必要なAPI呼び出し",
inputSchema: z.object({
query: z.string()
}),
execute: async ({ query }) => {
const response = await fetch("/api/data", {
headers: { Authorization: `Bearer ${authToken}` }
});
return response.json();
}
});
// すべてのツールを統合
export const createTools = (authToken: string) => ({
...staticTools,
authenticatedTool: createAuthenticatedTool(authToken),
});
クライアント側でのツール実行制御
onToolCall: async ({ toolCall }) => { // 動的ツールはスキップ(サーバー側で実行済み) if (toolCall.dynamic) { return; } // 静的ツールのみクライアントで処理 if (toolCall.toolName === "getAccessibilityTree") { const tree = extractAccessibilityTree(); addToolResult({ toolCallId: toolCall.toolCallId, tool: "getAccessibilityTree", output: tree, }); } }
設計の利点
- 認証トークンの管理が明確
- クライアント/サーバーの責務分離
- セキュリティ向上(センシティブな操作はサーバーのみ)
- ツールの再利用性向上