@uservane/copilotkit
Frontend UserVane capture for CopilotKit.
CopilotKit is a frontend framework. Agent execution and Langfuse tracing live on the customer’s backend (LangGraph, CrewAI, Mastra, or any AG-UI agent) over AG-UI. This package is frontend-only: it captures feedback at deterministic turn resolution and links by CopilotKit threadId. It does not ship a Langfuse trace bridge (unlike @uservane/openai-agents). The backend owns tracing; UserVane posts a session-level uservane.satisfaction score keyed by threadId once the respondent answers.
What you get
Section titled “What you get”<UserVaneCopilotFeedback>watches the chat loading edge, binds a server-minted token (sessionId = threadId), and callsresolveTaskonce per genuine turn. RendersInlineFeedbackadjacent to your chat layout (you place the component; no in-transcript slot required).- Server mint (
/server) re-exportsmintFeedbackTokenfrom@uservane/agent-core/server. Mint withsessionId = threadId. - Re-exports
UserVaneProvider,InlineFeedback,useUserVanefrom@uservane/agent-reactfor a single import surface.
Install
Section titled “Install”npm install @uservane/copilotkit @copilotkit/react-core# peer: react >= 18# pin CopilotKit >= 1.63 (threadId propagation bug in older versions, #2624)Server: mint with sessionId = threadId
Section titled “Server: mint with sessionId = threadId”// app/api/feedback-token/route.ts (server only)import { mintFeedbackToken } from "@uservane/copilotkit/server";
const threadId = body.threadId; // same value as <CopilotKit threadId={...}>
const { tokens } = await mintFeedbackToken({ secretKey: process.env.USERVANE_SECRET_KEY!, // uv_sk_... never to the client respondentId: userId, sessionId: threadId, surveyId: "surv_post_task",});// thread tokens[surveyId] + sessionId to the clientNever import @uservane/copilotkit/server from client code.
Client: capture at turn resolution
Section titled “Client: capture at turn resolution”import { CopilotKit } from "@copilotkit/react-core";import { CopilotChat } from "@copilotkit/react-ui";import { UserVaneProvider, UserVaneCopilotFeedback,} from "@uservane/copilotkit";
const threadId = "/* your stable chat thread id */";
export function SupportChat({ showToken }: { showToken: string }) { return ( <CopilotKit runtimeUrl="/api/copilotkit" threadId={threadId}> <UserVaneProvider apiKey="uv_pk_live_..." surveySlug="post-task"> <CopilotChat /> {/* Place adjacent to the chat, not inside the transcript */} <UserVaneCopilotFeedback surveyId="surv_post_task" showToken={showToken} outcome="done" /> </UserVaneProvider> </CopilotKit> );}Resolution rules (deterministic)
Section titled “Resolution rules (deterministic)”- Signal:
isLoadingtrue to false (generation complete). The resolution signal owns the sample, never a model-triggered tool (useCopilotAction/useHumanInTheLooprender paths are out of scope for capture). - Once per turn: deduped by the latest assistant message id.
- Suppressed when the turn ended via
stopGeneration(abort) or a HITL interrupt (agent waiting on a human, not a finished answer). sessionId = threadId: mint, bind, submit, and pending session scores share this key. AbsentthreadIdmeans unbound capture (flagged).
No secret key (uv_sk_) is reachable from the client entry.
Closing the Langfuse loop (backend owns traces)
Section titled “Closing the Langfuse loop (backend owns traces)”UserVane does not trace the CopilotKit agent. Your backend agent framework must set Langfuse sessionId = threadId on its own traces so the uservane.satisfaction session score lands on the same session. Then run @uservane/langfuse-push (or your own pending-scores consumer).
CopilotKit version
Section titled “CopilotKit version”- Peer:
@copilotkit/react-core >= 1.63 - Older versions had a threadId-not-forwarded-to-backend bug (#2624). Pin and verify
>= 1.63.
Out of scope (v1)
Section titled “Out of scope (v1)”- Model-triggered feedback tools (
useCopilotAction/useHumanInTheLoopcapture paths). - In-transcript v2 UI slots as a package-import contract for capture. Not required: place
UserVaneCopilotFeedbacknext to the chat. - A Langfuse trace bridge for CopilotKit (backend owns tracing).
- Observation-level auto-read (deferred).