useAgent

React hook for accessing AG-UI agent instances in React Native

Overview

useAgent is a React hook that returns an AG-UI AbstractAgent instance. The hook subscribes to agent state changes and triggers re-renders when the agent's state, messages, or execution status changes.

Re-exported from @copilotkit/react-core/v2. It is identical to the React (V2) useAgent; only the import path differs.

By default it binds to a shared agent from the CopilotKit registry. It can also register a private proxied agent for one thread, which is useful for custom thread switchers and multi-conversation UIs.

Throws an error if no agent is configured with the specified agentId, or if only part of the thread-scoped option set is provided.

Signature

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

function useAgent(options?: UseAgentProps): {
  agent: AbstractAgent;
  isReady: boolean;
};

For fully headless UI that does not import the built-in chat rendering stack, import the hook from the headless entry:

import { useAgent } from "@copilotkit/react-native/headless";

Parameters

Prop

Type

There are two valid option shapes:

  • useAgent() or useAgent({ agentId }): bind to a shared agent. The thread comes from chat configuration or the agent itself.
  • useAgent({ agentId, runtimeAgentId, threadId }): register a private local agent under agentId, route it to the runtime agent named by runtimeAgentId, and pin it to threadId.

Return Value

Prop

Type

Usage

Basic Usage

import { Text, View } from "react-native";
import { useAgent } from "@copilotkit/react-native";

function AgentStatus() {
  const { agent } = useAgent();

  return (
    <View>
      <Text>Agent: {agent.agentId}</Text>
      <Text>Messages: {agent.messages.length}</Text>
      <Text>Running: {agent.isRunning ? "Yes" : "No"}</Text>
    </View>
  );
}

Accessing and Updating State

import { Text, TouchableOpacity, View } from "react-native";
import { useAgent } from "@copilotkit/react-native";

function StateController() {
  const { agent } = useAgent();

  return (
    <View>
      <Text>{JSON.stringify(agent.state, null, 2)}</Text>
      <TouchableOpacity
        onPress={() => agent.setState({ ...agent.state, count: 1 })}
      >
        <Text>Update State</Text>
      </TouchableOpacity>
    </View>
  );
}

Event Subscription

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

function EventListener() {
  const { agent } = useAgent();

  useEffect(() => {
    const { unsubscribe } = agent.subscribe({
      onRunStartedEvent: () => console.log("Started"),
      onRunFinalized: () => console.log("Finished"),
    });

    return unsubscribe;
  }, []);

  return null;
}

Multiple Agents

import { Text, View } from "react-native";
import { useAgent } from "@copilotkit/react-native";

function MultiAgentView() {
  const { agent: primary } = useAgent({ agentId: "primary" });
  const { agent: support } = useAgent({ agentId: "support" });

  return (
    <View>
      <Text>Primary: {primary.messages.length} messages</Text>
      <Text>Support: {support.messages.length} messages</Text>
    </View>
  );
}

Thread-scoped Agent

Use the thread-scoped form when one runtime agent needs multiple independent frontend instances, for example one per open conversation. The local agentId must be unique in the current provider.

import { Text } from "react-native";
import { useAgent } from "@copilotkit/react-native";

function ThreadPreview({ threadId }: { threadId: string }) {
  const { agent, isReady } = useAgent({
    agentId: `preview-${threadId}`,
    runtimeAgentId: "support",
    threadId,
    throttleMs: 100,
  });

  if (!isReady) return <Text>Loading...</Text>;

  return <Text>{agent.messages.length} messages</Text>;
}

Optimizing Re-renders

import { Text } from "react-native";
import { useAgent, UseAgentUpdate } from "@copilotkit/react-native";

// Only re-render when messages change
function MessageCount() {
  const { agent } = useAgent({
    updates: [UseAgentUpdate.OnMessagesChanged],
  });

  return <Text>Messages: {agent.messages.length}</Text>;
}

Behavior

  • Automatic Re-renders: Component re-renders when agent state, messages, or execution status changes (configurable via updates parameter)
  • Optional Throttling: Message and state update re-renders can be throttled with throttleMs or the provider's defaultThrottleMs.
  • Readiness: While the runtime is connecting, agent is a fully-constructed provisional stand-in and isReady is false; once the runtime syncs, agent swaps to the real instance and isReady becomes true. Guard on isReady for work that must target the real agent (e.g. one-time subscriptions)
  • Error Handling: Throws error if no agent exists with specified agentId
  • Thread Scoping: threadId and runtimeAgentId must be passed together with an explicit local agentId; partial combinations throw at runtime and are rejected by the TypeScript type.
  • State Synchronization: State updates via setState() are immediately available to both app and agent
  • Event Subscriptions: Subscribe/unsubscribe pattern for lifecycle and custom events

Related