コンテンツにスキップ

ツール

ツールは、エージェントが呼び出すことができる関数です。LLMは、ツールの名前と説明に基づいて使用するタイミングを決定します。

import type { AgentTool } from "@schift-io/sdk";
const getWeather: AgentTool = {
name: "get_weather",
description: "Get current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "City name" },
},
required: ["city"],
},
handler: async (args) => {
const city = String(args.city);
const temp = await fetchWeatherAPI(city);
return { success: true, data: { city, temperature: temp } };
},
};
  • /^[a-zA-Z_][a-zA-Z0-9_]*$/ に一致する必要があります
  • snake_case を使用すること(LLMはこれで最も効果的に動作します)
  • エージェント内で一意である必要があります

パラメータはJSONスキーマのサブセットを使用します。zod依存関係は必要ありません。

parameters: {
type: "object",
properties: {
query: { type: "string", description: "Search query" },
limit: { type: "number", description: "Max results" },
category: {
type: "string",
description: "Filter by category",
enum: ["tech", "science", "business"],
},
},
required: ["query"],
}

ツールがパラメータを取らない場合は、parameters フィールドを省略します。ツールは単一の文字列入力を受け取ります。

すべてのハンドラーは ToolResult を返す必要があります:

interface ToolResult {
success: boolean;
data: unknown; // Any JSON-serializable value
error?: string; // Error message if success is false
}

RAG インスタンスをエージェントに渡すと、自動的に rag_search という名前のツールとして登録されます。

const rag = new RAG({ bucket: "docs" }, schift.transport);
const agent = new Agent({ rag, ... });
// エージェントは自動的に "rag_search" ツールを持っています
import { WebSearch } from "@schift-io/sdk";
const webSearch = new WebSearch({}, schift.transport);
const agent = new Agent({
tools: [webSearch.asTool()],
...
});
// エージェントは "web_search" ツールを持っています
const agent = new Agent({
name: "Multi-tool Agent",
instructions: "Use tools to answer questions.",
rag,
tools: [getWeather, searchDatabase, sendEmail],
transport: schift.transport,
});

LLMはすべてのツールの説明を確認し、各質問に対して適切なものを選択します。

maxCallsPerRun を使用して、ツールが単一の実行で呼び出される回数を制限します。これは、プロンプトインジェクションの悪用を防ぐためやコストを制御するために便利です。

const searchTool: AgentTool = {
name: "search_database",
description: "Search the product database",
maxCallsPerRun: 3, // エージェントの run() あたり最大 3 回の呼び出し
parameters: { ... },
handler: async (args) => { ... },
};

制限を超えた場合、エージェントはエラーを受け取り、別のアプローチを使用する必要があります。

内部では、エージェントはツールを管理するために ToolRegistry を使用します。高度なユースケースのために直接使用することもできます:

import { ToolRegistry } from "@schift-io/sdk";
const registry = new ToolRegistry();
registry.register(getWeather);
registry.register(searchDatabase);
// ツールが存在するか確認
registry.has("get_weather"); // true
// OpenAI互換のツール定義を生成
const openaiTools = registry.toOpenAI();
// Anthropic互換のツール定義を生成
const anthropicTools = registry.toAnthropic();
// 許可された名前でツールをフィルタリング
const filtered = registry.filtered(new Set(["get_weather"]));
// 特定のツールを除外
const without = registry.without(new Set(["search_database"]));

ツールにおけるエラーハンドリング

Section titled “ツールにおけるエラーハンドリング”

ハンドラーが例外をスローした場合、エラーはキャッチされ、失敗した ToolResult として返されます。エージェントはエラーを確認し、再試行するか別のアプローチを使用できます。

handler: async (args) => {
const resp = await fetch(`https://api.example.com/${args.id}`);
if (!resp.ok) {
return { success: false, data: null, error: `API returned ${resp.status}` };
}
return { success: true, data: await resp.json() };
}

ツールの実行はタイムアウト (toolTimeoutMs, デフォルト30秒) の影響を受けます。ツールが長時間かかる場合、タイムアウトし、エージェントはエラーを受け取ります。