Skip to main content

Overview

The useAgent hook provides access to a CopilotKit agent instance, allowing you to interact with agents, subscribe to their state changes, and manage agent runs.

Usage

import { useAgent } from "@copilotkit/react";

function AgentComponent() {
  const { agent } = useAgent();
  
  // Use agent instance
  const messages = agent.messages;
  const isRunning = agent.isRunning;
  
  return <div>Agent status: {isRunning ? "Running" : "Idle"}</div>;
}

Type Signature

function useAgent(props?: UseAgentProps): { agent: AbstractAgent }

Parameters

agentId
string
default:"'default'"
The ID of the agent to access. If not specified, uses the default agent.
const { agent } = useAgent({ agentId: "research-agent" });
updates
UseAgentUpdate[]
Array of update types to subscribe to. When specified, the component re-renders on these events.Available update types:
  • UseAgentUpdate.OnMessagesChanged - Re-render when messages change
  • UseAgentUpdate.OnStateChanged - Re-render when agent state changes
  • UseAgentUpdate.OnRunStatusChanged - Re-render when run status changes
If not specified, subscribes to all updates by default.
const { agent } = useAgent({ 
  updates: [
    UseAgentUpdate.OnMessagesChanged,
    UseAgentUpdate.OnRunStatusChanged
  ] 
});

Return Value

agent
AbstractAgent
The agent instance with the following properties and methods:

Update Types

enum UseAgentUpdate {
  OnMessagesChanged = "OnMessagesChanged",
  OnStateChanged = "OnStateChanged", 
  OnRunStatusChanged = "OnRunStatusChanged",
}

Examples

Basic Usage with Default Agent

import { useAgent } from "@copilotkit/react";

function ChatInterface() {
  const { agent } = useAgent();
  
  const handleSend = async (message: string) => {
    await agent.run({
      messages: [{ role: "user", content: message }]
    });
  };
  
  return (
    <div>
      {agent.messages.map((msg, idx) => (
        <div key={idx}>
          <strong>{msg.role}:</strong> {msg.content}
        </div>
      ))}
      <button onClick={() => handleSend("Hello!")}>
        Send Message
      </button>
    </div>
  );
}

Using a Specific Agent

import { useAgent } from "@copilotkit/react";

function ResearchPanel() {
  const { agent } = useAgent({ agentId: "research-agent" });
  
  return (
    <div>
      <h2>Research Agent</h2>
      <p>Status: {agent.isRunning ? "Researching..." : "Ready"}</p>
      <p>Messages: {agent.messages.length}</p>
    </div>
  );
}

Optimized Updates

Only re-render on specific events to optimize performance:
import { useAgent, UseAgentUpdate } from "@copilotkit/react";

function MessageList() {
  // Only re-render when messages change, not on state or run status changes
  const { agent } = useAgent({ 
    updates: [UseAgentUpdate.OnMessagesChanged] 
  });
  
  return (
    <ul>
      {agent.messages.map((msg, idx) => (
        <li key={idx}>{msg.content}</li>
      ))}
    </ul>
  );
}

Multi-Agent Application

import { useAgent } from "@copilotkit/react";

function MultiAgentDashboard() {
  const { agent: researchAgent } = useAgent({ agentId: "research" });
  const { agent: writingAgent } = useAgent({ agentId: "writing" });
  
  return (
    <div>
      <div>
        <h3>Research Agent</h3>
        <p>Status: {researchAgent.isRunning ? "Active" : "Idle"}</p>
      </div>
      <div>
        <h3>Writing Agent</h3>
        <p>Status: {writingAgent.isRunning ? "Active" : "Idle"}</p>
      </div>
    </div>
  );
}

Connecting to an Existing Thread

import { useAgent } from "@copilotkit/react";
import { useEffect } from "react";

function ThreadViewer({ threadId }: { threadId: string }) {
  const { agent } = useAgent();
  
  useEffect(() => {
    // Connect to existing conversation thread
    agent.connect(threadId);
  }, [agent, threadId]);
  
  return (
    <div>
      {agent.messages.map((msg, idx) => (
        <div key={idx}>{msg.content}</div>
      ))}
    </div>
  );
}

Subscribing to Agent Events

import { useAgent } from "@copilotkit/react";
import { useEffect, useState } from "react";

function AgentMonitor() {
  const { agent } = useAgent();
  const [eventLog, setEventLog] = useState<string[]>([]);
  
  useEffect(() => {
    const subscription = agent.subscribe({
      onMessagesChanged: () => {
        setEventLog(prev => [...prev, "Messages updated"]);
      },
      onRunInitialized: () => {
        setEventLog(prev => [...prev, "Run started"]);
      },
      onRunFinalized: () => {
        setEventLog(prev => [...prev, "Run completed"]);
      },
      onRunFailed: (error) => {
        setEventLog(prev => [...prev, `Run failed: ${error.message}`]);
      },
    });
    
    return () => subscription.unsubscribe();
  }, [agent]);
  
  return (
    <div>
      <h3>Event Log</h3>
      <ul>
        {eventLog.map((event, idx) => (
          <li key={idx}>{event}</li>
        ))}
      </ul>
    </div>
  );
}

Agent Lifecycle

The useAgent hook handles different agent lifecycle states:
  1. Disconnected: Runtime is configured but not yet connected
  2. Connecting: Establishing connection to runtime
  3. Connected: Agent is available and ready
  4. Error: Connection or agent initialization failed
The hook returns a provisional agent during connection states, ensuring your components can render without errors. Errors are emitted through the onError handler in CopilotKitProvider.

Notes

The hook maintains a stable agent reference during runtime connection states to prevent unnecessary re-renders and reconnection attempts.
If the specified agent is not found after runtime synchronization and no runtime is configured, the hook will throw an error. Ensure your agent is registered via selfManagedAgents or available from your runtime.