useThreads

Vue 3 composable for listing, managing, and syncing conversation threads with useThreads -- rename, archive, delete, and paginate threads with realtime updates.


useThreads needs an Enterprise Intelligence Platform project
Sign up for a free account to get a public license key and start syncing threads.
Create a free account

Overview

useThreads is a Vue 3 composable for managing conversation threads on the Enterprise Intelligence Platform. It fetches the thread list for a given agent, keeps it synchronized in realtime via the core thread store's realtime channel, and exposes mutation methods for renaming, archiving, and deleting threads.

Threads are sorted by recency — by lastRunAt when present, falling back to updatedAt, then createdAt (most recent first). The composable supports cursor-based pagination when a limit is provided. All inputs accept refs, computeds, or getters (MaybeRefOrGetter), so changing the thread context reactively re-fetches the list.

Return values are Vue refs and computeds. Read them with .value in <script setup>, or unwrap them automatically in <template>.

Signature

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

function useThreads(input: UseThreadsInput): UseThreadsResult

Parameters

Prop

Type

Return Value

Prop

Type

Usage

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

const {
  threads,
  isLoading,
  renameThread,
  archiveThread,
  deleteThread,
} = useThreads({ agentId: "my-agent" }); 
</script>

<template>
  <div v-if="isLoading">Loading threads...</div>
  <ul v-else>
    <li v-for="thread in threads" :key="thread.id">
      <span>{{ thread.name ?? "Untitled" }}</span>
      <button @click="renameThread(thread.id, 'New name')">Rename</button>
      <button @click="archiveThread(thread.id)">Archive</button>
      <button @click="deleteThread(thread.id)">Delete</button>
    </li>
  </ul>
</template>

Reactive agent context

Because inputs accept refs and getters, you can drive the thread list from reactive state. Switching agentId automatically re-fetches the list.

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

const agentId = ref("support-agent");
const includeArchived = ref(false);

const { threads, hasMoreThreads, fetchMoreThreads } = useThreads({
  agentId, // ref -- changing it re-fetches threads
  includeArchived,
  limit: 20,
});
</script>

<template>
  <select v-model="agentId">
    <option value="support-agent">Support</option>
    <option value="sales-agent">Sales</option>
  </select>

  <label>
    <input type="checkbox" v-model="includeArchived" />
    Show archived
  </label>

  <ul>
    <li v-for="thread in threads" :key="thread.id">
      {{ thread.name ?? "Untitled" }}
    </li>
  </ul>

  <button v-if="hasMoreThreads" @click="fetchMoreThreads">Load more</button>
</template>

Behavior

  • On mount, fetches the thread list and establishes a realtime subscription via the core thread store.
  • Thread creates, renames, archives, and deletes from any client are reflected immediately without polling.
  • All mutation methods use pessimistic updates: the list updates only after the server confirms the operation, not immediately on dispatch. Promises resolve on confirmation and reject on failure.
  • The composable defers its first fetch until the runtime reports a Connected status, so it issues a single list request plus a single subscribe request rather than refetching once realtime details resolve.
  • While the runtime is connecting (a runtime URL is set but no context has been dispatched yet), isLoading stays true to avoid an empty-list flash.
  • When no runtime URL is configured, error reports a configuration error and the thread store is cleared.
  • The threads array stays sorted by recency descending — by lastRunAt when present, falling back to updatedAt, then createdAt.
  • New threads are automatically named by the LLM after their first run (a 2 to 5 word title). This is configurable via generateThreadNames on the runtime.
  • The composable cleans up its store subscriptions and stops the store automatically when the owning scope is disposed (onScopeDispose).

Next steps