CCA-F 真题精讲:用 Agent SDK 设计客服 Agent(升级逻辑是拿分关键)
CCA-F 真题精讲:用 Agent SDK 设计客服 Agent(升级逻辑是拿分关键)
这道题考的不是写代码,是判断什么时候该让 Agent 停手。
Customer Support Resolution Agent 是 CCA-F(Claude Certified Architect Foundations)考试的六大场景之一,也是出现频率最高的场景。它把五个知识域全串起来考:Agentic loop、MCP 工具集成、升级逻辑、上下文管理、Human-in-the-loop。
题目原文大意:
Customer Support Resolution Agent 设计一个客服 Agent,处理用户咨询、解决问题,并在复杂情况下升级给人工。考核点:Agent SDK、MCP 工具、升级逻辑(escalation logic)。
很多人答这道题栽在同一个地方:把重点放在「怎么让 Agent 解决问题」,忽略了怎么让 Agent 知道自己该升级。CCA-F 的评分核心恰恰是后者。下面按 Exam Guide 的考点逐层拆解。
本文提纲
- 这道题到底在考什么
- 第一层:Agentic Loop 设计
- 第二层:MCP 工具的边界设计
- 第三层:升级逻辑(escalation)—— 拿分关键
- 完整代码实现
- 容易丢分的三个陷阱
- 一句话答案
这道题到底在考什么
对照 Exam Guide 的五大知识域权重,这道题的得分分布大致是:
| 考点 | 对应 Domain | 权重 | 这题占分 |
|---|---|---|---|
| Agentic loop 设计 | Domain 1 (27%) | 高 | 核心 |
| 工具接口与边界 | Domain 2 (18%) | 高 | 核心 |
| 何时升级人工 | Domain 1 + 5 | 高 | 拉分项 |
| MCP server 集成 | Domain 2 | 中 | 区分项 |
| 上下文与会话状态 | Domain 5 (15%) | 中 | 加分项 |
| Human-in-the-loop | Domain 5 | 中 | 加分项 |
Exam Guide 对这个场景的原话是:Agent 必须知道何时使用工具、何时升级给人工(knows when to use a tool versus when to escalate to a human)。注意是「versus」——这是个二选一的判断,不是「先试工具再升级」的默认流程。
三个明确的升级触发器(escalation triggers),Exam Guide 列得很死:
- 策略上限超出(policy limits exceeded)——比如退款超过 $50 自动限额
- 客户主动要求(customer request)——客户说「我要找人工」
- 无法推进(inability to make progress)——Agent 试了几轮没解决问题
记住这三个,代码里要显式实现,不能靠模型自己判断。
第一层:Agentic Loop 设计
客服 Agent 的核心是一个自主执行的循环:理解用户意图 → 选工具 → 执行 → 观察结果 → 决定下一步(继续/升级/完成)。用 Claude Agent SDK 实现这个循环是 Domain 1 的核心考核点。
设计 loop 时有两条 Exam Guide 强调的原则:
第一,循环要有明确的终止条件。不能是无限循环「一直试到成功」。每一轮要带最大尝试次数,超过就升级。无限循环是 Agent 系统的头号生产事故。
第二,工具调用要可观测、可拦截。Agent SDK 的 hooks 机制让你在每次工具调用前后插入逻辑——记日志、做审计、强制参数校验。客服场景涉及退款、改账户这些敏感操作,必须可审计。
from claude_agent_sdk import Agent, tool
# 客服 Agent 的 agentic loop
@tool
def check_order_status(order_id: str) -> dict:
"""Check the status of a customer order.
Use when: customer asks about order status, shipping, or delivery.
Do NOT use when: customer wants to cancel (use cancel_order instead).
"""
# 查订单系统(通常通过 MCP server 暴露)
return {"order_id": order_id, "status": "shipped", "eta": "2 days"}
@tool
def issue_refund(order_id: str, amount: float) -> dict:
"""Issue a refund for an order.
Use when: customer requests a refund AND amount <= 50.0.
HARD LIMIT: refuses any refund above $50 automatically.
For amounts above $50, the agent MUST escalate to human.
"""
if amount > 50.0:
return {"error": "REFUND_LIMIT_EXCEEDED", "max_auto": 50.0}
# 执行退款
return {"order_id": order_id, "refunded": amount, "status": "done"}
@tool
def escalate_to_human(reason: str, summary: str) -> dict:
"""Hand the conversation to a human agent.
Use when: ANY of these is true:
- policy limit exceeded (e.g. refund > $50)
- customer explicitly requests human
- agent made 3+ attempts without resolution
"""
return {"escalated": True, "ticket_id": "TKT-7821", "reason": reason}
agent = Agent(
model="claude-sonnet-4-5",
tools=[check_order_status, issue_refund, escalate_to_human],
max_turns=10, # 明确的循环上限,超过由兜底逻辑处理
)注意每个工具的 docstring。Exam Guide 反复强调:工具描述要写清「何时用」和「何时不用」,而不是只写功能。上面的 issue_refund 明确写了 amount <= 50.0 才用,超过就升级——这就是工具边界。
第二层:MCP 工具的边界设计
真实客服系统里,订单、退款、账户这些数据在后端系统,Agent 通过 MCP(Model Context Protocol)server 访问它们。Domain 2 考你怎么设计和集成这些工具。
graph TB
A[Customer Support Agent] --> B[MCP Server: Billing]
A --> C[MCP Server: Orders]
A --> D[MCP Server: CRM]
A --> E[Escalation Tool: Human Queue]
B --> F[(Billing DB)]
C --> G[(Order System)]
D --> H[(Customer Profile)]
E --> I[Human Agent Dashboard]
style A fill:#FF6B6B,color:#000000
style E fill:#DDA0DD,color:#000000
style B fill:#4ECDC4,color:#000000
style C fill:#45B7D1,color:#000000
style D fill:#96CEB4,color:#000000MCP 工具设计有四个 Exam Guide 划重点的要求:
结构化错误响应。工具出错不能返回模糊的字符串,要返回带错误类别和可重试标志的结构体。比如退款超限返回 {"error": "REFUND_LIMIT_EXCEEDED", "max_auto": 50.0, "retryable": false},Agent 一看就知道这不是临时故障,是硬限制,该升级而不是重试。
跨 Agent 的工具权限分配。一个客服 Agent 不该有删账户的权限。最小权限原则——给 Agent 的工具集要精确匹配它的职责边界。
工具描述要区分相似工具。cancel_order 和 issue_refund 都涉及订单,描述必须写清触发条件,否则模型会选错。上面代码里 check_order_status 明确写了「不要用于取消订单」,就是在防这个。
MCP server 集成进 Agent loop。不是把 MCP 当独立服务调,而是把它的工具注册进 Agent SDK 的 tools 列表,让 Agent 在 loop 里自主选择调用。
第三层:升级逻辑(escalation)—— 拿分关键
这是这道题真正拉分的地方。大多数人能写出 loop 和工具,但升级逻辑写得含糊。Exam Guide 要的是显式、可判定、有触发器的升级,不是「Agent 觉得搞不定就升级」这种黑盒。
def run_support_loop(agent, user_message: str, history: list):
attempts = 0
MAX_ATTEMPTS = 3 # 无法推进的硬阈值
while attempts < MAX_ATTEMPTS:
result = agent.run(user_message, history=history)
# 触发器 1:客户主动要求人工
if "escalate" in result.tool_calls:
return {"outcome": "escalated", "reason": "customer_request"}
# 触发器 2:策略上限超出(工具返回硬限制错误)
for call in result.tool_calls:
if call.result.get("error") == "REFUND_LIMIT_EXCEEDED":
agent.run_tool(escalate_to_human,
reason="refund_limit_exceeded",
summary=result.summary)
return {"outcome": "escalated", "reason": "policy_limit"}
# 触发器 3:问题已解决
if result.is_complete:
return {"outcome": "resolved", "answer": result.answer}
attempts += 1
history.append(result)
# 触发器 4:达到最大尝试次数仍无进展
agent.run_tool(escalate_to_human,
reason="max_attempts_exceeded",
summary="Agent tried 3 times without resolution")
return {"outcome": "escalated", "reason": "no_progress"}这段代码把 Exam Guide 的三个升级触发器全部显式实现,外加一个「最大尝试次数」的兜底。考官看到这种确定性升级逻辑,会判定你理解了 Agent 的局限性边界——这正是 CCA-F 想区分「会用工具」和「会设计安全系统」的分水岭。
升级时还有两个细节别丢分:
升级要带上下文摘要。把 escalate_to_human 的 summary 参数填满——之前的对话、已尝试的方案、为什么失败。人工接手时不用重新问一遍客户。这考的是 Domain 5 的上下文管理。
升级是终态,不是分支。一旦决定升级,Agent 不应该再继续尝试。升级后 loop 必须终止,把控制权完全交给人工。很多人写成「升级的同时继续跑」,这是错的。
完整代码实现
把三层合起来,一个符合 CCA-F 标准的客服 Agent 完整骨架:
from claude_agent_sdk import Agent, tool, hook
SYSTEM_PROMPT = """You are a customer support agent.
Resolve customer issues using the provided tools.
You MUST escalate to a human when:
1. A refund request exceeds $50 (policy limit)
2. The customer explicitly asks for a human agent
3. You cannot resolve the issue after 3 attempts
Never attempt workarounds for policy limits. Never promise
refunds above $50 without human approval."""
@hook(event="before_tool_call")
def audit_sensitive_calls(call):
"""Log every refund and account change for compliance audit."""
if call.tool_name in ("issue_refund", "update_account"):
audit_log.record(call.tool_name, call.params, call.timestamp)
return call # 放行
agent = Agent(
model="claude-sonnet-4-5",
system_prompt=SYSTEM_PROMPT,
tools=[
check_order_status, # MCP: order system
issue_refund, # MCP: billing, $50 hard limit
update_account, # MCP: CRM, scoped permissions
escalate_to_human, # native: human queue
],
hooks=[audit_sensitive_calls],
max_turns=10,
)
# 运行时
result = run_support_loop(agent, user_message, history=[])四个值得注意的设计:
system prompt 里写死升级规则。不是指望模型从工具描述里推断,而是用系统提示明确告知三条升级规则。这是 Domain 4(Prompt Engineering)的考点——高风险判断要在 system prompt 里固化。
hook 做合规审计。退款和账户修改这类操作,每次调用都记审计日志。这是企业级 Agent 的标配,Exam Guide 在 Domain 5(可靠性)里强调可观测性。
工具来源混合。check_order_status 等来自 MCP server(访问后端系统),escalate_to_human 是 native 工具(Agent SDK 内置的队列)。混合来源是真实场景,考的是你对 MCP 和 native tool 的边界理解。
max_turns 作为最后防线。即使升级逻辑有 bug,循环也不会无限跑。这是防御性设计——任何 Agent 系统都该有硬上限。
容易丢分的三个陷阱
陷阱一:把升级写成「最后手段」。错误写法是「Agent 先尽力解决,实在不行再升级」。正确写法是升级有明确触发器,命中触发器立即升级,不分先后。退款超过 $50 不是「最后手段」,是「第一响应」。
陷阱二:工具没有硬边界。错误做法是让 issue_refund 接受任意金额,靠 system prompt 提醒模型别退太多。正确做法是工具内部校验,超过限额直接返回错误。模型会犯错,代码不会。
陷阱三:升级不带上下文。错误做法是只传个 reason 字符串。正确做法是带上完整摘要——客户问题、已尝试方案、失败原因。考官在看你是否理解「人工接手」的成本。
一句话答案
设计一个基于 Claude Agent SDK 的客服 Agent,agentic loop 内集成 MCP 工具访问订单/计费/CRM 系统;每个工具带明确使用边界和硬限额(如退款 $50 上限);显式实现三类升级触发器——策略上限超出、客户主动要求、无法推进——命中即终止 loop 并带上下文摘要转人工;敏感操作通过 hook 做合规审计,循环设 max_turns 硬上限作为最后防线。
把这段话和上面的代码骨架记住,这道场景题基本稳拿。核心不是代码多漂亮,而是让考官看到你理解 Agent 的能力边界在哪,以及怎么用确定性逻辑守住那条边界。
参考文档与链接
- CCA-F Exam Guide — 官方考试指南,含五大知识域、六大场景、升级触发器定义
- CCA-F 官方课程 — 系统学习 Customer Support Resolution Agent 等场景
- The Claude Certified Architect Exam: 5 Domains, 6 Scenarios 全解 — dev.to 六大场景详解,含本场景升级逻辑要点
- Mastering the Customer Support Resolution Agent Scenario — Towards AI 针对本场景的深度备考
- Claude Agent SDK 文档 — Agent loop、tools、hooks 的官方 API
- Model Context Protocol 文档 — MCP server 设计与集成规范
- TheAIEra AI 认证页 — CCA-F 备考资源与考试指南汇总
- CCA-F 社区题库 — 150+ 道模拟题,含客服场景实战
备考 CCA-F 的,这道客服 Agent 场景题的升级逻辑你掌握了吗?评论区说说你的解法,有疑问我来答疑。觉得有用点个赞让更多备考的人看到。
作者: itech001 来源: 公众号:AI人工智能时代 网站: https://www.theaiera.cn/ 每日分享最前沿的AI新闻资讯和技术研究。
本文首发于 AI人工智能时代,转载请注明出处。