
05. Skill 系统注入专业能力从零到一实现一个 AI Agent 框架 · 第六篇1. 为什么需要 Skill大模型什么都知道一点但什么都不精。问它 DCF 怎么算它能背出来——但真要它实操就露馅了用户用 DCF 给 Apple 估值 ↓ LLMDCF 是 Discounted Cash Flow 的缩写... 步骤是预测现金流 → 折现 → 计算终值... 但是具体参数怎么设WACC 取多少增长率呢 它不知道。因为预训练数据里只有理论没有实操流程。更麻烦的是你不想每次让 Agent 做金融分析都在 prompt 里写一遍方法论你不想 Agent 在做一个新领域的任务时瞎摸索你希望 Agent 能复用经验——这次学会了下次直接上手Skill 就是干这个的。2. Skill 到底是什么Skill 不是代码不是 API——它是一份结构化的文档。打开 Axon 的.axon/skills/目录$ls.axon/skills/ company-valuation.md earnings-preview.md finance-sentiment.md discord-reader.md skill-creator.md... $cat.axon/skills/company-valuation.md# company-valuation## 用途用 DCF、相对估值、SOTP 三种方法估算公司内在价值## 步骤1. 获取财务数据使用 yfinance-data skill2. 计算 DCF预测 FCF → 确定 WACC → 计算终值3. 计算相对估值找可比公司 → 算 PE/PB 中位数 → 应用4. 如有多个业务线用 SOTP5. 综合三种方法给出估值区间## 注意事项- 终值占比过高时要谨慎 - 增长假设要有依据不要随便填...就一个 Markdown 文件。但意义重大。对比没有 Skill vs 有 Skill没有 Skill: Agent 收到给 Apple 估值 → 凭记忆瞎猜几个数字 → 可能忘算终值 → 可能用错折现率 → 结果不可靠 有 Skill: Agent 收到给 Apple 估值 → skill_list() 发现 company-valuation → skill_read(company-valuation) 加载完整方法论 → 按步骤一步一步执行 → 每一步都知道需要什么数据、用什么工具 → 结果可靠、可复现3. 从零开始Skill 的最小模型如果你自己设计 Skill 系统最少需要什么3.1 存储文件夹 Markdown.axon/skills/ ├── company-valuation.md ├── earnings-preview.md └── finance-sentiment.md每个.md文件就是一个 Skill。文件名去掉.md就是 Skill 的名字。就这么简单对。因为 Skill 本质是阅读材料——Agent 只需要能读到它。3.2 查询两个工具就够了// skill_list列出所有可用的 SkillasyncfunctionskillList():Promisestring{constfilesfs.readdirSync(SKILLS_DIR);constnamesfiles.filter(ff.endsWith(.md)).map(ff.replace(.md,));returnnames.join(\n);}// skill_read加载一个 Skill 的完整内容asyncfunctionskillRead(name:string):Promisestring{returnfs.readFileSync(${SKILLS_DIR}/${name}.md,utf-8);}Agent 的用法Agent 内部思维链 1. 用户说要给 Apple 估值 2. 我查一下有没有相关的 Skill → skill_list() 3. 看到 company-valuation → skill_read(company-valuation) 4. 哦原来应该先拉数据、再算 DCF... 5. 按步骤执行添加一个新 Skill 就是创建一个 Markdown 文件。不需要改代码不需要部署。4. 工程演进Skill 系统要解决哪些问题4.1 Agent 怎么知道什么场景用什么 Skill光有 Skill 列表不够。Agent 需要知道什么时候用哪个。每个 Skill 的## 用途部分就是干这个的# company-valuation ## 用途 用 DCF、相对估值、SOTP 三种方法估算公司内在价值 适用于已有财务数据的上市公司 不适合早期初创公司、未盈利公司skill_list返回名称和用途描述asyncfunctionskillList():Promisestring{// 读取每个文件的 ## 用途 部分constentriesfiles.map(f{constcontentfs.readFileSync(${SKILLS_DIR}/${f},utf-8);constpurposecontent.match(/## 用途\n(.)/)?.[1]||;return-${f.replace(.md,)}:${purpose};});returnentries.join(\n);}Agent 看到- company-valuation: 用 DCF、相对估值、SOTP 估算公司内在价值 - earnings-preview: 财报前瞻分析 - finance-sentiment: 社交媒体情绪分析一眼就能判断哪个能用。4.2 Skill 之间可以互相调用吗可以。一个 Skill 的步骤里可以引用另一个 Skill## 步骤 1. 使用 yfinance-data skill 获取财务数据 2. 计算 DCF 3. ...这不是真正的函数调用——它是文档层面的引用。Agent 在执行步骤 1 时会先去skill_read(yfinance-data)加载那个 Skill。4.3 谁来创建和维护 Skill最开始是人。但有了skill-creator这个 Skill 之后……# skill-creator ## 用途 创建新的 Skill、修改已有 Skill ## 步骤 1. 分析用户需求 → 确定需要什么领域的知识 2. 创建 .axon/skills/{name}.md 文件 3. 定义用途、步骤、注意事项 4. 用 skill_list 验证新 Skill 可见注意skill-creator 本身也是一个 Skill。它被用来创建其他的 Skill包括修改它自己。这叫自举bootstrapping——系统用自身的能力来扩展自己。一旦skill-creator写好Agent 就可以自己创建新的 Skill 了。用户我需要一个分析 SaaS 公司估值的 Skill ↓ Agent好的我看看 skill-creator 怎么用 → skill_read(skill-creator) → 按照步骤创建 .axon/skills/saas-valuation.md → skill_list 验证可见 → 让用户验收5. 代码解剖Axon 的 Skill 系统Skill 系统的代码很简单——因为它就两个工具。核心在src/tool/skill.ts。skill_list// src/tool/skill.tsasyncfunctionhandleSkillList():Promisestring{constskillsDirgetSkillsDir();if(!fs.existsSync(skillsDir)){return暂无可用技能;}constfilesfs.readdirSync(skillsDir).filter(ff.endsWith(.md)).sort();constlinesfiles.map(f{constnamef.replace(.md,);constcontentfs.readFileSync(path.join(skillsDir,f),utf-8);// 提取第一段用途描述constpurposeMatchcontent.match(/## 用途\s*\n\s*([^\n])/);constpurposepurposeMatch?purposeMatch[1].trim():无描述;return- **${name}**:${purpose};});returnlines.length0?可用技能\n${lines.join(\n)}:暂无可用技能;}skill_readasyncfunctionhandleSkillRead({name}:{name:string}):Promisestring{constfilePathpath.join(getSkillsDir(),${name}.md);if(!fs.existsSync(filePath)){return错误技能 ${name} 不存在。使用 skill_list 查看所有技能。;}returnfs.readFileSync(filePath,utf-8);}Agent 使用示例用户帮我看看 META 的财报前瞻 Agent 内部调用链路 ① skill_list() ↓ name: earnings-preview desc: 生成财报前瞻分析简报 ② skill_read(earnings-preview) ↓ 加载步骤 1. 获取财务数据 2. 分析师预期 3. 对比历史 4. 关键关注点 ③ 按步骤执行 → yfinance 拉 META 数据 → 对比去年同期 → 整理关注点 → 生成报告6. 动手实验用 Skill 系统实验一查看可用的 Skill用户你都会什么技能Agent 会调用skill_list()你就能看到当前所有可用的 Skill。实验二创建一个新 Skill用户创建一个新的 skill 叫做 pizza-analyzer 专门分析披萨店的质量 步骤1. 看评分 2. 看配料 3. 看价格Agent 应该会用skill-creator或者直接写文件来创建# pizza-analyzer ## 用途 分析披萨店的综合质量 ## 步骤 1. 获取评分数据 2. 分析配料搭配 3. 评估价格合理性 4. 给出综合评分实验三Skill 覆盖与冲突如果两个 Skill 用途描述相似Agent 会选哪个试试用户创建两个 Skill - fetch-stock-price: 获取股票当前价格 - get-share-price: 也是获取股票当前价格 然后问 Agent MSFT 当前多少钱看 Agent 选哪个。它靠什么决策动手改代码打开src/tool/skill.ts试试给 skill_list 加分类finance、social、analysis等标签加 search 功能skill_search(估值)返回相关的 SkillSkill 版本号每个 Skill 头部加version: 1.0list 时显示上一篇DAG 任务规划拆解复杂目标 →下一篇记忆系统让 Agent 记住你Agent 每次对话压缩后就失忆了。怎么让它记住你的名字、偏好、项目决策记忆系统就是干这个的。