工具執行器

AI 代理可以在伺服器端呼叫的自訂函式。

工具是 AI Agent 可以呼叫的自訂函式。它們定義在伺服器端,傳入 createAgentHandler

兩種風格

1. 簡單函式

簡單風格
toolExecutors: {
  weather: async (params, context) => {
    const res = await fetch(`https://api.weather.com?city=${params.city}`);
    return { success: true, result: await res.json() };
  },
}

2. 完整設定(推薦)

包含 metadata 用於 prompt 生成 — SDK 使用 descriptionwhenToUseschema 來告訴 LLM 何時以及如何呼叫工具。

完整設定風格
toolExecutors: {
  product_search: {
    description: '搜尋商品資料庫',
    whenToUse: '當用戶想要尋找商品、比較商品或詢問特定商品時',
    schema: {
      query: { type: 'string', required: true, description: '搜尋關鍵字(1-3 個詞)' },
      topK: { type: 'number', required: false, default: 10, description: '回傳數量' },
    },
    output: '包含 title、price、imageUrl、description 的商品陣列',

    execute: async (params, context) => {
      // context.userId — 已驗證的用戶
      // context.sessionId — 當前 session
      const res = await fetch('https://your-api.com/products/search', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...params, userId: context?.userId }),
      });
      return await res.json();
    },
  },
}

型別定義

型別
/** 簡單函式風格 */
type ToolExecutorFunction = (
  params: any,
  context?: SessionContext
) => Promise<ToolResult>;

/** 完整設定風格 */
interface ToolExecutorConfig {
  execute: ToolExecutorFunction;
  description?: string;
  whenToUse?: string;
  schema?: Record<string, {
    type: string;
    required?: boolean;
    default?: any;
    description?: string;
  }>;
  output?: string;
}

/** 傳入每個執行器的 context */
interface SessionContext {
  sessionId: string;
  userId: string;
  currentUrl: string;
  currentPage: PageState | null;
}

/** 工具回傳值 */
interface ToolResult {
  success: boolean;
  result?: any;
  error?: string;
}

工具優先順序

SDK 按以下順序解析工具:

優先順序
1. 手動 toolExecutors(傳入 createAgentHandler)  ← 最高優先
2. CUSTOMER 模式(在 Lens OS 後台設定)
3. PLATFORM 模式(SDK 內建工具)                   ← 最低優先
  • 手動 toolExecutors — 在你的專案中以程式碼定義(最高優先)
  • CUSTOMER 模式 — 透過 Lens OS 儀表板設定的外部端點
  • PLATFORM 模式 — SDK 內建實作(最低優先)

組織工具執行器

當專案有多個工具時,建議抽出到獨立檔案:

src/lib/tools.ts
import type { ToolExecutorConfig, SessionContext } from '@lens-os/sdk';

export function buildToolExecutors(): Record<string, ToolExecutorConfig> {
  return {
    product_search: {
      description: '搜尋商品',
      schema: { query: { type: 'string', required: true } },
      execute: async (params) => {
        const res = await fetch('/api/products/search', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(params),
        });
        return await res.json();
      },
    },

    user_orders: {
      description: '查詢用戶訂單',
      schema: {
        action: { type: 'string', required: true, description: '"get" | "update"' },
        orderId: { type: 'string', required: false },
      },
      execute: async (params, context?: SessionContext) => {
        const res = await fetch('/api/orders', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ ...params, userId: context?.userId }),
        });
        return await res.json();
      },
    },
  };
}
src/app/api/agent/chat/route.ts
import { createAgentHandler } from '@lens-os/sdk/server';
import { buildToolExecutors } from '@/lib/tools';

export const handler = createAgentHandler({
  apiKey: process.env.LENS_API_KEY!,
  openaiKey: process.env.OPENAI_API_KEY!,
  toolExecutors: buildToolExecutors(),
});

export const { POST } = handler;

Tip

你提供的 metadata 越多(descriptionwhenToUseschemaoutput), LLM 就越知道何時以及如何使用工具。