billing classifier
Here’s exactly how a reply gets counted.
This is the whole classifier. It takes the product, prior thread, and latest reply, then returns interested, not_interested, or neutral. Only interested is billable.
classify-reply.ts
import { openai, type OpenAIResponsesProviderOptions } from '@ai-sdk/openai';
import { generateText, Output } from 'ai';
import { z } from 'zod';
type EmailMessage = {
from: string;
to: string[];
subject: string;
body: string;
sentAt: string;
};
type ClassifyReplyInput = {
product: { name: string; website: string; description: string };
thread: EmailMessage[];
reply: EmailMessage;
};
const replyClassification = z.object({
verdict: z.enum(['interested', 'not_interested', 'neutral']),
reason: z.string().describe('One short factual sentence.'),
evidence: z.string().describe('The smallest exact excerpt supporting the verdict.'),
});
const system = [
'You are the billing classifier for PlzKnock cold outreach.',
'Classify only the latest inbound reply, using the prior thread as context.',
'interested: they clearly want to continue — e.g. ask for a call, demo, pricing, trial, proposal, or relevant details.',
'not_interested: they clearly decline, unsubscribe, complain, or say the offer is not relevant.',
'neutral: automated, out-of-office, ambiguous, merely polite, wrong-person, or otherwise neither clearly interested nor clearly not interested.',
'Do not infer interest from friendliness, opens, clicks, or sentiment.',
'Only interested is billable. When evidence is weak, return neutral.',
].join('\n');
export async function classifyReply(input: ClassifyReplyInput) {
const { output } = await generateText({
model: openai.responses('gpt-5.6-luna'),
output: Output.object({
name: 'reply_classification',
description: 'Billing classification for one inbound cold-email reply.',
schema: replyClassification,
}),
system,
prompt: JSON.stringify(input),
maxOutputTokens: 200,
providerOptions: {
openai: {
reasoningEffort: 'low',
textVerbosity: 'low',
store: false,
} satisfies OpenAIResponsesProviderOptions,
},
});
return output;
}Think we counted one wrong?
Send us the reply. A human will review it. If it clearly doesn’t count, we refund the $7.