useAgent

Vue 3 composable for accessing AG-UI agent instances

Open your coding agent in your project's folder, or in an empty folder for a new app.This runs in a coding agent on your computer.

Overview

useAgent is a Vue 3 composable that returns a reactive reference to an AG-UI AbstractAgent instance. The composable subscribes to agent changes and triggers reactive updates when the agent's state, messages, or execution status changes.

The composable returns { agent }, where agent is typed as a Vue shallowRef<AbstractAgent | null> for API compatibility. During setup, it synchronously assigns an existing or provisional agent; if neither can be resolved, it throws instead of returning with agent.value set to null. Access the underlying instance with agent.value in <script setup>, or rely on auto-unwrapping in <template>. Optional chaining remains useful when consuming the nullable public type.

Throws an error if no agent can be resolved for the given agentId after the runtime has synced (for example, when the id does not match any agent reported by your runtime /info or registered via agents__unsafe_dev_only).

Signature

import { useAgent } from "@copilotkit/vue/v2";
import type { ShallowRef } from "vue";
import type { AbstractAgent } from "@ag-ui/client";

function useAgent(props?: UseAgentProps): {
  agent: ShallowRef<AbstractAgent | null>;
};

Parameters

Reactive props accept MaybeRefOrGetter, so you can pass a plain value, a ref, or a getter function. The composable responds to each input according to the behavior described below.

Prop

Type

Return Value

Prop

Type

Usage

Basic Usage

<script setup lang="ts">
import { useAgent } from "@copilotkit/vue/v2";

const { agent } = useAgent();
</script>

<template>
  <div v-if="agent">
    <div>Agent: {{ agent.agentId }}</div>
    <div>Messages: {{ agent.messages.length }}</div>
    <div>Running: {{ agent.isRunning ? "Yes" : "No" }}</div>
  </div>
</template>

Accessing and Updating State

<script setup lang="ts">
import { useAgent } from "@copilotkit/vue/v2";

const { agent } = useAgent();

function updateState() {
  if (!agent.value) return;
  agent.value.setState({ ...agent.value.state, count: 1 });
}
</script>

<template>
  <div>
    <pre>{{ JSON.stringify(agent?.state, null, 2) }}</pre>
    <button @click="updateState">Update State</button>
  </div>
</template>

Event Subscription

<script setup lang="ts">
import { watchEffect } from "vue";
import { useAgent } from "@copilotkit/vue/v2";

const { agent } = useAgent();

watchEffect((onCleanup) => {
  if (!agent.value) return;
  const { unsubscribe } = agent.value.subscribe({
    onRunStartedEvent: () => console.log("Started"),
    onRunFinalized: () => console.log("Finished"),
  });

  onCleanup(unsubscribe);
});
</script>

<template>
  <div />
</template>

Multiple Agents

<script setup lang="ts">
import { useAgent } from "@copilotkit/vue/v2";

const { agent: primary } = useAgent({ agentId: "primary" });
const { agent: support } = useAgent({ agentId: "support" });
</script>

<template>
  <div>
    <div>Primary: {{ primary?.messages?.length ?? 0 }} messages</div>
    <div>Support: {{ support?.messages?.length ?? 0 }} messages</div>
  </div>
</template>

Thread-scoped Agent

<script setup lang="ts">
import { ref } from "vue";
import { useAgent } from "@copilotkit/vue/v2";

const threadId = ref("thread-1");

// Registers a local proxy routed to the runtime agent and pins it to this thread.
const { agent } = useAgent({
  agentId: "thread-1",
  runtimeAgentId: "default",
  threadId,
});
</script>

<template>
  <div v-if="agent">Thread: {{ agent.threadId }} ({{ agent.messages.length }} messages)</div>
</template>

Optimizing Reactive Updates

<script setup lang="ts">
import { useAgent, UseAgentUpdate } from "@copilotkit/vue/v2";

// Only update when messages change.
const { agent } = useAgent({
  updates: [UseAgentUpdate.OnMessagesChanged],
});
</script>

<template>
  <div>Messages: {{ agent?.messages?.length ?? 0 }}</div>
</template>

Throttling High-Frequency Updates

import { useAgent } from "@copilotkit/vue/v2";

// Coalesce streaming message and state updates into at most one update
// per 100ms. Run lifecycle callbacks still fire immediately.
const { agent } = useAgent({ throttleMs: 100 });

Behavior

  • Reactive updates: The agent ref triggers reactivity when state, messages, or execution status changes (configurable via the updates parameter).
  • Reactive inputs: agentId and runtimeAgentId drive private-proxy registration; agentId plus core registry and connection changes drive resolution. threadId pins or repins the current agent. updates, throttleMs, and the provider's defaultThrottleMs drive subscription behavior.
  • Agent binding: The shared-agent form resolves the explicit agentId, then the chat configuration's agentId, then DEFAULT_AGENT_ID, and may return an agent discovered by the runtime or registered by the provider. The thread-scoped form registers a private proxy under the local agentId, routes it to runtimeAgentId, and pins threadId to that proxy. All three thread-scoped properties are required together; changing threadId repins the existing proxy.
  • Throttling: Message and state updates can be throttled via throttleMs, resolved as throttleMs ?? provider defaultThrottleMs ?? 0. Run lifecycle callbacks always fire immediately.
  • Error handling: Throws an error if no agent can be resolved for the specified agentId after the runtime has synced.
  • State synchronization: State updates via setState() are immediately available to both app and agent.

Related