Prompt、Skill、MCP 到底该写什么?用一次订单退款任务讲清三层边界

你明明把退款政策写进了 Prompt,又复制到技能文件里,还在 MCP 工具说明中强调了一遍。原以为这是“三重保险”,结果 Agent 换了一个用户,仍引用上笔订单;没有查询订单状态,就直接发起退款;工具明明返回失败,它却回复用户“退款已办理”。

更麻烦的是,运营刚修改一条退款规则,你发现三个地方都要改,而且内容已经悄悄变成了三个版本。

AI 配置不是写得越多越安全,重复指令往往是在制造三个互相打架的真相源。

问题不在模型“够不够聪明”,而在于我们没有分清三层职责:

  • Prompt 管这一次要做什么
  • 技能文件管这类任务通常怎么做
  • MCP 工具说明管外部能力是什么、何时调用、参数怎么传

下面用一条完整的订单退款链路,把这件事讲透。

同一个退款任务,写在三个地方为什么会得到三种结果?

先看一个电商售后中的典型任务:

1. 获取用户订单号;

2. 查询订单状态;

3. 判断退款资格;

4. 满足条件时创建退款;

5. 不满足条件时解释原因或转人工;

6. 根据工具结果生成客服回复。

这是一个很适合观察分层问题的案例:订单号和用户诉求是动态信息,退款规则是稳定流程,查询与退款则依赖外部工具。

实践中最常见的翻车方式,是把整段任务同时塞进三个地方。

Prompt:

用户要退款。请查询订单,判断退款资格,符合条件就退款,

失败则转人工,回复要礼貌。退款政策如下……

Skill:

收到退款请求后查询订单,判断退款资格,符合条件就退款……

当前订单号为 A20250318,用户因为重复购买申请退款……

MCP description:

该工具用于退款。客服应先安抚用户,再查询订单,

按照退款政策判断,符合条件时创建退款,最后使用礼貌语气回复……

表面上,每一层都“写得很完整”,实际上出现了三类冲突:

  • Prompt 每轮重复携带整套流程,浪费上下文;
  • Skill 混入当前订单号,换用户后可能残留旧数据;
  • MCP 描述被客服 SOP 淹没,模型反而看不清工具边界。
图1:错误版执行过程——模型跳过 get_order,直接调用 create_refund;工具拒绝后,最终回复仍声称退款成功。
图中为流程示意,不代表真实平台评测结果。真正需要观察的不是最终回答,而是模型为什么调用、传了什么参数、工具返回了什么。

这种错误很反常识:规则写了三遍,系统却没有更稳定。原因是模型面对的不是“三重保险”,而是三份来源不同、寿命不同、可能互相冲突的指令。

三层各管什么:任务、方法与能力

最容易记住的分法,是把整个 Agent 看成一家餐厅:

  • Prompt 像顾客这次点的菜;
  • Skill 像后厨的标准菜谱;
  • MCP 工具说明像设备操作手册;
  • API 服务端则是燃气阀、门禁和食品安全制度。

你不会把顾客桌号写进永久菜谱,也不会把整套餐厅服务话术印在烤箱说明书上。

| 维度 | Prompt | 技能文件 | MCP 工具说明 | | 核心问题 | 这次做什么 | 这类任务怎么做 | 这个工具怎么用 | | 内容寿命 | 单次会话或短期 | 长期复用 | 随工具版本存在 | | 典型内容 | 用户诉求、临时上下文、输出格式 | SOP、规则、异常分支、示例 | 功能、参数、返回值、调用限制 | | 不该放什么 | 完整长期 SOP | 用户隐私与当次订单数据 | 整套业务流程、客服人设 | | 主要风险 | Token 浪费、指令冲突 | 规则污染、版本过期 | 误选工具、误传参数 |

判断一段内容应该放在哪里,最实用的依据不是文件名,而是信息生命周期

  • 只对当前对话有效:放入 Prompt;
  • 换一批用户仍然成立:放入技能文件;
  • 必须绑定某个具体工具:写入 MCP 工具说明。

不同 Agent 产品对“技能文件”的命名和加载方式可能不同,有的叫 Skill,有的叫 Workflow、Playbook 或 Knowledge,但任务层、流程层、能力层的分工基本不变

放错位置后,六类故障会一起出现

| 症状 | 可能原因 | 修复方向 | | 每轮都输入大段退款流程 | SOP 被塞进 Prompt | 迁移到技能文件 | | 换一个用户仍引用旧订单 | 动态数据写进技能文件 | 移回会话 Prompt | | 模型频繁选错相似工具 | 工具说明缺少调用边界 | 补充适用与禁止场景 | | 工具描述长达数千字 | 业务流程塞进 MCP 说明 | 将流程迁移到 Skill | | 模型声称退款成功,但工具失败 | 技能缺少结果校验规则 | 增加“以工具返回为准” | | 提示词禁止越权,接口却仍能执行 | 把安全控制寄托于自然语言 | 服务端强制鉴权与校验 |

其中最隐蔽的问题是版本分叉

假设退款政策发生变化。如果政策分别存在于 Prompt 模板、Skill 和 MCP 描述中,就需要修改三个位置。只要漏改一个,Agent 就可能在不同入口执行不同规则。

而正确分层后,政策通常只需要修改技能文件;除非接口参数或能力发生变化,否则 MCP 工具定义无需调整。

现场重构:把一坨客服指令拆回正确三层

Prompt:只保留本次任务

用户希望申请订单退款。

本次上下文:

  • order_id: {{order_id}}
  • 用户诉求: {{user_request}}
  • 回复语言: 简体中文
  • 回复风格: 简洁、礼貌,不承诺尚未确认的退款结果

请使用“订单退款处理”技能完成任务。

这里不再重复退款政策和完整操作步骤。Prompt 只回答四件事:谁、什么订单、要解决什么、如何输出。

技能文件:保存稳定 SOP

# 订单退款处理

适用场景

用户询问或申请订单退款。

执行流程

1. 确认订单号是否完整。

2. 查询订单状态。

3. 根据退款政策判断是否符合条件。

4. 符合条件时,征得必要确认后创建退款。

5. 不符合条件时,说明具体原因。

6. 遇到高风险订单、工具失败或政策冲突时转人工。

回复要求

  • 不得在工具返回成功前声称退款已经完成。
  • 不向用户展示内部风控字段。

Skill 负责的是“退款任务通常怎么处理”。即使查询订单的底层接口将来被替换,这套业务流程依然可能成立。

MCP 说明:只描述工具调用契约

查询工具:

{

"name": "get_order",

"description": "根据订单号查询订单当前状态、支付状态和可退款信息。仅用于已有明确订单号的场景;不得猜测订单号。",

"inputSchema": {

"type": "object",

"properties": {

"order_id": {

"type": "string",

"description": "用户提供或系统上下文中已确认的订单号"

}

},

"required": ["order_id"]

}

}

退款工具:

{

"name": "create_refund",

"description": "为符合退款条件的订单创建退款。调用前必须已查询订单,并确认订单当前允许退款。本工具只负责提交退款,不负责判断业务政策。",

"inputSchema": {

"type": "object",

"properties": {

"order_id": {

"type": "string"

},

"reason": {

"type": "string",

"description": "经过确认的退款原因"

}

},

"required": ["order_id", "reason"]

}

}

最后一句非常关键:

工具负责执行,不负责决定业务政策。

否则一旦退款政策变化,你就不得不修改接口描述,把业务版本和工具版本错误地绑在一起。

重构后,模型应该怎样执行?

正确的信息流应该是:

用户请求

Prompt:读取本次订单号、诉求与输出要求

技能文件:采用订单退款 SOP

get_order:查询订单状态与退款资格

技能规则:根据查询结果判断

create_refund:满足条件时提交退款

工具结果:确认成功、失败或待处理

生成客服回复

图2:正确版执行过程——先采用退款技能,再调用 get_order;确认 refundable=true 后调用 create_refund,最终回复与工具返回保持一致。

注意,“调用成功”和“退款到账”也不是一回事。如果工具只返回 submitted,客服只能说“退款申请已提交”,不能擅自升级为“退款已经到账”。

完整架构中,还要再补一层真正的安全边界:

图3:订单退款 Agent 的三层信息流。
用户请求

Prompt:本次目标与上下文

技能文件:选择并执行退款 SOP

MCP 工具说明:发现工具、理解参数与边界

真实 API:鉴权、校验、执行

工具结果

生成客服回复

MCP 说明不是安全边界。权限、退款金额、订单归属和订单状态,必须由 API 服务端强制校验。

自然语言可以告诉模型“不要越权”,却不能阻止攻击者绕过模型直接请求接口。

不要凭感觉:用同一批请求做小型对照测试

为了避免虚构胜率,可以准备一组 24 条客服请求,按六类场景各取四条:

  • 正常可退款;
  • 已退款或退款处理中;
  • 缺少订单号;
  • 不符合退款条件;
  • 工具返回失败;
  • 疑似越权或订单归属不一致。

建立三组配置:

  • A:所有内容集中写在 Prompt;
  • B:业务流程塞进 MCP 描述;
  • C:按 Prompt、Skill、MCP 正确分层。

测试时固定模型版本、温度、工具集合与样本顺序,逐条记录:

| 指标 | 记录方法 | | 正确工具选择率 | 是否先选择了符合场景的工具 | | 参数一次填写正确率 | 首次调用是否包含全部必填参数 | | 条件不满足时误调用率 | 不可退款场景是否调用了退款工具 | | 回复与工具结果一致率 | 最终措辞是否忠于工具返回 | | 平均输入 Token | 由调用日志记录 | | 政策变更改动位置数 | 修改一次规则需要编辑几个文件 |

本文不填入未经实际运行的“漂亮数字”。你可以将模型名称、版本、温度、24 条逐项结果和原始日志一起保存,避免把一次偶然成功包装成普遍结论。

想验证分层是否有效,最好的方法不是继续争论定义,而是让同一测试集在不同模型上跑一遍。你可以把文中的 Prompt、技能文件和 MCP 定义保存为固定配置,通过 api.884819.xyz 接入模型,记录工具选择、参数错误、Token 消耗和回复一致性。

平台使用用户名和密码即可注册,无需邮箱验证;内置 AI 对话,注册后可以直接使用。国产模型如 Deepseek、千问等完全免费,没有月租和订阅,其他模型按量付费。

新用户注册即送体验token。

建议同时保存一份自己的“退款客服测试包”:

  • Prompt 模板;
  • 技能文件示例;
  • 两个 MCP 工具定义;
  • 24—30 条客服测试问题;
  • 模型配置与评测记录表。

四问法:一段内容究竟应该放在哪?

以后遇到任何 Agent 配置,先问四个问题:

1. 换一个用户,这段内容还成立吗?

不成立,通常属于 Prompt。

2. 换一个工具,这段流程还成立吗?

成立,通常属于技能文件。

3. 不调用外部工具,这条规则还需要吗?

需要,通常是业务规则,而不是 MCP 描述。

4. 它描述的是目标、方法,还是接口能力?

目标进 Prompt,方法进 Skill,接口能力进 MCP。

最终可以压缩成一条迁移规则:

动态上下文进入 Prompt,稳定 SOP 进入技能文件,参数与能力边界进入 MCP;权限与最终业务校验留在服务端。

Prompt 工程的终点,从来不是写出一个包罗万象的“超级提示词”,而是为不同信息建立清晰的职责、版本和唯一真相源。

Prompt 负责下任务,Skill 负责教方法,MCP 负责报能力,API 负责守底线。

但位置分清后,还有一个更棘手的问题:如果退款政策已经更新,Skill 仍是旧版本,而工具返回又与 Prompt 预期冲突,模型究竟应该听谁的?

下一篇,我们将通过一次“新政策、旧 Skill、真实工具结果互相打架”的事故,拆解 Agent 的指令优先级、版本管理与冲突处理。

下一篇:《Prompt、Skill 和工具结果互相打架时,AI 应该听谁的?一文讲清 Agent 的指令优先级》 本文由8848AI原创,转载请注明出处。关注8848AI,带你从零开始学AI。

#Prompt技巧 #MCP #AISkills #Agent开发 #AI客服 #人工智能 #8848AI