SSE 與事件

即時串流事件與 DOM 互動協議。

在 Agent 執行期間,伺服器透過 Server-Sent Events (SSE) 串流事件給客戶端。 本頁涵蓋所有事件類型、DOM 互動的 Action Request 協議,以及用於視覺理解的 Page State。

SSE 事件參考

SSEEvent 聯合型別

SSEEvent
type SSEEvent =
  | SSETextEvent
  | SSEToolCallEvent
  | SSEToolResultEvent
  | SSEActionRequestEvent
  | SSEErrorEvent
  | SSEDoneEvent;

事件類型

  • text — 串流文字 token。 欄位:content: string
  • tool_call — Agent 正在呼叫工具。 欄位:name: stringparameters: Record<string, any>
  • tool_result — 工具執行完成。 欄位:name: stringresult: ToolResult
  • action_request — 伺服器請求客戶端執行 DOM 動作。 欄位:correlationIdactionparameters
  • error — 發生錯誤。 欄位:error: stringfatal: boolean
  • done — Agent 執行完成。無欄位。

事件介面

介面
interface SSETextEvent {
  type: 'text';
  content: string;
}

interface SSEToolCallEvent {
  type: 'tool_call';
  name: string;                    // 工具名稱
  parameters: Record<string, any>; // 工具參數
}

interface SSEToolResultEvent {
  type: 'tool_result';
  name: string;                    // 工具名稱
  result: ToolResult;              // { success, result?, error? }
}

interface SSEActionRequestEvent {
  type: 'action_request';
  correlationId: string;           // 用於配對請求/結果的唯一 ID
  action: string;                  // 'click', 'scroll', 'navigate' 等
  parameters: Record<string, any>;
}

interface SSEErrorEvent {
  type: 'error';
  error: string;
  fatal: boolean;                  // 若為 true,Agent 停止執行
}

interface SSEDoneEvent {
  type: 'done';
}

在 onEvent 中處理事件

事件處理
useLensAgent({
  endpoint: '/api/agent/chat',
  onEvent: (event) => {
    switch (event.type) {
      case 'text':
        // 串流文字 — messages 狀態會自動更新
        break;

      case 'tool_call':
        console.log(`呼叫工具: ${event.name}`, event.parameters);
        // 顯示此工具的「載入中」UI
        break;

      case 'tool_result':
        console.log(`工具結果: ${event.name}`, event.result);
        // 更新工具卡片為「已完成」
        break;

      case 'action_request':
        // 由 hook 自動處理(DOM 動作)
        break;

      case 'error':
        console.error(event.error);
        if (event.fatal) {
          // Agent 已停止 — 向用戶顯示錯誤
        }
        break;

      case 'done':
        // Agent 完成 — 如需要可進行清理
        break;
    }
  },
});

Action Request 協議

當 Agent 需要與用戶的頁面互動(點擊按鈕、滾動、導航),會使用 Action Request 協議:

Action Request 流程
伺服器                               客戶端
  │                                    │
  │── action_request (透過 SSE) ──────►│
  │   { correlationId, action, params }│
  │                                    │ 執行 DOM 動作
  │                                    │ 擷取頁面狀態
  │◄── POST /action-result ───────────│
  │   { correlationId, result,         │
  │     pageState }                    │
  │                                    │
  │ (agent 迴圈繼續)                    │

運作方式

  • Agent 決定呼叫 DOM 工具(例如 click
  • 伺服器透過 SSE 發送 action_request 事件,附帶 correlationId
  • 客戶端的 useLensAgent hook 接收事件後: 執行 DOM 動作、擷取最新頁面狀態,並將結果 POST 到 action-result 端點
  • 伺服器接收結果,更新頁面 context,繼續 agent 迴圈

自訂動作處理器

預設情況下,hook 使用內建的 WebUseTool 處理 DOM 動作。你可以覆寫它:

自訂處理器
useLensAgent({
  endpoint: '/api/agent/chat',

  onActionRequest: async (action, params) => {
    // 自訂 DOM 動作處理
    if (action === 'click') {
      const element = document.querySelector(params.selector);
      element?.click();
      return { success: true, result: '已點擊元素' };
    }
    return { success: false, error: `未知動作: ${action}` };
  },
});

頁面狀態與螢幕截圖

頁面狀態讓 Agent 能「看見」當前頁面,啟用視覺理解和 DOM 工具執行。

PageState 介面

PageState
interface PageState {
  url: string;
  title: string;
  markdown: string;                      // 頁面內容轉換為 markdown
  screenshot: string;                    // Base64 data URL
  actionableElements: ActionableElement[];
  timestamp: Date;
}

interface ActionableElement {
  id: string;
  type: 'button' | 'input' | 'link' | 'select' | 'textarea';
  selector: string;
  text?: string;
  placeholder?: string;
  description: string;
}

提供頁面狀態

getPageState
useLensAgent({
  endpoint: '/api/agent/chat',

  getPageState: async () => {
    // 此函式在以下時機被呼叫:
    // 1. 每次 sendMessage 之前(傳送初始頁面 context)
    // 2. 每次 action_request 之後(擷取更新後的狀態)

    return {
      url: window.location.href,
      title: document.title,
      markdown: extractPageMarkdown(),       // 你的實作
      screenshot: await captureScreenshot(),  // 你的實作
      actionableElements: findActionableElements(), // 你的實作
      timestamp: new Date(),
    };
  },
});

隨訊息傳送頁面狀態

sendMessage 搭配 pageState
await sendMessage('你在這個頁面上看到什麼?', {
  pageState: {
    url: window.location.href,
    title: document.title,
    markdown: '...',
    screenshot: 'data:image/png;base64,...',
    actionableElements: [],
    timestamp: new Date(),
  },
  currentUrl: window.location.href,
});

Note

useLensAgent hook 會自動處理 action request 和頁面狀態擷取。 你只需在希望 Agent 擁有視覺上下文時提供 getPageState