写个Skill 一天就能上线,但生产级的Skill你会发现远没有那么简单:Skill 设计不是 prompt 工程,而是一门系统工程。
读完你会得到:
- 一个三层架构范式,让 Prompt、适配逻辑、后端服务各司其职
- 一套实现方式选型决策树,告诉你什么时候该用 CLI、什么时候才需要 MCP
- 五要素安全防护体系,专门针对 AI 写操作的风险边界
- 一张可直接使用的 Skill 设计检查清单
先说局限:本文经验来自 databus_debug_toolkit ,场景特征是小规模用户、内部系统、调试导向。如果你的 Skill 面向外部用户、有高 SLA 要求,本文是参考案例,不是银弹。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
先定义"高质量",再动手
“高质量"不是感性词汇。对于生产级 AI Skill,它的评价维度有四个,且存在真实权衡:
| 维度 | 含义 | 与其他维度的权衡 |
|---|---|---|
| 安全可控 | 写操作不会静默执行,敏感数据不会泄漏 | 安全越高,摩擦越大 |
| 可审计 | 所有操作有完整日志,可追溯、可归因 | 审计越全,存储成本越高 |
| 用户体验 | 低延迟、友好的错误提示、合理的权限边界 | 体验越好,往往需要更多工程投入 |
| 可演进 | 能阶段化推进,解决当前主要矛盾,保留升级扩展能力 | 灵活性越高,初期架构设计越复杂 |
这四个维度不能同时最优化。你必须排序。
本文的优先级是:安全可控 > 可审计 > 可演进 > 用户体验。这是内部工具的合理排序。如果你做的是面向 C 端的 Skill,体验的优先级要大幅提升,但本文不覆盖那个场景。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
三层架构:让每一层只做一件事
Skill 架构最容易被忽视的设计原则是职责分层。
┌─────────────────────────────────────────┐
│ Prompt 层(AI 交互层) │
│ · 工具定义(名称/描述/参数 Schema) │
│ · 意图澄清与错误引导 │
│ · 安全约束(写操作双确认提示) │
└─────────────────┬───────────────────────┘
│ 标准化调用契约
┌─────────────────▼───────────────────────┐
│ 适配层(协议桥接层) │
│ · MCP Server(HTTP/stdio) │
│ · 内联 Markdown(静态知识注入) │
│ · 审计日志 & 可观测性 │
└─────────────────┬───────────────────────┘
│ 服务调用(gRPC/HTTP/SDK)
┌─────────────────▼───────────────────────┐
│ 服务层(业务逻辑层) │
│ · 数据查询 / 写操作执行 │
│ · 鉴权 & 频率限制 │
│ · 审计日志 & 可观测性 │
└─────────────────────────────────────────┘
三层各有一个核心职责,不能混:
Prompt 层是与 LLM 直接交互的契约层。核心原则是"工具描述即文档”——description 字段不能省略、不能模糊;参数必须有明确的类型约束;错误路径需要预设引导语,而非留给模型自由发挥。一个写得好的 Tool description,是 AI 能正确调用工具的基础。
适配层是变化最快、选型差异最大的层。它的核心职责只有一个:将 AI 的结构化调用翻译为下游服务能理解的协议。不承载任何业务逻辑——否则逻辑分散,难以测试。
服务层是纯粹的业务逻辑层,对 AI 的存在无感知。这层的 API 必须能被工程师直接调用和测试,而不是只能通过 AI 触达。这保证了可测试性和故障的可归因性。
💡 对于审计、可观测性等应该放在服务层还是适配层? 对于新服务,建议放在“服务层”,职责更加明晰,而且这些功能对普通API服务也是必须的;对于旧服务来说,可完全不用改造,可以将审计、可观测等放在适配层即可
职责混淆是 Skill 腐化的第一步。
最常见的反模式:把频率限制逻辑放在 prompt 里,比如"请不要在循环中批量调用"。这依赖模型的自觉,不是架构约束。安全约束必须在适配层或服务层技术强制实现——写在 SKILL.md 里的规则,AI 可以忽视;写进代码里的限制,AI 绕不过去。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
架构选型:别一上来就 MCP
直觉上,MCP 是"现代的、结构化的、为 AI 设计的",应该是第一选择。我们最初也这么想。在实际对比 14 个维度之后,发现这个直觉是错的。每种模式都有适用的场景。
三种实现方式的核心差异:
| 方式 | 核心机制 | 优点 | 缺点 | 典型场景 |
|---|---|---|---|---|
| 内联 Markdown Skill(Skill + Function Call) | SKILL.md 提示词 + AI 通过 Function Call 调 HTTP API | 零改造成本、学习成本低、快速迭代 | 重用性低、难以测试、AI 行为有歧义、凭证管理困难 | 快速实验、只读查询、低风险操作 |
| Skill + MCP | 将服务改造为 MCP Server,AI 调用标准化工具 | 工具语义明确、安全集中管控、跨项目复用、可观测性好 | 需改造服务、引入运维成本、团队需了解 MCP 协议 | 跨项目复用、写操作、企业级治理 |
| Skill + CLI | 封装为命令行工具,Skill 通过 Bash 调用 | 可独立测试、与 DevOps 工具链集成 | 分发成本高、认证分散、交互能力弱 | CI/CD 集成、批处理、脚本化 |
选型决策树:
是否有明确的 MCP Server Owner(被纳入服务治理)?
├── 否 → 内联 Markdown Skill,仅覆盖只读操作(schema 查询等)
└── 是
├── 需要「有状态会话」或「细粒度权限控制」?
│ ├── 是 → MCP(HTTP 模式)
│ └── 否
│ ├── 工具链是否已有成熟 CLI?
│ │ ├── 是 → CLI 封装(利用现有生态)
│ │ └── 否 → 评估冷启动延迟
│ │ ├── 延迟敏感(<200ms 体感阈值)→ CLI 或进程常驻
│ │ └── 延迟不敏感 → MCP(更好的类型安全)
│ └── 需要跨工具共享状态?
│ ├── 是 → MCP
│ └── 否 → CLI(更简单、更易调试)
我们为什么最终选了 MCP HTTP 模式?
databus_debug_toolkit 有三个具体需求:写操作的两步确认需要在请求之间维护预览状态(Session Store);多用户共享同一服务实例需要 appid 维度的频率限制;Phase 2+ 需要细粒度权限控制。这三个需求组合在一起,CLI 很难优雅实现,MCP HTTP 模式天然支持。
但这不是绝对结论。 如果已有CLI,或者都是单步操作,或者利用本地资源做一些逻辑,完全建议使用CLI。
💡 一个值得考虑的实践:在 MCP 与 CLI 之上建立统一抽象层,通过配置切换适配方式,避免将协议选择硬编码进 Prompt 层。这样从 CLI 迁移到 MCP 时,不需要修改工具描述。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
安全设计:五要素防护体系
这是生产级 Skill 和玩具 Skill 的分水岭。
AI 调用工具的节奏与人类完全不同。LLM 在单次 ReAct 循环中可能在毫秒内发起数十次工具调用,完全没有"我再想想"的自我审视。系统不替它做防护,就没有人替它做。
────────────────────────────────────
要素一:最小权限(Least Privilege)
Phase 1 只开放只读接口。
这不是懒,是用最小成本验证价值假设的工程哲学。只读操作的失败边界清晰——最坏情况是"返回错误结果",不造成数据损坏。先上线只读工具,可以在零副作用条件下验证三件事:工具描述的准确性、AI 调用的参数合法性、下游服务的容量压力。
这三件事的验证数据,是写操作上线的前置信心来源。
────────────────────────────────────
要素二:频率限制(Rate Limiting)
技术强制,不依赖 prompt。
频率控制必须在适配层(MCP Server)实现,不能写在 SKILL.md 里说"请不要批量调用"。
databus_debug_toolkit 的配置:
rate_limits:
- tool: tools_get_full_features
per_minute: 30 # 单实体查询,防批量拉取
- tool: tools_get_event_list
per_minute: 20 # 支持翻页,额外降低阈值
阈值必须通过配置文件管理,不能硬编码,上线后根据实际观测到的使用模式调整。
实现算法使用 Token Bucket(令牌桶),支持突发后平滑降速。
────────────────────────────────────
要素三:字段过滤(Output Field Filtering)
敏感字段的过滤在适配层统一处理。后端返回原始数据,过滤逻辑在 MCP Server 侧维护。
一个关键的架构决策:使用白名单还是黑名单?
databus_debug_toolkit 当前(Phase 1)采用黑名单——屏蔽已知敏感字段。理由是初期敏感字段边界尚未梳理清楚,白名单会导致太多合法字段被拦截。但黑名单有一个明显风险:新增字段默认可见,必须有机制保证新字段被及时评估。
我们的对策:Phase 2 上线前完成完整的敏感字段梳理,并将其作为 Phase 2 准入标准的硬性条件。
如果你的 Skill 面向更敏感的数据,建议从一开始就使用白名单。
────────────────────────────────────
要素四:写操作双确认(Two-Phase Write)
这是设计中最容易被误解的部分。
双确认不只是 UX 设计,它是一个架构级的熔断机制。
在 AI 意图与实际执行之间插入一个人类审核节点,确保 LLM 幻觉或参数误解的影响范围被限制在"预览阶段"。
执行流程:
用户自然语言 → AI → MCP Server(confirmed=false,预览模式)
↓ 返回操作预览 + 影响范围描述
AI 展示预览给用户
↓ 用户明确确认(真人操作,不是 AI 替代)
AI → MCP Server(confirmed=true,同一 session)
↓ 校验 session 内存在对应预览记录 + 参数哈希一致
→ 后端 API 执行 → 写入审计日志
一个关键的安全质疑:AI 能否自动 bypass 这个确认?
这是真实存在的风险。对策是双重防护,缺一不可:
技术强制(第一道):MCP Server 验证同一 session 内存在预览记录。如果 AI 直接传
confirmed=true而没有先做预览,服务端返回preview_required错误,技术上拒绝执行。这不依赖 AI 的自觉。Prompt 约束(第二道):SKILL.md 中明确写明"必须等待用户明确说’确认执行’等确认词后,才能传 confirmed=true"。Prompt 层是第二道防线,不是第一道。
5 分钟预览有效期 + 参数哈希校验(防止预览后篡改参数)是额外的安全加固。
────────────────────────────────────
要素五:审计日志(Audit Trail)
审计日志只有被消费才是安全能力。否则只是存储成本。
我们的设计:所有写操作产生 AUDIT 级别日志,保留 ≥30 天,接入公司内部可观测系统。告警规则包括:
write_op_skip_preview_total > 0(任意 1 分钟内)→ P1 告警,立即审查- 单 appid 1 小时内响应数据条数 > 1000 → P2 告警,检查批量爬取
- 工具 3 分钟错误率 > 10% → P2 告警
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
阶段化演进:晋级标准是硬条件,不是感觉
不要一上来就搞大而全的tool,可以对使用方进行调研,对高频使用的只读操作,优先提供。 对企业场景来说,安全可用永远是第一位的。
我们演进的三步节奏:
Phase 1:只读 + 单工具验证
↓ (观测调用模式、收集错误样本、建立安全基线)
Phase 2:组合工具 + 可逆写操作(双确认)
↓ (验证副作用边界、完善审计体系)
Phase 3+:不可逆操作 + 批量写操作
(依赖外部审批流,安全评审通过后)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
我们踩过的坑
一篇没有失败的技术分享,读起来像成功学。这里列出我们实际遇到的四个问题。
────────────────────────────────────
坑 1:Tool description 写得不够精确
早期版本的 tools_get_full_features description 只写了"查询实体的完整特征数据"。
结果:AI 在不需要全量数据的场景下也会调用这个工具,且不使用 focus_keys 参数,每次返回大量无用字段,既浪费 token,又触发了数据量告警。
修复:在 description 中明确写"可使用 focus_keys 缩小返回字段范围以控制数据量。注意:本接口有频率限制,请勿在循环中批量调用。“并在 inputSchema 中给 focus_keys 加上使用场景描述。
💡 教训:description 字段不是备注,是给 LLM 看的调用契约。模糊的描述等于把调用策略的决定权交给模型。
────────────────────────────────────
坑 2:缺乏多维度的观测数据
最初只有请求量和请求成功率。
后来发现,根本不知道系统被谁访问了,是否
────────────────────────────────────
坑 2:频率限制的粒度设计
最初想按 session_id 做频率限制——同一会话内限流。
后来意识到这不能防止攻击者开多个会话绕过限制,应该按 appid 限流(同一 appid 跨会话累计计数)。
💡 教训:限流的粒度要和攻击面对齐。session 级别的限流防不住"多开会话"的绕过。
────────────────────────────────────
坑 4:错误信息透传
早期版本直接把后端 gRPC 错误原样返回给 AI,包含服务名、内部错误码等敏感信息。在一次内部安全 review 时被指出。
修复:在适配层统一做错误过滤,将后端原始错误映射为用户友好的描述,原始错误只写入日志。
💡 教训:适配层的职责之一就是信息过滤。后端的错误细节是内部信息,不应该直传到 AI 上下文。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Skill 设计检查清单
把上面的经验提炼成一张自检清单,直接使用。
价值验证(开始动手前)
- 明确目标用户是谁,他们会在什么场景下选择用 Skill 而非直接操作
- 量化"成功"的指标(调用量?排障时间缩短?原始接口访问减少?)
- 确认是否有 Owner 负责运维和安全响应
架构设计
- 三层职责是否清晰(Prompt / 适配 / 服务)
- 适配方式选型(内联 Markdown / CLI / MCP)是否有明确的决策理由
- 安全约束是否在适配层技术强制,而非仅依赖 prompt
Prompt 层
- 每个 Tool 的 description 是否足够精确(可做 AI 可用性测试验证)
- 参数 Schema 是否有合法取值说明、上下限约束
- 错误路径是否有预设的用户引导语
安全设计
- 威胁模型是否明确(防谁、防什么、不防什么)
- 高风险接口是否有频率限制(技术强制)
- 字段过滤策略(白名单/黑名单)是否明确,变更机制是否确定
- 写操作是否有两步确认,且第二步需要人工触发(不可被 AI 自动 bypass)
- 审计日志是否有消费侧(谁看、触发什么告警)
演进策略
- Phase 1 是否只开放只读操作
- Phase 2 的晋级标准是否可量化(不是"感觉稳了”)
- MCP Server 接口是否只增不改(向后兼容约束)
上线前
- 内部用户灰度验证(至少 2 人,至少 3 天)
- 接入内部可观测系统(指标上报 + 结构化日志)
- 告警规则配置完成(包括写操作绕过预览的 P1 告警)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
结语
永远不要相关AI,即使99次都正常,也不能保证第100次一定正常。但是作为系统负责人,你是需要对系统、数据、安全负责的。
所以,把 Skill 当成系统工程来设计,加好“harness”。