最佳實踐
指南、疑難排解與環境設定。
最佳實踐
1. 保持 API 金鑰在伺服器端
始終在伺服器端使用 createAgentHandler。絕對不要將 LENS_API_KEY 或 OPENAI_API_KEY 暴露給客戶端。
.env
# 不要使用 NEXT_PUBLIC_ 前綴
LENS_API_KEY=lens-xxx
OPENAI_API_KEY=sk-xxx2. 提供豐富的工具 Metadata
你提供的 metadata 越多,LLM 就越知道何時以及如何使用工具。
好的做法 vs 不好的做法
// 好的做法
{
description: '依關鍵字、分類或作者搜尋商品',
whenToUse: '當用戶想尋找、比較或瀏覽商品時',
schema: {
query: { type: 'string', required: true, description: '搜尋關鍵字(1-3 個詞)' },
topK: { type: 'number', required: false, default: 10 },
},
output: '包含 title、price、imageUrl 的商品陣列',
execute: async (params) => { ... },
}
// 不好的做法 — LLM 不知道何時使用這個工具
{
execute: async (params) => { ... },
}3. 始終回傳結構化的 ToolResult
ToolResult
// 成功
{ success: true, result: { message: '找到 5 個商品', products: [...] } }
// 錯誤
{ success: false, error: '資料庫連線失敗' }4. 優雅地處理錯誤
錯誤處理
execute: async (params) => {
try {
const res = await fetch(url, { ... });
if (!res.ok) {
const err = await res.json();
return { success: false, error: err.error || '請求失敗' };
}
return await res.json();
} catch (err) {
return {
success: false,
error: err instanceof Error ? err.message : '未知錯誤',
};
}
}5. 使用 context.userId 處理用戶相關工具
用戶 context
user_orders: {
execute: async (params, context) => {
// context.userId 由 SDK 自動填入
const res = await fetch('/api/orders', {
method: 'POST',
body: JSON.stringify({ ...params, userId: context?.userId }),
});
return await res.json();
},
}環境變數
.env
# 必填(僅限伺服器端 — 絕對不要使用 NEXT_PUBLIC_ 前綴)
LENS_API_KEY=lens-xxx # Lens OS API 金鑰
OPENAI_API_KEY=sk-xxx # OpenAI API 金鑰
# 可選
OPENAI_MODEL=gpt-4o # LLM 模型(預設:gpt-4o)
NEXT_PUBLIC_BASE_URL=http://localhost:3000 # 內部 API 呼叫的 Base URL疑難排解
Module not found: @lens-os/sdk/server
確認你的 @lens-os/sdk 版本包含 ./server 匯出。 檢查 node_modules/@lens-os/sdk/package.json:
package.json exports
{
"exports": {
".": { "import": "./dist/index.mjs", "types": "./dist/index.d.mts" },
"./react": { "import": "./dist/react/index.mjs", "types": "./dist/react/index.d.mts" },
"./server": { "import": "./dist/server/index.mjs", "types": "./dist/server/index.d.mts" }
}
}SSE 連線中斷
如果 SSE 串流提前斷線,確認你的伺服器/代理沒有進行緩衝:
SSE Headers
// createAgentHandler 已自動設定這些標頭:
{
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no', // 用於 nginx
}工具沒有被呼叫
- 確認
ToolExecutorConfig中有提供description和whenToUse - 確認工具已傳入
createAgentHandler({ toolExecutors: ... }) - 啟用事件日誌:
除錯日誌
onEvent: (event) => {
console.log('[SSE]', event.type, event);
}Action Request 逾時
如果 DOM 動作逾時(預設 30 秒),可增加逾時時間:
增加逾時
createAgentHandler({
...config,
actionTimeout: 60000, // 60 秒
});OpenAI 錯誤:Image URLs only allowed for role 'user'
如果使用包含螢幕截圖的頁面狀態,請確認你的 SDK 版本 >= 0.1.3, 該版本修正了 prompt builder,將包含圖片的頁面狀態訊息使用 role: "user"。
Warning
絕對不要將 API 金鑰提交到版本控制。使用
.env 檔案並將它們加入 .gitignore。