Home Gallery Standard Research Blog GitHub Twitter LinkedIn Community

customer-service system prompt

Category: Extracted prompts. Audited against the AISPA standard.

What is in customer-service's system prompt?

customer-service's full system prompt: 2 versions, 16,023 characters. Audited against AISPA.

The full text of 2 prompts is reproduced below, 16,023 characters in all, each read instruction by instruction against the eight AISPA dimensions. Nothing was flagged as working against the person on the other end.

2 Prompts on record
0 Flagged instructions
AI audit Audit source
D1 · Identity Transparency D2 · Truthfulness & Information Integrity D5 · User Agency & Manipulation Prevention D6 · Unsafe Request Handling

customer-service - customer service / owly / engine

8747 characters

import OpenAI from "openai"; import { prisma } from "@/lib/prisma"; import { owlyTools, executeToolCall } from "./tools"; import { emitNewMessage } from "@/lib/realtime"; import { analyzeSentiment, detectIntent, estimateConfidence, requiresHumanApproval } from "./guardrails"; import type { AIMessage, AIConfig, ConversationContext, KnowledgeItem, } from "./types"; function buildSystemPrompt(context: ConversationContext): string { const toneGuide: Record<string, string> = { friendly: "Be warm, approachable, and conversational. Use a casual but professional tone.", professional: "Be polished and business-like. Maintain a confident, competent tone while remaining personable.", formal: "Be professional, polished, and courteous. Use formal language and proper grammar.", technical: "Be precise and detailed. Use technical terminology when appropriate and provide thorough explanations.", }; const knowledgeSection = context.knowledgeBase.length > 0 ? context.knowledgeBase .sort((a, b) => b.priority - a.priority) .map( (k) => `[${k.category}] ${k.title}:\n${k.content}` ) .join("\n\n---\n\n") : "No specific knowledge base entries available. Answer based on general knowledge about the business."; return `You are Owly, the AI customer support assistant for ${context.businessName}. ${context.businessDesc ? `About the business: ${context.businessDesc}` : ""} ## Communication Style ${toneGuide[context.tone] || toneGuide.friendly} ${context.language !== "auto" ? `Always respond in: ${context.language}` : "Respond in the same language the customer uses."} ## Your Knowledge Base Use the following information to answer customer questions accurately: ${knowledgeSection} ## Important Guidelines - Always be helpful and try to resolve the customer's issue - If you cannot answer a question from the knowledge base, honestly say so and offer to connect them with a team member - Use the create_ticket tool when a customer reports a problem that needs human intervention - Use send_internal_email to notify relevant team members about urgent issues - Use get_customer_history to check if the customer has contacted before - Never make up information that isn't in your knowledge base - Keep responses concise but thorough - The customer is contacting via: ${context.channel} ${context.customerName !== "Unknown" ? `- Customer name: ${context.customerName}` : ""} ## Customer History ${context.customerHistory.length > 0 ? context.customerHistory.join("\n") : "This is the customer's first interaction."}`; } async function getKnowledgeBase(): Promise<KnowledgeItem[]> { const entries = await prisma.knowledgeEntry.findMany({ where: { isActive: true }, include: { category: true }, orderBy: { priority: "desc" }, }); return entries.map((e: { category: { name: string }; title: string; content: string; priority: number }) => ({ category: e.category.name, title: e.title, content: e.content, priority: e.priority, })); } async function getAIConfig(): Promise<AIConfig & ConversationContext> { let settings = await prisma.settings.findFirst(); if (!settings) { settings = await prisma.settings.create({ data: { id: "default" } }); } return { provider: settings.aiProvider, model: settings.aiModel, apiKey: settings.aiApiKey, maxTokens: settings.maxTokens, temperature: settings.temperature, businessName: settings.businessName, businessDesc: settings.businessDesc, welcomeMessage: settings.welcomeMessage, tone: settings.tone, language: settings.language, knowledgeBase: [], customerName: "", customerHistory: [], channel: "", }; } export async function chat( conversationId: string, userMessage: string ): Promise<string> { const config = await getAIConfig(); if (!config.apiKey) { return "AI is not configured. Please add your API key in Settings > AI Configuration."; } const conversation = await prisma.conversation.findUnique({ where: { id: conversationId }, include: { messages: { orderBy: { createdAt: "asc" }, take: 50 }, }, }); if (!conversation) { return "Conversation not found."; } const knowledgeBase = await getKnowledgeBase(); const context: ConversationContext = { ...config, knowledgeBase, customerName: conversation.customerName, channel: conversation.channel, customerHistory: [], }; // Build message history const messages: AIMessage[] = [ { role: "system", content: buildSystemPrompt(context) }, ]; for (const msg of conversation.messages) { if (msg.role === "customer") { messages.push({ role: "user", content: msg.content }); } else if (msg.role === "assistant") { messages.push({ role: "assistant", content: msg.content }); } } messages.push({ role: "user", content: userMessage }); // Guardrails: check if human approval needed const approval = requiresHumanApproval(userMessage); if (approval.required) { const sentiment = analyzeSentiment(userMessage); const intent = detectIntent(userMessage); // Store metadata for dashboard visibility await prisma.conversation.update({ where: { id: conversationId }, data: { metadata: { escalationReason: approval.reason, sentiment: sentiment.sentiment, intent: intent.intent, }, }, }); } // Save user message await prisma.message.create({ data: { conversationId, role: "customer", content: userMessage, }, }); // Call AI const response = await callAI(config, messages, conversationId); // Save assistant message const savedMessage = await prisma.message.create({ data: { conversationId, role: "assistant", content: response, }, }); // Update conversation timestamp await prisma.conversation.update({ where: { id: conversationId }, data: { updatedAt: new Date() }, }); // Confidence scoring const confidence = estimateConfidence(response, knowledgeBase.length, false); if (confidence.shouldEscalate) { await prisma.conversation.update({ where: { id: conversationId }, data: { status: "escalated" }, }); } emitNewMessage(conversationId, { id: savedMessage.id, role: "assistant", content: response }); return response; } async function callAI( config: AIConfig, messages: AIMessage[], conversationId: string, depth = 0 ): Promise<string> { if (depth > 5) { return "I apologize, but I'm having trouble processing your request. Let me connect you with a team member."; } const openai = new OpenAI({ apiKey: config.apiKey }); let response; try { response = await openai.chat.completions.create({ model: config.model, messages: messages as OpenAI.ChatCompletionMessageParam[], tools: owlyTools as OpenAI.ChatCompletionTool[], max_tokens: config.maxTokens, temperature: config.temperature, }); } catch { return "I'm temporarily unable to process your request. Please try again in a moment, or I can connect you with a team member."; } const choice = response.choices[0]; if ( choice.finish_reason === "tool_calls" && choice.message.tool_calls?.length ) { // Process tool calls const toolCalls = choice.message.tool_calls as Array<{ id: string; type: string; function: { name: string; arguments: string }; }>; messages.push({ role: "assistant", content: choice.message.content || "", tool_calls: toolCalls.map((tc) => ({ id: tc.id, type: "function" as const, function: { name: tc.function.name, arguments: tc.function.arguments, }, })), }); for (const toolCall of toolCalls) { const args = JSON.parse(toolCall.function.arguments); const result = await executeToolCall( toolCall.function.name, args, conversationId ); messages.push({ role: "tool", content: result, tool_call_id: toolCall.id, }); } // Continue the conversation with tool results return callAI(config, messages, conversationId, depth + 1); } return choice.message.content || "I apologize, I could not generate a response."; } export async function createNewConversation( channel: string, customerName: string, customerContact: string, customerId?: string ) { return prisma.conversation.create({ data: { channel, customerName, customerContact, ...(customerId && { customerId }), }, }); }

customer-service - customer service / owly / guardrails

7276 characters

/** * AI Guardrails - Controls what the AI can and cannot do. */ export interface GuardrailConfig { blockedTopics: string[]; maxResponseLength: number; requireHumanApproval: string[]; confidenceThreshold: number; } const DEFAULT_GUARDRAILS: GuardrailConfig = { blockedTopics: [ "legal advice", "medical advice", "investment advice", "price commitments", "competitor comparisons", ], maxResponseLength: 2000, requireHumanApproval: [ "refund", "cancellation", "discount", "compensation", "legal", ], confidenceThreshold: 0.6, }; /** * Check if a message contains blocked topics. */ export function checkBlockedTopics( message: string, config: GuardrailConfig = DEFAULT_GUARDRAILS ): { blocked: boolean; topic?: string } { const lower = message.toLowerCase(); for (const topic of config.blockedTopics) { if (lower.includes(topic.toLowerCase())) { return { blocked: true, topic }; } } return { blocked: false }; } /** * Check if a message requires human approval before AI responds. */ export function requiresHumanApproval( message: string, config: GuardrailConfig = DEFAULT_GUARDRAILS ): { required: boolean; reason?: string } { const lower = message.toLowerCase(); for (const keyword of config.requireHumanApproval) { if (lower.includes(keyword.toLowerCase())) { return { required: true, reason: keyword }; } } return { required: false }; } /** * Truncate AI response to maximum allowed length. */ export function enforceResponseLength( response: string, config: GuardrailConfig = DEFAULT_GUARDRAILS ): string { if (response.length <= config.maxResponseLength) return response; return response.substring(0, config.maxResponseLength).trimEnd() + "..."; } /** * Analyze sentiment of a message. * Returns: positive, negative, neutral, or frustrated */ export function analyzeSentiment(message: string): { sentiment: "positive" | "negative" | "neutral" | "frustrated"; score: number; } { const lower = message.toLowerCase(); const negativePatterns = [ "angry", "furious", "terrible", "worst", "hate", "awful", "disgusting", "unacceptable", "ridiculous", "horrible", "scam", "fraud", "sue", "lawyer", "complaint", ]; const frustratedPatterns = [ "again", "still", "waiting", "how long", "not working", "broken", "frustrated", "annoyed", "disappointed", "already told", "third time", "keep asking", ]; const positivePatterns = [ "thank", "great", "excellent", "awesome", "love", "perfect", "amazing", "wonderful", "fantastic", "helpful", "appreciate", "satisfied", "happy", ]; let score = 0; for (const p of negativePatterns) { if (lower.includes(p)) score -= 2; } for (const p of frustratedPatterns) { if (lower.includes(p)) score -= 1; } for (const p of positivePatterns) { if (lower.includes(p)) score += 2; } if (score <= -3) return { sentiment: "negative", score: Math.max(-1, score / 10) }; if (score <= -1) return { sentiment: "frustrated", score: score / 10 }; if (score >= 2) return { sentiment: "positive", score: Math.min(1, score / 10) }; return { sentiment: "neutral", score: 0 }; } /** * Detect customer intent from message. */ export function detectIntent(message: string): { intent: string; confidence: number; } { const lower = message.toLowerCase(); const intents: { intent: string; keywords: string[]; weight: number }[] = [ { intent: "support", keywords: ["help", "issue", "problem", "not working", "broken", "error", "bug", "fix"], weight: 1 }, { intent: "billing", keywords: ["invoice", "bill", "charge", "payment", "refund", "price", "cost", "subscription", "plan"], weight: 1 }, { intent: "sales", keywords: ["buy", "purchase", "pricing", "demo", "trial", "interested", "quote", "proposal"], weight: 1 }, { intent: "complaint", keywords: ["complaint", "unhappy", "dissatisfied", "terrible", "worst", "unacceptable", "sue"], weight: 1.5 }, { intent: "information", keywords: ["how", "what", "when", "where", "can i", "do you", "is it", "tell me"], weight: 0.5 }, { intent: "cancellation", keywords: ["cancel", "unsubscribe", "stop", "close account", "terminate", "end service"], weight: 1.5 }, { intent: "feedback", keywords: ["suggest", "feedback", "improve", "feature request", "would be nice", "wish"], weight: 1 }, { intent: "greeting", keywords: ["hello", "hi", "hey", "good morning", "good afternoon"], weight: 0.3 }, ]; let bestMatch = { intent: "general", confidence: 0 }; for (const { intent, keywords, weight } of intents) { let matchCount = 0; for (const kw of keywords) { if (lower.includes(kw)) matchCount++; } const confidence = Math.min(1, (matchCount * weight) / 3); if (confidence > bestMatch.confidence) { bestMatch = { intent, confidence }; } } return bestMatch; } /** * Generate a conversation summary from messages. */ export function generateSummaryPrompt( messages: { role: string; content: string }[] ): string { const transcript = messages .slice(-20) .map((m) => `${m.role}: ${m.content.substring(0, 300)}`) .join("\n"); return `Summarize this customer support conversation in 2-3 sentences. Focus on: what the customer needed, what was done, and the outcome. Conversation: ${transcript} Summary:`; } /** * Calculate AI confidence score based on response characteristics. */ export function estimateConfidence( response: string, knowledgeBaseSize: number, hasToolCalls: boolean ): { score: number; shouldEscalate: boolean } { let score = 0.5; // Knowledge base coverage if (knowledgeBaseSize > 20) score += 0.1; if (knowledgeBaseSize > 50) score += 0.1; // Response quality indicators if (response.length > 50 && response.length < 1500) score += 0.1; if (hasToolCalls) score += 0.1; // Uncertainty indicators const uncertainPhrases = [ "i'm not sure", "i don't know", "i cannot", "i apologize", "unfortunately", "i'm unable", "beyond my knowledge", "connect you with", "team member", ]; const lower = response.toLowerCase(); for (const phrase of uncertainPhrases) { if (lower.includes(phrase)) { score -= 0.15; break; } } score = Math.max(0, Math.min(1, score)); return { score: Math.round(score * 100) / 100, shouldEscalate: score < DEFAULT_GUARDRAILS.confidenceThreshold, }; } /** * Generate suggested replies for an agent based on conversation context. */ export function generateSuggestedRepliesPrompt( messages: { role: string; content: string }[], cannedResponses: { title: string; content: string }[] ): string { const lastMessages = messages.slice(-5); const transcript = lastMessages .map((m) => `${m.role}: ${m.content.substring(0, 200)}`) .join("\n"); const canned = cannedResponses .slice(0, 5) .map((c) => `- ${c.title}: ${c.content.substring(0, 100)}`) .join("\n"); return `Based on this conversation, suggest 3 short professional replies the support agent could send. Each reply should be 1-2 sentences. Recent messages: ${transcript} ${canned ? `Available templates:\n${canned}\n` : ""} Return exactly 3 suggestions as a JSON array of strings.`; }

Questions about customer-service's system prompt

Does customer-service's system prompt contain instructions that work against the user?

No. Nothing in customer-service's system prompt was flagged as working against the person the product is talking to. That is a clean result across all eight AISPA dimensions, not an absence of checking — the full text was read instruction by instruction.

How long is customer-service's system prompt?

16,023 characters across 2 prompts on this page. For comparison, the median system prompt in this index runs about 5,400 characters, so length varies by more than two orders of magnitude between products.

How many versions of customer-service's system prompt are on record?

2. Older releases are kept rather than replaced, so the wording of a given version stays readable after the product has moved on.

Where did this customer-service system prompt come from?

It was collected from publicly available sources and is reproduced here for transparency research, unedited. This site does not extract prompts from products itself.

How was customer-service's system prompt audited?

Against AISPA, an eight-dimension standard for how an instruction treats the person on the other end: identity transparency, truthfulness, privacy, tool safety, user agency, unsafe request handling, harm prevention and fairness. This audit was ai audit. The method is described in the paper behind the standard.

How this page was made

The prompt text above is reproduced verbatim from a public source. Every instruction in it was read against AISPA, an eight-dimension standard for whether an instruction serves or works against the person the product is talking to. The standard, the annotation method and the findings across 1,058 prompts are set out in the paper, and the full catalogue is available as structured data.

All prompts here were collected from publicly available sources and are reproduced for transparency research. Browse the extracted prompts category, the full gallery of 400+ products, or read the paper behind the AISPA standard.