@uservane/agent-core
Framework-agnostic headless core for agent-native capture. Holds the controller, correlation seam, anonymous keys, types, and the server-only mint helpers. Framework adapters (@uservane/vercel-ai, @uservane/openai-agents, @uservane/copilotkit) re-export this surface and stay thin.
Install
Section titled “Install”npm install @uservane/agent-coreClient (headless)
Section titled “Client (headless)”import { AgentController } from "@uservane/agent-core";
const controller = new AgentController();controller.init({ key: "uv_pk_live_...", surveySlug: "post-task" });controller.identify({ userId: "u_123" });
// After the server mints a bound token and you thread it down:controller.bind({ surveyId, showToken, sessionId });
// At true task resolution:controller.resolveTask({ outcome: "refunded" });
// Off-platform / async resolution: close the task without an in-session ask.controller.resolveTask({ defer: true, outcome: "refund_pending" });// later: mintDeferredAskLink on the server and deliver via your channel.Model-requested tool (opt-in)
Section titled “Model-requested tool (opt-in)”Off by default. The server must mint with allowModelRequested: true (bakes amr into the show-token). The model cannot self-enable. Captures are stored as identity_kind=model-requested and are headline-excluded. Never fires while a task is open.
import { handleRequestUserFeedback } from "@uservane/agent-core";
const result = handleRequestUserFeedback(controller);// { ok: true, status: "feedback_requested", ... }// or { ok: false, status: "task_open" | "not_enabled" | ... }Adapter wrappers expose the same contract as framework tools from @uservane/vercel-ai and @uservane/openai-agents (createRequestUserFeedbackTool(controller)).
Server: @uservane/agent-core/server
Section titled “Server: @uservane/agent-core/server”import { mintFeedbackToken, mintDeferredAskLink } from "@uservane/agent-core/server";
const { tokens } = await mintFeedbackToken({ secretKey: process.env.USERVANE_SECRET_KEY!, // uv_sk_... NEVER ship to the browser respondentId: userId, sessionId, // same id you use for Langfuse session / agent groupId surveyId: "surv_post_task", // Optional: enable the model-requested agent tool for this token (self-selection; // those captures are headline-excluded). // allowModelRequested: true,});
// Out-of-band ask after an async outcome (e.g. refund days later).// UserVane does not send email/SMS; last-mile delivery is your channel.const deferred = await mintDeferredAskLink({ secretKey: process.env.USERVANE_SECRET_KEY!, respondentId: userId, surveyId: "surv_post_task", sessionId,});// deferred.url: hosted ask link (STANDALONE capture, not session-linked).// deferred.showToken + deferred.sessionId: session-linked path for the next// in-app session via controller.bind({ surveyId, showToken, sessionId }).Never import @uservane/agent-core/server from client code.
What this is not
Section titled “What this is not”- Not a React UI (see
@uservane/agent-react). - Not a framework adapter (see vercel-ai / openai-agents / copilotkit).
- Not an email or SMS sender (out-of-band delivery reuses your channel).
- Observation-level auto-read of AI SDK / OTel trace ids is deferred.