如果你有 100 个 Skills,难道就要给 LLM 喂 100 个工具定义吗?显然不行。
核心概念:通过单一的 Skill 工具管理所有 Skills。
不是:100 个 Skills = 100 个工具
而是:100 个 Skills = 1 个 Skill 工具(元工具)
这个“元工具”就像一个Skills 的总开关。LLM 只需要知道怎么调用这个总开关,然后告诉它想用哪个具体的 Skill(比如pdf-analysis),以及传入什么参数。
优势:避免工具列表爆炸,统一管理,实现动态加载。
LLM 的上下文窗口是昂贵的资源,我们必须精打细算。一个 Skill 的定义可能包含几 KB 的说明文档和几十 KB 的脚本代码,如果全塞进去,Token 消耗会非常大。
解决方案是:按需、分级加载。
这是渐进式披露的延伸,也是最关键的 Token 优化点:脚本代码不进入 LLM 上下文。
为什么?
完整流程:Skill 工具 → 加载 SKILL.md (Level 2) → 注入 LLM 上下文 → LLM 推理 → 调用 Bash 工具 → 加载脚本 (Level 3) 到 Sandbox → 执行脚本。
Skills 的元数据和文件内容需要一个存储系统。在追求实时性、高性能和分布式的 Agent 架构中,我们推荐使用Redis。
为什么选 Redis?
数据结构示例:
# Skills 文件内容(Hash)skills:{skill_name}:{version}├─ SKILL.md:"..."└─ scripts/extract.py:"..."# 当前版本号(String)skills:{skill_name}:current_version →"4"
我们放弃了传统的轮询(Polling)模式,采用Redis Pub/Sub的推送(Push)模式,实现 Skills 的实时更新。
更新流程:开发者修改 Skills → 更新管理器写入 Redis → 发布消息到 Pub/Sub → 各节点收到消息,清除缓存。
延迟:< 10ms,基本实现实时更新。
Skills 的加载必须是按需的,并且与 Agent 的 Run Loop 紧密结合。
关键点:不要在每轮 Agent loop 中重新加载!一旦 Level 2/3 文件被加载,它们应该被缓存起来。
核心原则:一个对话使用一致的 Skills 版本。
对话开始 → 锁定版本(如 v4)→ Run Loop(始终用 v4)→ 对话结束
为什么?保证一致性,行为可预测,易于调试。
一个成熟的 Agent 框架应该支持在Run Loop 的任何时候加载新的 Skill。
excel-analysispdf-generation(动态新增)image-processing(再次新增)特性:完全动态,无需预知;按需加载,节省资源;自动去重,不重复加载。
当需要用到多个 Skills 时,批量加载比单个加载效率更高。
# 单个加载Skill(skill_name="pdf-processing")# 批量加载(推荐)Skill(skill_names=["excel-analysis","image-processing","pdf-generation"])
在底层,批量加载可以利用 Redis 的MGET或HMGET等命令,实现并行加载,性能提升往往能达到 3 倍以上,极大地优化了用户体验。
Skills 的脚本文件最终要在 Sandbox 中执行。这里有一个关于文件系统策略的选择题:挂载(Mount)还是复制(Copy)?
策略模式:成熟的 Agent 平台会根据 Sandbox 的类型自动选择最合适的策略。在生产环境中,复制是主流选择,以确保每个 Agent 任务的隔离性和安全性。
Skills 机制不是简单的“插件系统”,它是一套针对大模型特性优化的上下文工程。
通过Meta-Tool 架构解决规模问题,通过渐进式加载解决成本问题,再通过Redis + 版本锁定解决工程稳定性问题。只有把这些底层细节打磨好,Agent 才能在复杂的业务场景中跑得稳、跑得快。
希望这 10 个底层设计细节,能为你构建自己的 Agent 平台提供一些实用的思路。
| 欢迎光临 链载Ai (http://www.lianzai.com/) | Powered by Discuz! X3.5 |