useLensAgent Hook

Core React Hook for managing Agent conversation state

Overview

useLensAgent is the core React Hook provided by Lens OS SDK, offering complete Agent interaction functionality: sending messages, receiving streamed responses, managing conversation history, and more.

Basic Usage

Basic Example
import { useLensAgent } from "@lens-os/sdk/react";

function Chat() {
  const {
    messages,
    isLoading,
    sendMessage,
    newSession,
  } = useLensAgent({
    endpoint: "/api/lens/agent/chat",
    userId: "user-123",
  });

  return (
    <div>
      {messages.map((msg, i) => (
        <div key={i}>{msg.content}</div>
      ))}

      <button onClick={() => sendMessage("Hello!")}>
        Send
      </button>
    </div>
  );
}

API Reference

Options

Options
interface UseLensAgentOptions {
  // Required
  endpoint: string;     // Chat API path

  // Optional
  userId?: string;      // User identifier (can be injected server-side)
  onEvent?: (event: SSEEvent) => void;  // Event callback
}
ParameterTypeRequiredDescription
endpointstringYesChat API path, e.g. "/api/lens/agent/chat"
userIdstringNoUser identifier (can be injected server-side)
onEventfunctionNoSSE event callback function

Return Value

Return
interface UseLensAgentReturn {
  // State
  messages: Message[];        // Conversation messages
  isLoading: boolean;         // Is executing
  isInitialized: boolean;     // SDK initialized
  sessionId: string;          // Current Session ID
  error: Error | null;        // Last error

  // Methods
  sendMessage: (message: string, context?: MessageContext) => Promise<void>;
  abort: () => void;          // Cancel current execution
  newSession: () => void;     // Start new conversation
  loadSession: (sessionId: string, messages: Message[]) => void;
}

State

messages

Conversation message array, each message formatted as:

Message
interface Message {
  role: "user" | "assistant" | "system" | "tool";
  content: string | MessageContent[];
  timestamp?: Date;
}

isLoading

true when Agent is processing a message, useful for:

  • Showing loading indicator
  • Disabling send button
  • Switching to stop button

sessionId

Unique identifier for the current conversation. A new ID is generated each time newSession() is called.

Methods

sendMessage

Send a message to the Agent:

sendMessage
// Basic usage
await sendMessage("Find TypeScript books for me");

// With context (for page capture)
await sendMessage("Click the search button", {
  currentUrl: window.location.href,
  pageState: {
    url: "...",
    title: "...",
    markdown: "...",
    screenshot: "...",
    actionableElements: [...],
  },
});

abort

Cancel the current request:

abort
<button onClick={isLoading ? abort : handleSend}>
  {isLoading ? "Stop" : "Send"}
</button>

newSession

Start a new conversation, clearing current messages:

newSession
<button onClick={newSession}>New Chat</button>

loadSession

Load a history conversation:

loadSession
const handleLoad = async (targetSessionId: string) => {
  const res = await fetch(`/api/lens/agent/sessions/${targetSessionId}`);
  const data = await res.json();

  if (data.success) {
    loadSession(targetSessionId, data.messages);
  }
};

Event Handling

Use onEvent callback to handle SSE events:

onEvent
const { messages } = useLensAgent({
  endpoint: "/api/lens/agent/chat",
  userId: "user-123",

  onEvent: (event) => {
    switch (event.type) {
      case "tool_call":
        console.log("Tool started:", event.name);
        // Show Tool Card
        break;

      case "tool_result":
        console.log("Tool completed:", event.name, event.result);
        // Update Tool Card
        break;

      case "text":
        console.log("Text:", event.content);
        break;

      case "error":
        console.error("Error:", event.error);
        break;

      case "done":
        console.log("Completed");
        break;
    }
  },
});

Event type descriptions:

  • tool_call: Agent starts executing a tool, use to show Tool Card
  • tool_result: Tool execution complete, use to update Tool Card state
  • text: Text content update
  • error: Error occurred
  • done: Conversation round complete

Full Example

Here is a complete chat component example with all features:

Chat.tsx
"use client";

import { useState, useRef, useEffect } from "react";
import { useLensAgent } from "@lens-os/sdk/react";

export function Chat({ userId }: { userId: string }) {
  const [input, setInput] = useState("");
  const messagesEndRef = useRef<HTMLDivElement>(null);

  const {
    messages,
    isLoading,
    error,
    sendMessage,
    abort,
    newSession,
  } = useLensAgent({
    endpoint: "/api/lens/agent/chat",
    userId,
    onEvent: (event) => {
      if (event.type === "tool_call") {
        console.log("Tool:", event.name);
      }
    },
  });

  // Auto scroll
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const handleSend = async () => {
    if (!input.trim() || isLoading) return;
    const message = input;
    setInput("");
    await sendMessage(message);
  };

  return (
    <div className="flex flex-col h-full">
      {/* Messages */}
      <div className="flex-1 overflow-auto p-4 space-y-4">
        {messages.map((msg, i) => (
          <div
            key={i}
            className={msg.role === "user" ? "text-right" : "text-left"}
          >
            <span className={`inline-block p-3 rounded-lg ${
              msg.role === "user" ? "bg-blue-500 text-white" : "bg-gray-100"
            }`}>
              {typeof msg.content === "string" ? msg.content : "..."}
            </span>
          </div>
        ))}

        {isLoading && <div className="text-gray-500">Thinking...</div>}
        {error && <div className="text-red-500">Error: {error.message}</div>}

        <div ref={messagesEndRef} />
      </div>

      {/* Input */}
      <div className="border-t p-4 flex gap-2">
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && handleSend()}
          placeholder="Type a message..."
          className="flex-1 border rounded px-3 py-2"
        />
        <button
          onClick={isLoading ? abort : handleSend}
          className="bg-blue-500 text-white px-4 py-2 rounded"
        >
          {isLoading ? "Stop" : "Send"}
        </button>
        <button
          onClick={newSession}
          className="border px-4 py-2 rounded"
        >
          New Chat
        </button>
      </div>
    </div>
  );
}

Tip

This example shows basic chat functionality. For a more complete component (with Tool Cards, Rules menu), see the "Chat Component" docs.

Next Steps