customer-success

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Customer Success Engineering

客户成功工程

Overview

概述

This skill covers building technical systems that power customer support and success operations. It addresses support ticket system integration (Zendesk, Intercom, Freshdesk), knowledge base architecture, conversational AI chatbot design, customer feedback collection and routing, SLA management and enforcement, escalation workflow automation, self-service portal implementation, and customer health scoring models.
Use this skill when building or integrating support systems, designing chatbot flows, creating self-service documentation portals, implementing SLA tracking, building customer health dashboards, or automating support workflows.

本技能涵盖构建为客户支持与成功运营提供支撑的技术系统,包括支持工单系统集成(Zendesk、Intercom、Freshdesk)、知识库架构设计、对话式AI聊天机器人开发、客户反馈收集与路由、SLA管理与执行、升级工作流自动化、自助服务门户实施以及客户健康评分模型构建。
当你需要构建或集成支持系统、设计聊天机器人流程、创建自助服务文档门户、实施SLA跟踪、构建客户健康仪表板或自动化支持工作流时,可使用本技能。

Core Principles

核心原则

  1. Self-service first - The best support interaction is the one that never happens. Invest in searchable knowledge bases, in-app help, and contextual guidance before scaling human support.
  2. Automate triage, not resolution - AI can classify, prioritize, and route tickets effectively. Let humans handle resolution for complex issues. Over-automating resolution creates frustrated customers.
  3. Measure time-to-resolution, not ticket count - Closing tickets quickly means nothing if the customer's problem isn't solved. Track first-contact resolution rate, customer effort score, and reopen rate.
  4. Context travels with the ticket - Every handoff (bot to human, L1 to L2) must include full conversation history, user account data, and attempted solutions. Repeating information is the #1 customer complaint.
  5. Feedback is a product signal - Support tickets are unstructured product feedback. Tag, categorize, and surface trends to product teams. The most common support topic should become the next product improvement.

  1. 自助优先 - 最好的支持互动是无需人工介入的互动。在扩大人工支持规模之前,优先投入可搜索的知识库、应用内帮助和上下文引导。
  2. 自动化分流,而非自动化解决 - AI可以有效地分类、优先级排序和路由工单。让人工处理复杂问题的解决。过度自动化问题解决会导致客户不满。
  3. 衡量解决时间,而非工单数量 - 快速关闭工单如果没有解决客户的问题毫无意义。跟踪首次联系解决率、客户努力评分和重开率。
  4. 工单携带完整上下文 - 每一次交接(机器人转人工、L1转L2)都必须包含完整的对话历史、用户账户数据和已尝试的解决方案。重复提供信息是客户最常见的投诉点。
  5. 反馈是产品信号 - 支持工单是非结构化的产品反馈。对工单进行标记、分类,并向产品团队呈现趋势。最常见的支持主题应成为下一个产品改进方向。

Key Patterns

关键模式

Pattern 1: Knowledge Base Architecture

模式1:知识库架构

When to use: Building searchable documentation that serves both customers (self-service) and support agents (internal reference).
Implementation:
typescript
// Knowledge base article schema
interface Article {
  id: string;
  slug: string;
  title: string;
  content: string;          // Markdown
  excerpt: string;          // For search results
  category: string;
  subcategory: string;
  tags: string[];
  audience: "customer" | "internal" | "both";
  visibility: "public" | "authenticated" | "internal";
  relatedArticles: string[];
  metadata: {
    createdAt: Date;
    updatedAt: Date;
    author: string;
    reviewedAt: Date | null;
    helpfulVotes: number;
    notHelpfulVotes: number;
    viewCount: number;
  };
}

// Search implementation with vector + full-text hybrid
async function searchKnowledgeBase(
  query: string,
  options?: { category?: string; audience?: string; limit?: number }
): Promise<SearchResult[]> {
  const limit = options?.limit ?? 10;

  // 1. Semantic search (catches paraphrased queries)
  const embedding = await getEmbedding(query);
  const semanticResults = await vectorDb.search({
    vector: embedding,
    filter: {
      audience: options?.audience ?? "customer",
      ...(options?.category && { category: options.category }),
    },
    limit,
  });

  // 2. Full-text search (catches exact terminology)
  const textResults = await db.$queryRaw`
    SELECT id, title, excerpt,
           ts_rank(search_vector, plainto_tsquery('english', ${query})) AS rank
    FROM articles
    WHERE search_vector @@ plainto_tsquery('english', ${query})
      AND audience IN ('customer', 'both')
      ${options?.category ? Prisma.sql`AND category = ${options.category}` : Prisma.empty}
    ORDER BY rank DESC
    LIMIT ${limit}
  `;

  // 3. Merge and deduplicate results
  const merged = mergeSearchResults(semanticResults, textResults);

  // 4. Track search for analytics
  await trackSearch(query, merged.length);

  return merged;
}

// Feedback loop - track article helpfulness
async function rateArticle(
  articleId: string,
  helpful: boolean,
  feedback?: string
): Promise<void> {
  await db.articleFeedback.create({
    data: {
      articleId,
      helpful,
      feedback,
      createdAt: new Date(),
    },
  });

  // Update aggregate counts
  await db.article.update({
    where: { id: articleId },
    data: helpful
      ? { helpfulVotes: { increment: 1 } }
      : { notHelpfulVotes: { increment: 1 } },
  });

  // Flag articles with low helpfulness for review
  const article = await db.article.findUnique({ where: { id: articleId } });
  if (article) {
    const total = article.helpfulVotes + article.notHelpfulVotes;
    const helpfulRate = total > 10 ? article.helpfulVotes / total : 1;

    if (helpfulRate < 0.5 && total > 10) {
      await createReviewTask(articleId, "Low helpfulness score");
    }
  }
}
tsx
// In-app contextual help widget
function HelpWidget({ context }: { context: string }) {
  const [articles, setArticles] = useState<Article[]>([]);
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    // Fetch relevant articles based on current page/feature context
    if (isOpen) {
      searchKnowledgeBase("", { category: context, limit: 5 })
        .then(setArticles);
    }
  }, [isOpen, context]);

  return (
    <div className="help-widget">
      <button
        onClick={() => setIsOpen(!isOpen)}
        aria-label="Help"
        aria-expanded={isOpen}
      >
        ?
      </button>
      {isOpen && (
        <div role="dialog" aria-label="Help articles">
          <SearchInput onSearch={(q) => searchKnowledgeBase(q, { category: context }).then(setArticles)} />
          <ArticleList articles={articles} />
          <a href="/support">Contact support</a>
        </div>
      )}
    </div>
  );
}
Why: Hybrid search (semantic + full-text) covers both conceptual queries ("how do I share my project?") and exact terminology queries ("SSO SAML configuration"). The feedback loop ensures low-quality articles are flagged for improvement. Contextual help surfaces relevant articles without the user needing to search.

适用场景: 构建可搜索的文档,为客户(自助服务)和支持人员(内部参考)提供服务。
实现方案:
typescript
// Knowledge base article schema
interface Article {
  id: string;
  slug: string;
  title: string;
  content: string;          // Markdown
  excerpt: string;          // For search results
  category: string;
  subcategory: string;
  tags: string[];
  audience: "customer" | "internal" | "both";
  visibility: "public" | "authenticated" | "internal";
  relatedArticles: string[];
  metadata: {
    createdAt: Date;
    updatedAt: Date;
    author: string;
    reviewedAt: Date | null;
    helpfulVotes: number;
    notHelpfulVotes: number;
    viewCount: number;
  };
}

// Search implementation with vector + full-text hybrid
async function searchKnowledgeBase(
  query: string,
  options?: { category?: string; audience?: string; limit?: number }
): Promise<SearchResult[]> {
  const limit = options?.limit ?? 10;

  // 1. Semantic search (catches paraphrased queries)
  const embedding = await getEmbedding(query);
  const semanticResults = await vectorDb.search({
    vector: embedding,
    filter: {
      audience: options?.audience ?? "customer",
      ...(options?.category && { category: options.category }),
    },
    limit,
  });

  // 2. Full-text search (catches exact terminology)
  const textResults = await db.$queryRaw`
    SELECT id, title, excerpt,
           ts_rank(search_vector, plainto_tsquery('english', ${query})) AS rank
    FROM articles
    WHERE search_vector @@ plainto_tsquery('english', ${query})
      AND audience IN ('customer', 'both')
      ${options?.category ? Prisma.sql`AND category = ${options.category}` : Prisma.empty}
    ORDER BY rank DESC
    LIMIT ${limit}
  `;

  // 3. Merge and deduplicate results
  const merged = mergeSearchResults(semanticResults, textResults);

  // 4. Track search for analytics
  await trackSearch(query, merged.length);

  return merged;
}

// Feedback loop - track article helpfulness
async function rateArticle(
  articleId: string,
  helpful: boolean,
  feedback?: string
): Promise<void> {
  await db.articleFeedback.create({
    data: {
      articleId,
      helpful,
      feedback,
      createdAt: new Date(),
    },
  });

  // Update aggregate counts
  await db.article.update({
    where: { id: articleId },
    data: helpful
      ? { helpfulVotes: { increment: 1 } }
      : { notHelpfulVotes: { increment: 1 } },
  });

  // Flag articles with low helpfulness for review
  const article = await db.article.findUnique({ where: { id: articleId } });
  if (article) {
    const total = article.helpfulVotes + article.notHelpfulVotes;
    const helpfulRate = total > 10 ? article.helpfulVotes / total : 1;

    if (helpfulRate < 0.5 && total > 10) {
      await createReviewTask(articleId, "Low helpfulness score");
    }
  }
}
tsx
// In-app contextual help widget
function HelpWidget({ context }: { context: string }) {
  const [articles, setArticles] = useState<Article[]>([]);
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    // Fetch relevant articles based on current page/feature context
    if (isOpen) {
      searchKnowledgeBase("", { category: context, limit: 5 })
        .then(setArticles);
    }
  }, [isOpen, context]);

  return (
    <div className="help-widget">
      <button
        onClick={() => setIsOpen(!isOpen)}
        aria-label="Help"
        aria-expanded={isOpen}
      >
        ?
      </button>
      {isOpen && (
        <div role="dialog" aria-label="Help articles">
          <SearchInput onSearch={(q) => searchKnowledgeBase(q, { category: context }).then(setArticles)} />
          <ArticleList articles={articles} />
          <a href="/support">Contact support</a>
        </div>
      )}
    </div>
  );
}
设计思路: 混合搜索(语义搜索+全文搜索)既可以处理概念性查询(如“如何分享我的项目?”),也可以处理精确术语查询(如“SSO SAML配置”)。反馈循环可标记出低质量的文章以便改进。上下文帮助无需用户主动搜索即可展示相关文章。

Pattern 2: Support Ticket Integration

模式2:支持工单集成

When to use: Connecting your application to a ticketing system for structured support workflows.
Implementation:
typescript
// Unified support ticket interface (abstracts provider)
interface SupportTicket {
  id: string;
  externalId: string;       // Provider's ticket ID
  subject: string;
  description: string;
  status: "open" | "pending" | "in_progress" | "resolved" | "closed";
  priority: "low" | "normal" | "high" | "urgent";
  category: string;
  tags: string[];
  requester: {
    id: string;
    email: string;
    name: string;
  };
  assignee?: {
    id: string;
    name: string;
    group: string;
  };
  metadata: {
    plan: string;
    accountAge: number;
    mrr: number;            // Monthly recurring revenue
    previousTickets: number;
  };
  createdAt: Date;
  updatedAt: Date;
  firstResponseAt?: Date;
  resolvedAt?: Date;
}

// Auto-triage new tickets with AI classification
async function triageTicket(ticket: SupportTicket): Promise<TriageResult> {
  const classification = await classifyTicket(ticket.subject, ticket.description);

  // Priority escalation rules
  let adjustedPriority = classification.priority;

  // Enterprise customers get elevated priority
  if (ticket.metadata.mrr >= 5000) {
    adjustedPriority = elevate(adjustedPriority);
  }

  // Revenue at risk detection
  if (containsCancellationIntent(ticket.description)) {
    adjustedPriority = "urgent";
    classification.tags.push("churn-risk");
  }

  // Route to appropriate team
  const team = determineTeam(classification.category, adjustedPriority);

  return {
    category: classification.category,
    priority: adjustedPriority,
    team,
    tags: classification.tags,
    suggestedArticles: await findRelatedArticles(ticket.subject),
    autoResponse: classification.confidence > 0.9
      ? generateAutoResponse(classification, ticket)
      : null,
  };
}

// SLA enforcement
interface SLAPolicy {
  priority: string;
  firstResponseMinutes: number;
  resolutionMinutes: number;
}

const SLA_POLICIES: SLAPolicy[] = [
  { priority: "urgent", firstResponseMinutes: 30, resolutionMinutes: 240 },
  { priority: "high", firstResponseMinutes: 120, resolutionMinutes: 480 },
  { priority: "normal", firstResponseMinutes: 480, resolutionMinutes: 1440 },
  { priority: "low", firstResponseMinutes: 1440, resolutionMinutes: 4320 },
];

async function checkSLABreaches(): Promise<SLABreach[]> {
  const openTickets = await getOpenTickets();
  const breaches: SLABreach[] = [];

  for (const ticket of openTickets) {
    const policy = SLA_POLICIES.find((p) => p.priority === ticket.priority);
    if (!policy) continue;

    const now = new Date();
    const age = (now.getTime() - ticket.createdAt.getTime()) / 60000;

    // First response SLA
    if (!ticket.firstResponseAt && age > policy.firstResponseMinutes) {
      breaches.push({
        ticketId: ticket.id,
        type: "first_response",
        minutesOverdue: Math.round(age - policy.firstResponseMinutes),
      });
    }

    // Resolution SLA
    if (!ticket.resolvedAt && age > policy.resolutionMinutes) {
      breaches.push({
        ticketId: ticket.id,
        type: "resolution",
        minutesOverdue: Math.round(age - policy.resolutionMinutes),
      });
    }
  }

  return breaches;
}
Why: AI-powered triage routes tickets to the right team faster, reducing first-response time. Revenue-based priority escalation ensures high-value customers get appropriate attention. SLA monitoring provides accountability and surfaces systemic issues (if a category consistently breaches SLA, it signals a product or documentation gap).

适用场景: 将你的应用与工单系统连接,实现结构化的支持工作流。
实现方案:
typescript
// Unified support ticket interface (abstracts provider)
interface SupportTicket {
  id: string;
  externalId: string;       // Provider's ticket ID
  subject: string;
  description: string;
  status: "open" | "pending" | "in_progress" | "resolved" | "closed";
  priority: "low" | "normal" | "high" | "urgent";
  category: string;
  tags: string[];
  requester: {
    id: string;
    email: string;
    name: string;
  };
  assignee?: {
    id: string;
    name: string;
    group: string;
  };
  metadata: {
    plan: string;
    accountAge: number;
    mrr: number;            // Monthly recurring revenue
    previousTickets: number;
  };
  createdAt: Date;
  updatedAt: Date;
  firstResponseAt?: Date;
  resolvedAt?: Date;
}

// Auto-triage new tickets with AI classification
async function triageTicket(ticket: SupportTicket): Promise<TriageResult> {
  const classification = await classifyTicket(ticket.subject, ticket.description);

  // Priority escalation rules
  let adjustedPriority = classification.priority;

  // Enterprise customers get elevated priority
  if (ticket.metadata.mrr >= 5000) {
    adjustedPriority = elevate(adjustedPriority);
  }

  // Revenue at risk detection
  if (containsCancellationIntent(ticket.description)) {
    adjustedPriority = "urgent";
    classification.tags.push("churn-risk");
  }

  // Route to appropriate team
  const team = determineTeam(classification.category, adjustedPriority);

  return {
    category: classification.category,
    priority: adjustedPriority,
    team,
    tags: classification.tags,
    suggestedArticles: await findRelatedArticles(ticket.subject),
    autoResponse: classification.confidence > 0.9
      ? generateAutoResponse(classification, ticket)
      : null,
  };
}

// SLA enforcement
interface SLAPolicy {
  priority: string;
  firstResponseMinutes: number;
  resolutionMinutes: number;
}

const SLA_POLICIES: SLAPolicy[] = [
  { priority: "urgent", firstResponseMinutes: 30, resolutionMinutes: 240 },
  { priority: "high", firstResponseMinutes: 120, resolutionMinutes: 480 },
  { priority: "normal", firstResponseMinutes: 480, resolutionMinutes: 1440 },
  { priority: "low", firstResponseMinutes: 1440, resolutionMinutes: 4320 },
];

async function checkSLABreaches(): Promise<SLABreach[]> {
  const openTickets = await getOpenTickets();
  const breaches: SLABreach[] = [];

  for (const ticket of openTickets) {
    const policy = SLA_POLICIES.find((p) => p.priority === ticket.priority);
    if (!policy) continue;

    const now = new Date();
    const age = (now.getTime() - ticket.createdAt.getTime()) / 60000;

    // First response SLA
    if (!ticket.firstResponseAt && age > policy.firstResponseMinutes) {
      breaches.push({
        ticketId: ticket.id,
        type: "first_response",
        minutesOverdue: Math.round(age - policy.firstResponseMinutes),
      });
    }

    // Resolution SLA
    if (!ticket.resolvedAt && age > policy.resolutionMinutes) {
      breaches.push({
        ticketId: ticket.id,
        type: "resolution",
        minutesOverdue: Math.round(age - policy.resolutionMinutes),
      });
    }
  }

  return breaches;
}
设计思路: 基于AI的自动分流可将工单更快地分配给合适的团队,缩短首次响应时间。基于收入的优先级升级确保高价值客户获得应有的关注。SLA监控可确保问责制,并发现系统性问题(如果某类工单持续违反SLA,说明存在产品或文档缺口)。

Pattern 3: Customer Health Scoring

模式3客户健康评分

When to use: Proactively identifying at-risk customers before they churn.
Implementation:
typescript
// Health score calculation
interface HealthSignal {
  name: string;
  weight: number;
  score: (customer: Customer) => number; // 0-100
}

const healthSignals: HealthSignal[] = [
  {
    name: "product_usage",
    weight: 0.3,
    score: (c) => {
      const weeklyActive = c.loginDaysLast30 / 30 * 100;
      return Math.min(100, weeklyActive * 1.5);
    },
  },
  {
    name: "feature_adoption",
    weight: 0.2,
    score: (c) => {
      const total = CORE_FEATURES.length;
      const adopted = c.featuresUsed.filter((f) => CORE_FEATURES.includes(f)).length;
      return (adopted / total) * 100;
    },
  },
  {
    name: "support_sentiment",
    weight: 0.15,
    score: (c) => {
      if (c.ticketsLast90Days === 0) return 70; // Neutral
      const resolved = c.resolvedTicketsLast90Days / c.ticketsLast90Days;
      return resolved * 100;
    },
  },
  {
    name: "expansion_signals",
    weight: 0.15,
    score: (c) => {
      const usageGrowth = c.currentMonthUsage / (c.previousMonthUsage || 1);
      if (usageGrowth > 1.2) return 100;
      if (usageGrowth > 1.0) return 70;
      if (usageGrowth > 0.8) return 40;
      return 10;
    },
  },
  {
    name: "payment_health",
    weight: 0.2,
    score: (c) => {
      if (c.failedPaymentsLast90Days > 2) return 20;
      if (c.failedPaymentsLast90Days > 0) return 60;
      return 100;
    },
  },
];

function calculateHealthScore(customer: Customer): {
  score: number;
  status: "healthy" | "at-risk" | "critical";
  signals: Array<{ name: string; score: number; weight: number }>;
} {
  const signals = healthSignals.map((signal) => ({
    name: signal.name,
    score: signal.score(customer),
    weight: signal.weight,
  }));

  const weightedScore = signals.reduce(
    (total, s) => total + s.score * s.weight,
    0
  );

  return {
    score: Math.round(weightedScore),
    status: weightedScore >= 70 ? "healthy" : weightedScore >= 40 ? "at-risk" : "critical",
    signals,
  };
}

// Scheduled job: calculate health scores and alert CSMs
async function updateHealthScores(): Promise<void> {
  const customers = await db.customer.findMany({
    where: { subscriptionStatus: "active" },
    include: { usage: true, tickets: true, payments: true },
  });

  for (const customer of customers) {
    const health = calculateHealthScore(customer);

    await db.customerHealth.upsert({
      where: { customerId: customer.id },
      create: { customerId: customer.id, ...health },
      update: health,
    });

    // Alert CSM for critical customers
    if (health.status === "critical" && customer.mrr >= 1000) {
      await notifyCSM(customer.csmId, {
        customer: customer.name,
        score: health.score,
        signals: health.signals.filter((s) => s.score < 40),
      });
    }
  }
}
Why: Health scoring transforms reactive support (wait for churn) into proactive customer success (intervene before churn). Composite scores combining usage, support sentiment, feature adoption, and payment health give a holistic view. Automated alerts for critical accounts ensure high-value customers get timely CSM attention.

适用场景: 主动识别有流失风险的客户,在他们流失前进行干预。
实现方案:
typescript
// Health score calculation
interface HealthSignal {
  name: string;
  weight: number;
  score: (customer: Customer) => number; // 0-100
}

const healthSignals: HealthSignal[] = [
  {
    name: "product_usage",
    weight: 0.3,
    score: (c) => {
      const weeklyActive = c.loginDaysLast30 / 30 * 100;
      return Math.min(100, weeklyActive * 1.5);
    },
  },
  {
    name: "feature_adoption",
    weight: 0.2,
    score: (c) => {
      const total = CORE_FEATURES.length;
      const adopted = c.featuresUsed.filter((f) => CORE_FEATURES.includes(f)).length;
      return (adopted / total) * 100;
    },
  },
  {
    name: "support_sentiment",
    weight: 0.15,
    score: (c) => {
      if (c.ticketsLast90Days === 0) return 70; // Neutral
      const resolved = c.resolvedTicketsLast90Days / c.ticketsLast90Days;
      return resolved * 100;
    },
  },
  {
    name: "expansion_signals",
    weight: 0.15,
    score: (c) => {
      const usageGrowth = c.currentMonthUsage / (c.previousMonthUsage || 1);
      if (usageGrowth > 1.2) return 100;
      if (usageGrowth > 1.0) return 70;
      if (usageGrowth > 0.8) return 40;
      return 10;
    },
  },
  {
    name: "payment_health",
    weight: 0.2,
    score: (c) => {
      if (c.failedPaymentsLast90Days > 2) return 20;
      if (c.failedPaymentsLast90Days > 0) return 60;
      return 100;
    },
  },
];

function calculateHealthScore(customer: Customer): {
  score: number;
  status: "healthy" | "at-risk" | "critical";
  signals: Array<{ name: string; score: number; weight: number }>;
} {
  const signals = healthSignals.map((signal) => ({
    name: signal.name,
    score: signal.score(customer),
    weight: signal.weight,
  }));

  const weightedScore = signals.reduce(
    (total, s) => total + s.score * s.weight,
    0
  );

  return {
    score: Math.round(weightedScore),
    status: weightedScore >= 70 ? "healthy" : weightedScore >= 40 ? "at-risk" : "critical",
    signals,
  };
}

// Scheduled job: calculate health scores and alert CSMs
async function updateHealthScores(): Promise<void> {
  const customers = await db.customer.findMany({
    where: { subscriptionStatus: "active" },
    include: { usage: true, tickets: true, payments: true },
  });

  for (const customer of customers) {
    const health = calculateHealthScore(customer);

    await db.customerHealth.upsert({
      where: { customerId: customer.id },
      create: { customerId: customer.id, ...health },
      update: health,
    });

    // Alert CSM for critical customers
    if (health.status === "critical" && customer.mrr >= 1000) {
      await notifyCSM(customer.csmId, {
        customer: customer.name,
        score: health.score,
        signals: health.signals.filter((s) => s.score < 40),
      });
    }
  }
}
设计思路: 健康评分将被动支持(等待客户流失)转变为主动客户成功(在客户流失前进行干预)。结合使用情况、支持反馈、功能采用和支付健康状况的综合评分可提供全面的客户视图。针对关键账户的自动提醒确保高价值客户及时获得客户成功经理(CSM)的关注。

Anti-Patterns

反模式

Anti-PatternWhy It's BadBetter Approach
Bot-only support with no human escalationFrustrated customers, churnBot for triage + knowledge, human for resolution
No context passed on escalationCustomer repeats everythingPass full conversation history + account data
Measuring success by tickets closedIncentivizes premature closureMeasure first-contact resolution + customer effort
Knowledge base with no feedback loopStale, unhelpful articles persistTrack helpfulness votes, flag low performers
Same SLA for all customersEnterprise customers get same priority as freeTiered SLAs based on plan and revenue
Support separate from product feedbackMiss patterns that could prevent ticketsTag tickets as product feedback, surface trends

反模式弊端优化方案
仅使用机器人支持,无人工升级通道导致客户不满、流失机器人负责分流+知识库引导,人工负责问题解决
升级时不传递上下文客户需要重复提供信息传递完整的对话历史+账户数据
以关闭工单数量衡量成功会促使过早关闭工单衡量首次联系解决率+客户努力评分
知识库无反馈循环过时、无用的文章持续存在跟踪有用性投票,标记低质量文章
所有客户使用相同SLA企业客户与免费客户优先级相同基于套餐和收入的分层SLA
支持与产品反馈分离错过可减少工单的模式将工单标记为产品反馈,呈现趋势

Checklist

检查清单

  • Knowledge base searchable via hybrid search (semantic + full-text)
  • In-app contextual help widget on key pages
  • Support tickets auto-triaged with AI classification
  • SLA policies defined per priority level
  • SLA breach monitoring with escalation alerts
  • Customer health scores calculated on schedule
  • High-value at-risk customers trigger CSM alerts
  • Full context (conversation + account data) on every escalation
  • Article helpfulness tracked with feedback loop
  • Support trends surfaced to product team monthly

  • 知识库支持混合搜索(语义+全文)
  • 关键页面配备应用内上下文帮助组件
  • 支持工单通过AI分类自动分流
  • 按优先级定义SLA政策
  • SLA违规监控并带有升级提醒
  • 定期计算客户健康评分
  • 高价值风险客户触发CSM提醒
  • 每一次升级都携带完整上下文(对话+账户数据)
  • 跟踪文章有用性并建立反馈循环
  • 每月向产品团队呈现支持趋势

Related Resources

相关资源

  • Skills:
    llm-app-development
    (chatbot RAG),
    product-analytics
    (support funnel analysis)
  • Skills:
    email-systems
    (support notification emails),
    accessibility-a11y
    (accessible help widgets)
  • Rules:
    docs/reference/stacks/react-typescript.md
    (help widget components)
  • 技能:
    llm-app-development
    (聊天机器人RAG)、
    product-analytics
    (支持漏斗分析)
  • 技能:
    email-systems
    (支持通知邮件)、
    accessibility-a11y
    (无障碍帮助组件)
  • 规则:
    docs/reference/stacks/react-typescript.md
    (帮助组件)