useInterrupt
Vue 3 composable for handling agent interrupt events and resuming execution with user input
Overview
useInterrupt is a Vue 3 composable that listens for agent custom events named on_interrupt, captures the latest interrupt payload for a run, and surfaces it once the run finalizes. Your UI calls resolveInterrupt(response) to resume the agent with a resume payload.
Unlike a render-prop API, the Vue composable does not return UI. Instead it returns reactive state (interrupt, result, hasInterrupt, slotProps) plus the resolveInterrupt function, and (by default) publishes that state into <CopilotChat> so you can render interrupts through the chat's #interrupt slot.
event.value is typed by the TValue type parameter (defaults to unknown), since the interrupt payload shape depends on your agent. Type-narrow it in your handler and enabled callbacks, or pass an explicit TValue when calling the composable.
By default (renderInChat omitted or true), the composable pushes interrupt state into <CopilotChat>, where you render it via the #interrupt slot. Set renderInChat: false to manage rendering yourself from the returned reactive refs.
Signature
import { useInterrupt } from "@copilotkit/vue/v2";
function useInterrupt<TValue = unknown, TResult = never>(
config?: UseInterruptConfig<TValue, TResult>,
): UseInterruptResult<TValue, TResult>;Parameters
Prop
Type
Return Value
Prop
Type
Usage
In-chat interrupt UI (default)
By default the composable publishes interrupt state into <CopilotChat>. Mount the composable, then render the interrupt through the chat's #interrupt slot.
<script setup lang="ts">
import { useInterrupt } from "@copilotkit/vue/v2";
import { CopilotChat } from "@copilotkit/vue/v2";
interface Approval {
question: string;
}
// Publishes interrupt state into <CopilotChat>.
useInterrupt<Approval>();
</script>
<template>
<CopilotChat>
<template #interrupt="{ event, resolve }">
<div class="rounded border p-3">
<!-- `#interrupt` slot props are typed with `unknown` value; cast to your payload type. -->
<p>{{ (event.value as Approval).question }}</p>
<div class="mt-2 flex gap-2">
<button @click="resolve({ approved: true })">Approve</button>
<button @click="resolve({ approved: false })">Reject</button>
</div>
</div>
</template>
</CopilotChat>
</template>Manual placement with async preprocessing
Set renderInChat: false and render directly from the returned reactive refs.
<script setup lang="ts">
import { useInterrupt } from "@copilotkit/vue/v2";
const { interrupt, result, hasInterrupt, resolveInterrupt } = useInterrupt<
string,
{ label: string }
>({
renderInChat: false,
enabled: (event) => event.value.startsWith("approval:"),
handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
});
</script>
<template>
<aside v-if="hasInterrupt" class="rounded border p-3">
<div class="font-medium">{{ result?.label ?? "" }}</div>
<div class="mt-2">{{ interrupt?.value }}</div>
<button class="mt-2" @click="resolveInterrupt({ accepted: true })">
Continue
</button>
</aside>
</template>Reading reactive state in script
import { useInterrupt } from "@copilotkit/vue/v2";
const { interrupt, hasInterrupt, result, resolveInterrupt } = useInterrupt({
handler: ({ event }) => ({ label: String(event.value) }),
});
// `interrupt` and `result` are reactive refs; `hasInterrupt` is a computed.
// Call `resolveInterrupt(response)` to resume the agent.Behavior
- Interrupts are collected from agent custom events named
on_interrupt. - The pending interrupt is surfaced when the run finalizes (
onRunFinalized). - Starting a new run (
onRunStartedEvent) clears pending interrupt state, and a failed run (onRunFailed) discards the in-flight interrupt. event.valueis typed byTValue(defaults tounknown); narrow it inhandler/enabledor pass an explicitTValue.resultis inferred from thehandlerreturn type and is alwaysTResult | null. Ifhandlerreturns a rejected promise,resultis set tonull; a synchronousthrowis not caught (it surfaces from the watcher that runs the handler) andresultis left unchanged.- When
enabledreturnsfalse, the interrupt is ignored:resultandslotPropsstaynulland nothing is published to chat. - With
renderInChatomitted ortrue,slotPropsis published into<CopilotChat>for the#interruptslot. WithrenderInChat: false, no chat publishing occurs and you render from the returned refs. resolveInterrupt(response)resumes the agent viarunAgentwithforwardedProps.command.resume = response(along with the originatinginterruptEvent); it no-ops if no agent is resolved.