BlogCompose

Half of every support ticket is asking what the user already did. Attach the answer instead.

The ticket says "it's not working" - and the next twenty minutes go to figuring out who this user is, what plan they're on, and whether "it" is a bug, a quota, or a misunderstanding. The actual fix usually takes two. All of that context lives in your usage data; here is how to attach it to every ticket automatically.

The hook

Support for a solo founder is a context-reconstruction job. The ticket says "it's not working" - and the next twenty minutes go to figuring out who this user is, what plan they're on, what they were doing when it broke, and whether "it" is a bug, a quota, or a misunderstanding. The actual fix usually takes two. All of that context lives in your usage data at the moment the ticket arrives, so I attach it to every ticket automatically - a generated context card, written for me, before I've read the message. My app meters usage with Vevee (@vevee/sdk). When a ticket comes in (helpdesk webhook, support@ pipe, contact form - anything with a user identifier), one compose() call builds the card:

import { createClient } from "@vevee/sdk";

const vevee = createClient({ apiKey: process.env.VEVEE_SECRET_KEY! });

interface SupportContext {
  who: string;             // plan, tenure, usage level in one line
  recentActivity: string;  // what they did in the last 48h, in order
  likelyIssue: string;     // best inference: bug / quota / confusion
  quotaState: string;      // where they stand vs. limits RIGHT NOW
  watchOut: string;        // anything that changes the tone (churn-risk, VIP, repeat issue)
}

async function onTicketCreated(ticket: Ticket) {
  const ctx = await vevee.compose<SupportContext>(
    "support-context",
    ticket.userId,
    { subject: ticket.subject } // the ticket subject steers the inference
  );

  if (ctx.status === "generated") {
    await addInternalNote(ticket.id, formatCard(ctx.output));
  }
}

The prompt behind the card

The compose type's prompt: "A support ticket just arrived from this user with subject '{subject}'. From their recent events and usage, reconstruct what they were most likely doing when the problem occurred. State their exact quota position. Infer whether this smells like a bug, a limit, or a misunderstanding - and say which evidence points there. One line of anything the responder should know about this account." Data sources: user usage, user events, user attributes - and if prompt logging is enabled for the app, their recent prompts, which is often the difference between guessing and knowing.

The card on a real ticket

Ticket subject: "generation keeps failing???" The card that landed on it as an internal note:

  • Who: Pro ($15/mo), customer for 7 months, heavy daily user.
  • Last 48h: 22 successful image_generation events, then at 14:12 four consecutive reserve() denials, then two more attempts, then the ticket (14:31).
  • Quota state: 498/500 monthly generations. The "failures" are limit denials, not errors.
  • Likely issue: quota, not bug - denials line up exactly with the cap, and nothing failed before 14:12.
  • Watch out: second month in a row she's capped before month-end. She's outgrown Pro; this ticket is an upgrade conversation wearing a bug report's clothes.

The ninety-second reply

My reply took ninety seconds and didn't open with "could you tell me more about the issue?" It opened with: "You're not seeing a bug - you hit your monthly cap at 14:12 (you're at 498/500). Second month running you've maxed it, so you might genuinely want the next tier; here's what that looks like." Accurate, fast, and the support ticket just became the most credible upsell surface in the product - because it's true and it solved their problem.

Why founders should steal this even with a support tool that "has AI"

Helpdesk AI summarizes the conversation. This summarizes the product reality - quota positions, event sequences, reservation denials - which the helpdesk cannot see and which is where the answer usually is. The two compose nicely: their AI drafts the prose, your card supplies the facts. Mechanics: server-side webhook handler (sk_* key), fractions of a cent per card (usage.costMicroUsd reports each one; the dashboard's monthly compose budget caps the pile). The math that sold me: ~20 minutes of context archaeology per ticket becomes ~2. At even five tickets a week that's 90 founder-minutes back, every week, for one webhook and one dashboard config.

Users who opted out of AI personalization return opted_out - their tickets get handled the classic way, by reading and asking. Which, at the volume of opted-out tickets, is fine.
See your own numbers in two minutes.Add the SDK and your users, costs and revenue fill in on the next request.
Join waitlist

Keep reading

ShareCopy a link to this post.

Set your first limit in about five minutes.

50k operations free every month. No card required.
Join waitlist