Skip to main content

Skills设计:业务SOP拆成按需加载的手册

上一篇开头那句“刚买的手机我不想要了,还没发货的话帮我取消”,当时是拿来讲确认规则的示例。这次在本机把它真跑了一遍。2026-10-08,用admin账号对比特严选Agent说:

那台iPhone 18 Pro Max我不想要了,还没发货吧?帮我取消

一轮跑完,会话上下文里是六条消息:

序号角色内容
1USER用户那句话
2ASSISTANT思考 + 调用load_skill,参数skill_code: order_change
3TOOLload_skill的结果:一份“订单变更”办理手册
4ASSISTANT思考 + 调用query_order,不带参数
5TOOL最近5笔订单,其中88239是iPhone 18 Pro Max 512GB,已支付待发货
6ASSISTANT思考 + 调用cancel_order,参数orderNo: 88239,停在确认卡

要注意的是第2条。模型第一步没有去查订单,而是先取了一份手册。它的思考原话是英文的:

The rule: 用户要取消订单 → load order_change skill. Let me load the skill first, then follow it.

拿到手册之后,它才按手册第1步查订单,从五笔里认出88239,再按第5步发起取消。确认卡上我点了取消,订单现在还是已支付待发货。

“先查订单拿状态”“四个状态四条路”“取消前说清会发生什么”,这些规则不在人设里,也不在工具描述里。它们写在一份只有办取消改址这件事时才会被读到的文本里。这一篇讲的就是这份文本:它为什么不直接写进人设,它和工具的区别在哪,一份手册怎么写模型才用得起来,清单和正文各从哪来,以及它进了上下文之后会怎样。

上一篇定的是cancel_order执行前要不要用户点头。点头之前,模型怎么知道该先查什么、什么状态下能办,是本篇的事。两件事各管一段,谁也替代不了谁。

办事规则全写进人设会怎样​

1. 比特严选有五件要按流程办的事​

序章分过级:一星任务一次工具调用就完事,二星以上才用得着循环。其中三星和四星的任务,每一类都有一套固定的办理顺序:

  • 退换货按签收天数分三档,第8到15天只收质量问题
  • 取消和改地址按订单状态分四条路,已发货的不能取消只能拒收
  • 故障诊断一次只给一步,等用户反馈再定下一步
  • 下单先试算券、逐项列清,用户确认后才建单,建单和付款是两步
  • 全家桶先定主设备再配周边,手表必须配iPhone,表带按表壳尺寸分档

这些就是业务SOP(Standard Operating Procedure,标准作业程序)。比特严选数据集里把它们写成了五份手册,正文是Markdown,初始化器从resources/initializer/bit-selection/skills/播进库里:

技能标识名称对应任务正文字符数
after_sale_apply退换货办理T31,012
order_change订单变更T10822
fault_diagnosis故障诊断T8823
order_checkout选购下单T111,386
iot_bundle多设备搭配T71,184

字符数按库里t_agent_skill.content的长度数的,五份合计5,227。后续可能会继续扩展其他的Skill。

2. 都写进人设,每次调用都带着用不上的流程​

最直接的放法是把五段流程全写进人设。人设是管理端配的那份系统提示词,每次模型调用都排在消息列表最前面,第一章讲提示词那篇展开过。比特严选的人设现在约2,200字符,五份手册塞进去,长度翻三倍还多,而且手册只会越写越多。

长本身不是主要问题,前缀缓存能把每轮重复的那段按折扣计价。问题出在三处:

  • 每次调用都带着四份和这一轮无关的流程。排查手册写“一次只让用户做一步”,下单手册写“下单前逐项列清”,退换货手册写“照样提交,让工具给判定”。五套规则摆在同一份提示词里,模型每轮要自己从里面挑出当前适用的那一段。办取消的时候旁边躺着排查手册的“一次只给一步”,模型容易把别的场景的规则套到当前任务上。
  • 改一条退货步骤要改人设。ReActAgentProvider每次取Agent时会比对人设文本,不相等就重建Agent实例。手册拆出去之后改正文不重建,下文讲指纹时会看到为什么。
  • 人设是所有场景共用的一份。“身份”“工具选择”“结果处理”这些真正每轮都要看的规则,被五类事的细节稀释了。

手册只有一两份、每份几行的时候,写进人设也能用。拆出去的收益随手册数量涨。

Ragent的做法是把每类事的流程单独存成一份手册,人设里只留“什么时候该去取手册”的判据,模型判断当前任务对得上哪份手册,才把那一份取进上下文。

手册和工具各管什么​

1. 手册告诉模型怎么办,工具替模型办​

工具是序章定义过的东西:入参出参固定,替模型做一件事。cancel_order收到订单号,真的去改订单状态、回补库存、退券。

手册只是一段文本。它进了上下文,模型照着做,手册自己不碰任何数据。两者摆在一起:

工具手册
谁执行MCP Server上的代码模型自己
改不改业务数据写工具会改不改
以什么形式进模型输入工具schema:名字、描述、参数定义一段文本
什么时候在模型输入里每次调用都在加载之后才在
模型不照办怎么办服务端校验、执行前确认手册自己没有兜底,靠的还是工具那一列

最后一行要单独说。手册管不住执行,所以手册里一再把判断权往工具那边推。订单变更手册“系统的硬约束”第一条:

能不能取消、能不能改,由工具按库里的实时状态判定,不要拿几轮之前查到的状态下结论

这和序章定退货三档时的口径是同一件事:模型算出来的天数、模型记得的状态,一律不作数,判据在服务端现算。

开头那次实跑正好给了一个“模型不照办”的样本。当时手册第3步写的是“取消前把这单会一起发生的事说清楚:库存回补、用掉的券退回、已支付的原路退款”。模型的思考里看见了这一条:

Per manual step 3: explain what will happen — 库存回补、用掉的券退回、已支付原路退款. Then cancel. … But user explicitly asked to cancel, so I should just do it and report.

它判断用户已经说了要取消,跳过第3步直接提交。拦下它的不是手册,是前面讲执行前确认时那张确认卡;我点了取消之后,它的下一条回复才把三件事补上。

这件事划出了手册的边界。手册能提高模型按流程办的概率,不能保证。有代码把关的两道关卡也管不到这一步:确认卡只保证提交前要用户点头,服务端只按实时状态判断能不能办,谁都不看模型有没有先把退款、退券、回补库存讲给用户。所以“取消前先讲清楚”能不能做到,取决于手册和人设的文字写得够不够明确。出问题之后把这两处文字的提示词都改了,改成什么样,下面讲一份手册怎么写的时候说。

当然上面这个模型思考和模型会有关系,项目跑测试时用的deepseek-flash,使用GPT时就没有问题。

2. 两份不解锁任何工具的手册​

看到手册和cancel_order成对出现,容易把手册理解成工具的使用说明。五份手册里有两份没有绑任何工具。故障诊断手册的声明文件是这样的:

# tool-ids 故意留空:这份手册解锁的不是工具而是流程——没有它模型会一次抛五条排查建议,多轮诊断塌成一轮
skill-code=fault_diagnosis
name=故障诊断
description=用户报告设备故障、异常或错误码,需要一步步排查时用这个技能;只问功能用法与参数的,不用加载
content-file=skills/fault-diagnosis.md
tool-ids=
sort-order=2
enabled=true

多设备搭配手册同样留空,理由也写在注释里:“搭配流程(先主设备后周边、手表必须配手机)提示词里一个字都没有,手册的价值在流程本身,不在解锁工具”。

效果在第二章讲裁剪那篇的八轮会话里能看到。用户说AirPods Pro左耳没声,第一轮模型加载了fault_diagnosis,给第一步之前的思考是“按手册,一次只让用户做一步”,之后两轮用户回来说没好,模型没有再查资料,接着往下排查。手册在那个会话里没有解锁任何工具,它改变的是模型组织回答的方式。

另外三份有值的tool-ids,含义是“加载这份手册之后才解锁的工具”:没加载的时候,模型的工具清单里看不见cancel_order。为什么要藏、怎么藏、什么时候收回,是后面讲加载技能前后工具清单怎么变的那篇的内容,本篇只定义到这里。

一份手册怎么写​

1. 四段结构:什么时候用、办事步骤、怎么填、硬约束​

把开头那份订单变更手册整段贴出来,库里现在是什么样就是什么样,822字符:

## 什么时候用
用户要取消订单或改收货信息时,按本手册办。
只问「多久不付款会自动取消」「发货后还能不能改地址」这类规则,走知识库,不用本手册。

## 办事步骤
1. 先用 query_order 确认是哪一单,拿到当前状态。用户只说「刚才那单」时,列最近几笔让他确认
2. 按状态分流,四个状态四条路:
- 待支付:能取消,也能改收货信息
- 已支付待发货:能取消(原路退款),也能改收货信息
- 已发货:两件都办不了。取消改成建议拒收,拒收后自动退款;改地址改成建议联系快递改派
- 已签收或已取消:两件都办不了。已签收要退就走售后申请,已取消不用再取消一次
3. 取消前先把这单会一起发生的事讲给用户:用掉的券退回、已支付的原路退款、库存回补。这段话写在发起 cancel_order 的那条回复正文里、放在调用之前,不能等提交结果出来再补;用户一上来就明确要取消,也照样先讲
4. 改地址前把要改的项和改成什么当场列出来,让用户确认无误再提交
5. 用 cancel_order 或 change_address 提交,把结果如实回给用户

## 这几项怎么填
- 订单号取自 query_order 的返回值,不要凭对话内容拼
- change_address 的收货人、手机号、地址三项,用户没说要改的就不要传:传了就会覆盖原值
- 订单查询返回的手机号是打码的,不要拿打码值当原值回填进去
- 地址要完整到门牌号,用户只说「换到公司」这类不完整信息时问清楚再提交

## 系统的硬约束
- 能不能取消、能不能改,由工具按库里的实时状态判定,不要拿几轮之前查到的状态下结论
- 只有待支付和已支付待发货能改收货信息,已发货之后改不动
- 手机号格式不合法、地址太短会被直接回绝,与其被打回不如先问清楚
- 提交时若返回「状态刚发生变化」,说明这单在两次操作之间被改了,重新查一次订单再决定,不要反复重试

五份手册都是这四段。每段给模型的东西不一样:

  • 什么时候用:先说该用,再说不该用。“只问规则走知识库,不用本手册”这句是防模型“先看看”就加载,加载是有代价的,下文会算。
  • 办事步骤:顺序和分支。第2步那四条路,就是序章说T10“分支最宽”那件事落成的文字。开头那次实跑里模型先查订单再取消,走的是第1步到第5步。
  • 这几项怎么填:参数从哪来。工具schema只说orderNo是字符串、receiverPhone是字符串,不说值该从哪取、哪些字段没说就别传。这一段补的是schema说不清的事。
  • 系统的硬约束:哪些判断不归模型。能不能取消由工具判;返回“状态刚发生变化”要重查,不要重试。

解锁付费内容,👉戳​