本文对应项目版本:
v0.0.8
在 v0.0.7 里,我已经给 AI Mind 落下了第一个正式 Skill:utility-skill。
那一版的重点,是证明一件事:
在 Multi-Tool Runtime 之上,是否真的能再长出一层更稳定的能力模式。
但只有一个 Skill,其实还不够。
因为单 Skill 最多只能证明:
- 这套结构能跑
- Runtime 能感知 Skill
- Tool 可以被 Skill 收口
它还证明不了另一件更关键的事:
当系统开始进入多 Skill 阶段时,这层抽象到底是不是真的成立。
所以到了 v0.0.8,我真正要回答的问题就变成了:
- 第二个 Skill 应该是什么
- 什么样的 Skill 才值得进入正式版本
- 多 Skill Runtime 的边界应该怎么收
- 前端又该怎么把这种能力模式切换表达出来
这篇文章想讲的,就是我如何从最初的 writer-skill 设想,最后收敛到了 reader-skill,并让 AI Mind 真正迈出“从单 Skill 到多 Skill”的第一步。
为什么多 Skill 是这一版必须面对的问题
如果项目一直只有一个 utility-skill,那 Skill Runtime 很容易停留在一个比较尴尬的状态:
- 看起来像是做出了一层新抽象
- 但又很难证明它不是一次性的特殊 case
因为只有一个 Skill 时,你很难回答这些问题:
- Skill 之间的边界能不能真正拉开
- Runtime 是否能根据不同 Skill 暴露不同 Tool 子集
- 自动模式下的路由是否还有意义
- 前端是否需要为不同 Skill 提供更明确的交互入口
换句话说,单 Skill 更像是在证明“这套机制存在”,而多 Skill 才开始证明“这套机制成立”。
所以 v0.0.8 的重点,不是再多做一个功能,而是:
让第二个 Skill 真正成为一个有独立边界、有独立 Tool 价值的能力模式。
为什么最开始想到的是 writer-skill
一开始我最自然想到的第二个 Skill,其实是 writer-skill。
这个方向表面上看很合理:
- 它和
utility-skill差异足够大 - 用户很容易理解“写作模式”
- 前端做模式切换时,也很容易有感知
所以我最初尝试的方向是:
- 做一个
writer-skill - 再配一个偏结构整理的 Tool
- 让模型在“改写、总结、整理、生成标题”这类任务上走另一条路径
从想法上说,这条线没有问题。
真正的问题出在落地后。
很快我就发现,写作整理类任务和 utility-skill 最大的不同在于:
它们里有很大一部分,其实本来就是大模型原生就会做的事情。
比如:
- 润色一段话
- 把几句话改写得更自然
- 整理成一段通顺表达
- 概括几个点
这些任务里,模型往往会直接回答,而不是老老实实触发 Tool。
也就是说,writer-skill 可以命中,但 Tool 的独特价值却不够稳定。
为什么我最后放弃了 writer-skill
最后让我决定止损的,不是某一个 bug,而是一个越来越明确的判断:
第二个正式 Skill,最好补的是模型没有的能力,而不是模型已经比较擅长的能力。
writer-skill 的问题主要有三个。
1. 写作整理很多时候是模型原生能力
写作并不是不能做成 Skill,而是它很难在当前阶段承担“证明多 Skill Runtime 成立”的任务。
因为一旦用户的需求是:
- 改写
- 润色
- 概括
- 整理成更自然的一段话
模型会天然倾向于自己直接写。
这意味着:
- Skill 也许命中了
- 但 Tool 不一定会稳定触发
2. Tool 没形成“非它不可”的能力差
如果一个 Tool 提供的只是:
- 换个结构
- 换个格式
- 帮你整理一下语序
那它很容易被模型直接绕过去。
因为模型会判断:
我自己直接写一段,往往比调用一个结构整理 Tool 更简单。
这和 calculator、datetime、unit-convert 完全不一样。
后者一旦不用 Tool,模型就很容易答错;而前者即使不用 Tool,模型也很可能还能答得不错。
3. 第二个 Skill 不应该只是“多一种说话风格”
这是这轮最重要的取舍。
我最后越来越明确地意识到:
多 Skill 的关键,不是“多几个模式名字”,也不是“多几段 Prompt”。
真正值得留下来的 Skill,应该满足至少一条:
- 它组织了一组边界清晰的 Tool
- 它补的是模型原本拿不到的能力
- 它能明显改变 Runtime 的可用能力范围
writer-skill 在当前阶段没有足够强地满足这些条件。
所以我最后放弃它,并不是因为写作不重要,而是因为它不适合当前作为“第二个正式 Skill”。
为什么第二个 Skill 最终变成了 reader-skill
我最后把第二个 Skill 改成了 reader-skill。
因为这时我更想验证的是:
Skill Runtime 是否能承载一类模型本身完全拿不到的信息能力。
reader-skill 对应的正是这类场景:
- 实时天气
- 本地文本文件
它们有一个共同点:
没有 Tool,就没有能力来源。
这和写作场景最大的区别在于:
- 没有天气 Tool,模型就拿不到实时天气
- 没有本地文件读取 Tool,模型就看不到你的项目文件
这时候 Tool 不再是“可选增强”,而是“能力成立的前提”。
于是 reader-skill 的价值就变得非常明确:
- 它不是在给模型增加一种风格
- 而是在给模型接入一类新的上下文来源
这就让第二个 Skill 终于拥有了足够清晰的独立边界。
这版 reader-skill 是怎么收边界的
reader-skill 这一版我只落了两个 Tool,而且每个 Tool 都故意收得很小。
1. city-weather
用途非常单一:
- 查询指定城市的实时天气
它只收一个参数:
city
数据源我也没有做得很重,而是直接用了轻量的 wttr.in。
这背后的考虑很简单:
- 这版的重点不是做一个完整天气系统
- 而是验证“实时信息如何进入 Skill Runtime”
也就是说,city-weather 的价值不在于“做得多强”,而在于它非常直接地证明了:
没有外部 Tool,模型就是拿不到这部分实时信息。
2. local-text-read
local-text-read 同样只做一件事:
- 读取项目根目录下的直接文本文件
它也只收一个参数:
filename
而且我给它加了很强的边界限制:
- 只允许根目录直接文件
- 不允许子目录
- 不允许绝对路径
- 不允许
../ - 只允许文本类文件
这也是我这一版很看重的一点:
Tool 的价值不只是“能做什么”,还包括“它不会越界做什么”。
如果第二个 Skill 要证明它是一种正式能力模式,那它不仅要有能力来源,也要有稳定边界。
多 Skill Runtime 这一版真正收敛了什么
到 v0.0.8,项目里的 Skill 边界终于开始变清楚了。
现在可以比较明确地把它们分成两类:
utility-skill
负责确定性实用任务:
- 计算
- 时间日期
- 单位换算
- 文本转换
对应 Tool:
calculatordatetimeunit-converttext-transform
reader-skill
负责外部上下文获取:
- 实时天气
- 本地文件读取
对应 Tool:
city-weatherlocal-text-read
这时候 Skill 才真正不再只是“一个标签”,而是:
- 当前属于哪一种能力模式
- 当前允许模型使用哪些 Tool
- 当前回答主要建立在哪一类能力来源上
多 Skill 链路图
flowchart LR
A["用户请求"] --> B["/api/chat"]
B --> C{"是否显式传入 skill"}
C -- "是" --> D["直接命中对应 Skill"]
C -- "否" --> E["轻量规则路由"]
E --> F{"命中 utility / reader ?"}
F -- "utility" --> G["utility-skill"]
F -- "reader" --> H["reader-skill"]
F -- "未命中" --> I["普通聊天链路"]
G --> J["allowedTools 过滤 ToolRegistry"]
H --> J
J --> K["模型在当前 Tool 子集里决定是否调用 Tool"]
K --> L["Runtime 执行 Tool"]
L --> M["流式返回 reasoning / tool / text"]
这一版里我刻意没有做的,是:
- 模型自主 Skill 路由
- 多 Skill 编排
- 更复杂的 Agent 化链路
因为我想先证明的不是“系统越来越聪明”,而是:
多 Skill Runtime 在结构上已经开始稳定成立。
为什么前端也要一起进入正式组件基线
这版还有一个我认为非常值得一起写进去的变化:
前端开始正式进入 shadcn/ui 基线阶段。
原因其实也很现实。
当输入区开始同时出现:
- 模型选择器
- Skill 模式切换
- 深度思考开关
- 推理过程面板
- Tool 卡片
如果继续完全靠手写样式往前堆,界面会越来越像几套东西拼在一起。
所以这一版我顺手做了前端统一收口:
- 正式接入
shadcn/ui - 使用
Radix - 图标统一为
lucide-react - 主题走
cssVariables - 当前基线切到
radix-vega
这一轮已经统一下来的区域包括:
- 输入区控制条
- 顶部错误条
- 推理过程面板
- Tool 卡片
- 空状态
而且我还补了几项比较细的交互收口:
- 输入框上下边距收紧
- 推理面板上下边距收紧
- Tool 状态色区分:
- 完成:绿
- 执行中:蓝
- 失败:红
实用和读取模式下的提示文案分开
这一点对我来说很重要,因为它说明:
多 Skill Runtime 的成立,不只是后端 Runtime 的问题,也是前端表达能力的一部分。
这版最重要的工程结论
如果要我用几句话总结 v0.0.8,我最想留下的是这三点:
1. 不是所有 Skill 都值得进入正式版本
有些 Skill 看起来方向对,但它不一定适合当前版本的验证目标。
writer-skill 就属于这种情况:
- 它不是完全没价值
- 但它不适合当前承担“证明第二个 Skill 成立”的任务
2. 第二个 Skill 最好补的是模型缺失的能力
如果 Tool 补的是模型原本就会做的事情,那它就很容易被绕过。
但如果 Tool 补的是模型完全拿不到的上下文,那 Skill 的价值会立刻清晰很多。
这也是为什么 reader-skill 比 writer-skill 更适合当前阶段。
3. 多 Skill 的成立,不只是 Runtime 的事,也是 UI 的事
一旦系统开始真正区分:
- 自动 / 实用 / 读取
- reasoning / tool / text
- 不同 Tool 状态
那前端也必须同步给出更统一、更稳定的表达方式。
这也是为什么这版里,我没有把 UI 统一看成“顺手做的样式活”。
它其实也是版本收敛的一部分。
这一版之后,我更清楚了一件事
如果说 v0.0.7 证明的是:
Tool Runtime 之上可以长出第一层 Skill Runtime。
那么 v0.0.8 证明的就是:
多 Skill 不是多几个不同名字的 Prompt,而是第二个 Skill 是否真的打开了一块新的能力边界。
对现在的 AI Mind 来说,这块边界已经开始变得清楚:
utility-skill:确定性实用任务reader-skill:外部上下文获取
这也让整个 Runtime Skeleton 比之前更像一个会继续长大的系统,而不是一组不断堆叠的局部功能。
后面会往哪走
如果继续沿这条线往后走,我更关心的是:
reader-skill的稳定性继续收口- 网页读取 / MCP 能力怎么接入
- 更高层的 Agent Runtime 什么时候开始真正有必要
但至少在 v0.0.8 这个点上,我已经比较确认:
第二个 Skill 终于不是一个“看起来像 Skill 的名字”,而是一块真正成立的能力模式。
最后
这个项目还会继续沿着:
reader-skill稳定性收口- 网页读取 / MCP
- Agent Runtime
这些方向继续往前走。
如果这篇文章对你有帮助,欢迎到 GitHub 看看项目,也欢迎顺手点个 Star。
仓库地址: github.com/HWYD/ai-min…