showcase/shell-docs/src/content/reference/vue/hooks/useAgent.mdx
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 a Vue shallowRef<AbstractAgent | null> — it is null until an agent resolves. (If the agent cannot be resolved for the given agentId after the runtime syncs, the composable throws rather than leaving agent as null.) Access the underlying instance with agent.value in <script setup>, or rely on auto-unwrapping in <template>, and guard with agent?. / agent.value?. for the unresolved case.
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>;
};
All reactive inputs accept MaybeRefOrGetter, so you can pass a plain value, a ref, or a getter function and the composable will re-resolve when it changes.
Pass an empty array `[]` to prevent automatic reactive updates.
Resolved as `throttleMs ?? provider defaultThrottleMs ?? 0`. Passing `throttleMs: 0` explicitly disables throttling even when the provider specifies a non-zero `defaultThrottleMs`.
Run lifecycle callbacks (`onRunInitialized`, `onRunFinalized`, `onRunFailed`, `onRunErrorEvent`) always fire immediately, regardless of throttling.
The properties and methods below belong to the unwrapped agent (`agent.value`).
### Core Properties
<PropertyReference name="agentId" type="string | undefined">
Unique identifier for the agent instance.
</PropertyReference>
<PropertyReference name="description" type="string">
Human-readable description of the agent's purpose.
</PropertyReference>
<PropertyReference name="threadId" type="string">
Unique identifier for the current conversation thread.
</PropertyReference>
<PropertyReference name="messages" type="Message[]">
Array of conversation messages. Each message is an AG-UI `Message`. Common fields:
- `id: string` - unique message identifier
- `role: "user" | "assistant" | "system" | "tool" | "developer"` - message role (the per-message shape varies by role; for example, `tool` messages carry `toolCallId` instead of plain `content`)
- `content: string` - message content (text messages)
</PropertyReference>
<PropertyReference name="state" type="any">
Shared state object synchronized between application and agent. Both can read and modify this state.
</PropertyReference>
<PropertyReference name="isRunning" type="boolean">
Indicates whether the agent is currently executing.
</PropertyReference>
### Methods
<PropertyReference name="runAgent" type="(parameters?: RunAgentParameters, subscriber?: AgentSubscriber) => Promise<RunAgentResult>">
Manually triggers agent execution. Resolves with a `RunAgentResult` (`{ result, newMessages }`) once the run finalizes. `result` is the final value of the run and `newMessages` are the messages produced during it.
**Parameters:**
- `parameters.forwardedProps?: any` - data to pass to the agent execution context
**Example:**
```ts
const { result, newMessages } = await agent.value.runAgent({
forwardedProps: {
command: { resume: "user response" },
},
});
```
</PropertyReference>
<PropertyReference name="setState" type="(newState: any) => void">
Updates the shared state. Changes are immediately available to both application and agent.
**Example:**
```ts
agent.value.setState({
...agent.value.state,
theme: "dark",
});
```
</PropertyReference>
<PropertyReference name="subscribe" type="(subscriber: AgentSubscriber) => { unsubscribe: () => void }">
Subscribes to agent events. Returns a cleanup handle.
**Subscriber Events:**
- `onCustomEvent?: ({ event: { name: string, value: any } }) => void` - custom events
- `onRunStartedEvent?: () => void` - agent execution starts
- `onRunFinalized?: () => void` - agent execution completes
- `onStateChanged?: (params: { state: any, messages: Message[], agent: AbstractAgent }) => void` - state changes (read the new state from `params.state`)
- `onMessagesChanged?: (params: { messages: Message[], state: any, agent: AbstractAgent }) => void` - messages added or modified (read them from `params.messages`)
</PropertyReference>
<PropertyReference name="addMessage" type="(message: Message) => void">
Adds a single message to the conversation and notifies subscribers.
</PropertyReference>
<PropertyReference name="addMessages" type="(messages: Message[]) => void">
Adds multiple messages to the conversation and notifies subscribers once.
</PropertyReference>
<PropertyReference name="setMessages" type="(messages: Message[]) => void">
Replaces the entire message history with a new array of messages.
</PropertyReference>
<PropertyReference name="abortRun" type="() => void">
Aborts the currently running agent execution.
</PropertyReference>
<PropertyReference name="clone" type="() => AbstractAgent">
Creates a deep copy of the agent with cloned messages, state, and configuration.
</PropertyReference>
<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>
<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>
<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>
<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>
<script setup lang="ts">
import { ref } from "vue";
import { useAgent } from "@copilotkit/vue/v2";
const threadId = ref("thread-1");
// Each thread id resolves an independent agent clone with its own
// messages and state.
const { agent } = useAgent({ agentId: "default", threadId });
</script>
<template>
<div v-if="agent">Thread: {{ agent.threadId }} ({{ agent.messages.length }} messages)</div>
</template>
<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>
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 });
agent ref triggers reactivity when state, messages, or execution status changes (configurable via the updates parameter).agentId, threadId, and throttleMs accept MaybeRefOrGetter. The composable re-resolves and re-subscribes when they change, and also re-resolves when the runtime connection status or available agents change.threadId is set, the composable resolves a per-thread clone of the agent so each thread keeps independent messages and state.throttleMs, resolved as throttleMs ?? provider defaultThrottleMs ?? 0. Run lifecycle callbacks always fire immediately.agentId after the runtime has synced.setState() are immediately available to both app and agent.