Skip to content

Chapter 19 · Capstone 1: Production-Grade Smart Customer Service Agent ​

Chapter goals: Synthesize everything learned in Chapters 1–18 to build an e-commerce after-sales customer service Agent from scratch — intent routing, order query, return-policy RAG Q&A, human transfer, and session memory; land the three production red lines (cost tiered routing, credential safety, eval closed-loop) during construction, not as事后补课.

19.1 Requirements and Architecture ​

Define the business边界 first. This customer service Agent only handles four after-sales scenarios:

RequirementCapabilityChapter
Chat / simple Q&A fast replyCheap small-model triagech08 branch
Query order statusqueryOrder toolch05 createTool
Return-policy RAG Q&ARAG retrieval of policy docsch12
Agitated user / over-权限 requestWorkflow suspend → human handoffch09

Overall architecture — intent routing is the总闸门 for cost and quality:

text
User message
   │
   ▼
┌──────────────────┐   Simple/chat (~70% traffic)
│  Intent triage   │──────────────▶ gpt-5-mini direct reply
│  (gpt-5-mini)    │
└───────┬──────────┘
        │ Business question (order / return-policy)
        ▼
┌─────────────────────────────────┐
│  expertAgent (claude-sonnet)    │
│  ├─ queryOrder tool ──▶ order DB │
│  ├─ RAG policy retrieval ──▶ vector store │
│  └─ Memory (user-isolated sessions) │
└───────┬─────────────────────────┘
        │ Agitated / beyond refund权限
        ▼
   workflow.suspend() ──▶ human agent takes over

The one design主线: let the cheap model handle what it can应付, save the expensive model for where itcounts.

19.2 Project Scaffold and Model Tiered Routing ​

Reuse the Chapter 1 scaffold; add directory structure:

bash
npm install @mastra/core @mastra/libsql @mastra/memory zod
mkdir -p src/mastra/{agents,tools,workflows}

Write two tier agents. Follow the Chapter 4 three-principles (define role, draw boundaries, give format):

typescript
// src/mastra/agents/triage-agent.ts —— Front-line triage: cheap modelhandles most traffic
import { Agent } from '@mastra/core/agent';

export const triageAgent = new Agent({
  id: 'triage',
  name: 'Triage',
  instructions: `
You are the first reception for e-commerce after-sales. Responsibilities:
- Judge user intent: casual chat / order query / return-policy inquiry / complaint
- For casual chat and simple common questions, answer in one sentence directly
- For requests involving a specific order or policy, output "transfer" with a summary of the original request
Always use Chinese; replies under 80 characters.`,
  // Cheap tier: intent recognition does not need a flagship model
  model: 'openai/gpt-5-mini',
});
typescript
// src/mastra/agents/expert-agent.ts —— Expert seat: only消耗 the high-capability model when needed
import { Agent } from '@mastra/core/agent';

export const expertAgent = new Agent({
  id: 'expert',
  name: 'Support Expert',
  instructions: `
You are a senior after-sales specialist handling order queries and return-policy inquiries.
Rules:
- When answering policy questions, you must rely on the provided policy materials; never fabricate clauses
- Before querying an order, you must have a valid order ID
- If the user is agitated or requests exceed standard policy, reply "I will transfer you to a human agent"
Always use Chinese.`,
  // High-capability tier: tool calls + policy reasoning
  model: 'anthropic/claude-sonnet-4-5',
});

Wire them into a分流主干 with the workflow branch() syntax (Chapter 8):

typescript
// src/mastra/workflows/support-router.ts —— Intent分流主干
import { createStep, createWorkflow } from '@mastra/core/workflows';
import { z } from 'zod';

const classifyStep = createStep({
  id: 'classify',
  inputSchema: z.object({ message: z.string(), userId: z.string() }),
  outputSchema: z.object({ simple: z.boolean(), message: z.string(), userId: z.string() }),
  execute: async ({ inputData, mastra }) => {
    // Let the cheap小模型 judge whether this is a simple question
    const res = await mastra.getAgent('triage').generate(inputData.message);
    const simple = !res.text.includes('transfer');
    return { simple, message: inputData.message, userId: inputData.userId };
  },
});

export const supportFlow = createWorkflow({
  id: 'support-router',
  inputSchema: z.object({ message: z.string(), userId: z.string() }),
  outputSchema: z.object({ answer: z.string() }),
})
  .then(classifyStep)
  .branch([
    // Simple question: use the triage answer (already cached in classify)
    [async ({ inputData }) => inputData.simple, answerSimpleStep],
    // Business question: hand off to the expert seat for the full tool + RAG pipeline
    [async () => true, expertAnswerStep],
  ])
  .commit();

Cost benefit

In typical e-commerce customer service traffic, ~70% is casual chat and common questions. The全量 flagship-model bill通常 drops to under one-third after分流.

19.3 Order Query Tool and Policy RAG ​

The expert seat needs two weapons: an order查询 tool and policy RAG retrieval.

typescript
// src/mastra/tools/query-order.ts —— Order query tool:连模拟 database
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';

// Demo mock data; replace with a real order service API in production
const mockOrderDb: Record<string, { status: string; amount: number; item: string }> = {
  'SO-2026-0001': { status: 'Shipped', amount: 299, item: 'Wireless Earbuds' },
  'SO-2026-0002': { status: 'Pending Payment', amount: 1299, item: 'Mechanical Keyboard' },
};

export const queryOrderTool = createTool({
  id: 'query-order',
  description: 'Query order status, amount, and item by order ID. Call only when the user provides an order ID.',
  inputSchema: z.object({
    orderId: z.string().regex(/^SO-\d{4}-\d{4}$/, 'Order ID format: SO-2026-0001'),
  }),
  outputSchema: z.object({
    found: z.boolean(),
    status: z.string().optional(),
    amount: z.number().optional(),
    item: z.string().optional(),
  }),
  execute: async ({ inputData }) => {
    // Least-privilege: read-only here; never expose write credentials
    const order = mockOrderDb[inputData.orderId];
    if (!order) return { found: false };
    return { found: true, ...order };
  },
});

The policy RAG pipeline follows Chapter 12: chunk the return-policy Markdown docs, embed, store in LibSQL, retrieve on query, inject into the expert agent's context.

19.4 Production Red Lines Landed During Construction ​

Red Line 1: Cost Tiered Routing ​

The triage→expert branch结构 ensures ~70% of traffic never touches the expensive model. Verified by comparing crew.usage_metrics-equivalent stats before and after分流.

Red Line 2: Credential Safety ​

API keys flow exclusively through .env + process.env; no硬编码. The queryOrderTool is read-only — no write credentials are ever exposed to the agent.

Red Line 3: Evals Closed-Loop ​

Chapter 15's Scorers are mounted on the expert agent: answerRelevancy (权重 0.7) + toxicity (权重 0.3). A CI job runs a regression batch on each PR; scores below threshold fail the build.

19.5 Human Transfer via Suspend ​

When the expert agent detects an agitated user or an over-权限 request, the workflow suspends:

typescript
const handoffStep = createStep({
  id: 'handoff',
  inputSchema: z.object({ userId: z.string(), issue: z.string() }),
  outputSchema: z.object({ transferred: z.boolean() }),
  execute: async ({ inputData, suspend }) => {
    await suspend({
      message: `User ${inputData.userId} requires human handoff: ${inputData.issue}`,
    });
    return { transferred: false }; // Only reached if not suspended
  },
});

The suspended run persists to Storage; a human agent resumes with run.resume({ resumeData: { resolved: true } }).

19.6 Chapter Summary ​

  • Architecture: triage (cheap) → branch → expert (expensive) with tools + RAG + memory;
  • Cost tiered routing lands the #1 production red line during design, not after;
  • Order query tool follows least-privilege (read-only, validated input);
  • Policy RAG injects authoritative knowledge without hallucination;
  • Human transfer via workflow suspend + Storage persistence;
  • Evals mounted on the expert agent with CI regression gates.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What percentage of typical e-commerce customer service traffic should the cheap triage model handle?

2. Why is the order query tool designed as read-only?

3. What triggers a workflow suspend in this capstone?

4. How is the evals closed-loop landed in this capstone?

🛠️ Hands-On Exercises ​

  1. Build the full capstone: triage agent → branch → expert agent with queryOrder tool + RAG policy retrieval + Memory. Verify the分流 saves ~70% token cost.
  2. Add a suspension point for over-权限 requests; verify the workflow persists and can be resumed by a human.
  3. Mount eval scorers on the expert agent; run a CI regression batch and verify the build fails when scores drop.

Capstone 1 complete. Next: Capstone 2: Full-Stack AI App.