自訂工具
進階工具設計模式和最佳實踐。
學習為 Lens OS Agent 設計強健且高效的工具執行器的進階模式。
工具設計模式
1. 搜尋 + 顯示模式
搜尋資料,然後產生顯示頁面:
搜尋和顯示模式
// Tool 1: Search
product_search: {
description: "Search products",
// ...
execute: async (params) => {
const results = await searchProducts(params.query);
return {
success: true,
result: { results, message: `Found ${results.length} products` },
};
},
},
// Tool 2: Generate page
generate_page: {
description: "Generate page from search results",
whenToUse: "IMPORTANT: Must complete product_search first before calling this",
schema: {
title: { type: "string", required: true },
productIds: { type: "array", required: true },
},
execute: async (params) => {
const pageUrl = await generatePage(params);
return {
success: true,
result: { pageUrl, message: `Page generated: ${pageUrl}` },
};
},
},2. 讀取 + 寫入模式
查詢然後更新模式:
讀取和寫入模式
user_orders: {
description: "Query or update user orders",
schema: {
action: {
type: "string",
required: true,
description: '"get" to query | "update" to modify | "cancel" to cancel',
},
orderId: { type: "string", required: false },
updates: { type: "object", required: false },
},
execute: async (params, context) => {
switch (params.action) {
case "get":
return await getOrders(context?.userId);
case "update":
return await updateOrder(params.orderId, params.updates);
case "cancel":
return await cancelOrder(params.orderId);
}
},
},錯誤處理
優雅降級
後援處理
execute: async (params) => {
try {
const result = await primaryMethod(params);
return { success: true, result };
} catch (primaryError) {
console.error("Primary method failed:", primaryError);
try {
// Fallback
const fallback = await fallbackMethod(params);
return {
success: true,
result: {
...fallback,
message: "使用後援方法取得",
},
};
} catch (fallbackError) {
return {
success: false,
error: "服務暫時無法使用,請稍後再試",
};
}
}
},使用者友善的錯誤訊息
驗證和錯誤
execute: async (params) => {
if (!params.query?.trim()) {
return { success: false, error: "請輸入搜尋關鍵字" };
}
if (params.query.length > 100) {
return { success: false, error: "關鍵字過長,請縮短" };
}
// ...
},Context 使用
存取使用者資訊
使用 Context
execute: async (params, context) => {
const userId = context?.userId;
if (!userId) {
return { success: false, error: "請先登入" };
}
// Use userId to query user-specific data
const orders = await getOrdersByUser(userId);
return { success: true, result: orders };
},效能提示
快取
實作快取
const cache = new Map<string, { data: any; timestamp: number }>();
const CACHE_TTL = 5 * 60 * 1000; // 5 分鐘
execute: async (params) => {
const cacheKey = JSON.stringify(params);
const cached = cache.get(cacheKey);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return { success: true, result: cached.data };
}
const result = await expensiveOperation(params);
cache.set(cacheKey, { data: result, timestamp: Date.now() });
return { success: true, result };
},平行執行
平行查詢
execute: async (params) => {
// Execute multiple queries in parallel
const [products, categories, reviews] = await Promise.all([
searchProducts(params.query),
getCategories(),
getTopReviews(params.query),
]);
return {
success: true,
result: { products, categories, reviews },
};
},測試工具
本地測試
test-tools.ts
// 直接引入你定義的 tools 物件
const tools = { /* 你的工具定義 */ };
async function test() {
// Test product_search
const result = await tools.product_search.execute(
{ query: "TypeScript", topK: 5 },
{ userId: "test-user", sessionId: "test-session" }
);
console.log("Result:", JSON.stringify(result, null, 2));
}
test();執行測試
bun test-tools.tsTip
在部署前務必在本地測試你的工具,以確保它們能夠優雅地處理邊界情況和錯誤。