资讯动态

DeerFlow 系列教程 第九篇 | Skills 技能系统——Agent 的知识与能力扩展

发布时间:2026/10/23 19:29:52 来源:尧图企业网站定制
1. 为什么你的 DeerFlow Agent 总是“答得对但做得乱”很多人第一次跑通 DeerFlow 之后都会经历一个相似的阶段单轮问答挺聪明一旦让它做“调研 整理 出图 写报告”这种复合任务输出就开始飘。要么步骤漏了要么工具乱调要么同一个坑反复踩。我试过把提示词写得很长去约束它结果上下文被塞满效果反而更差。问题不在模型而在你缺了一层“工作流封装”。DeerFlow 的 Skills 技能系统就是干这个的它把“遇到某类任务该按什么步骤做、用哪些工具、参考哪些文档”写成一份 Markdown 手册Agent 在需要时按需加载而不是每次都靠你临时叮嘱。这一篇就带你从 SKILL.md 的定义规范一路走到技能加载与调用链路最后在本地跑通一个自定义技能并确认 Agent 真的识别、真的调用。先明确三个概念避免后面混淆。工具Tool是原子操作比如web_search、bash、read_file每个工具干一件事注册在代码层。技能Skill是更高层的编排模板本质是一份SKILL.md文档告诉 Agent 先做什么、再做什么、用哪些工具、参考哪些资源。技能系统则是这套文档的发现、加载、缓存、启用/禁用与安全校验机制。适合谁读已经跑通 DeerFlow 基础对话、想给 Agent 扩展专属能力的开发者被“多步骤任务不稳定”困扰的 Agent 玩家以及想理解渐进式加载Progressive Loading这类上下文优化思路的工程师。读完你能自己写一个技能、注册进去、验证它被正确触发。2. TaoToken 前置准备给技能调用链路配一个稳定模型入口技能系统本身不依赖特定模型服务但技能被触发后Agent 要读 SKILL.md、要按指令调工具、要做安全扫描这些都走模型推理。如果你本地模型时好时坏排查技能问题时你会分不清是“技能没被加载”还是“模型没响应”。所以先把模型入口固定下来后面排障才干净。我用 TaoToken 作为统一入口原因是它兼容 OpenAI 风格的接口Base URL 和 Key 一填就能用省去在多个 SDK 之间来回改配置的麻烦。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 这个不加 UTM直接填进配置即可。你需要准备三件套这是后面所有配置的基础配置项值说明Base URLhttps://taotoken.net/apiOpenAI 兼容接口前缀API Key在控制台创建形如sk-...只显示一次Model ID按需选择技能推理建议用能力较强的模型创建 Key 的路径是控制台里的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。如果你还没决定用哪个模型可以先在模型对话页面试一下https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。注意技能的安全扫描security_scanner会调用 LLM 做内容分类。如果模型入口不稳定扫描失败会走保守回退策略——默认 block导致你保存技能时被拒。所以先把模型连通性确认好再动技能。这里要强调一个容易踩的坑技能系统里的“模型调用”和“工具调用”是两条链路。工具如read_file是本地执行的不经过模型但“判断该不该加载某个技能”是模型根据 description 做的决策。所以模型入口挂了表现是“技能明明存在却从不触发”而不是报错。把 Base URL、Key、Model ID 三件套配好是后面验证步骤能跑通的前提。如果你打算长期做 Agent 编码和技能迭代可以考虑 Coding Plan额度更划算https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入细节可以对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。3. 可复制配置SKILL.md 模板与技能注册这一节是全文的核心操作区。我们分两步先写一个能跑的自定义技能再把它注册进 DeerFlow 并确认配置生效。3.1 技能目录结构DeerFlow 的技能放在项目根目录的skills/下分public/内置只读和custom/自定义可编辑被 gitignore。我们要动的是custom/skills/ ├── public/ # 20 个内置技能只读 │ └── deep-research/ │ └── SKILL.md └── custom/ # 用户自定义可编辑 └── my-translator/ └── SKILL.md支持的资源子目录只有四个这是安全边界别乱建references、templates、scripts、assets。3.2 SKILL.md 完整模板SKILL.md由两部分组成YAML Front Matter---包裹的元数据 Markdown 正文。下面是一个可直接复制的翻译技能模板--- name: my-translator description: Use this skill when the user asks to translate text between languages. Provides a structured translation workflow with context awareness and style adaptation. version: 1.0.0 author: your-name --- # Translation Skill ## Overview This skill provides a systematic approach to text translation that goes beyond literal translation, preserving tone and domain terminology. ## Workflow ### Step 1: Analyze Source Text - Identify the source language - Understand the context and tone - Note any domain-specific terminology ### Step 2: Translate - Preserve the original meaning and nuance - Adapt cultural references when appropriate - Maintain consistent terminology ### Step 3: Review - Compare with the original for accuracy - Check for natural flow in the target language - Verify technical terms are correctFront Matter 里name和description是必需字段缺一个整个技能会被跳过。命名规则很严只允许小写字母、数字和连字符不能以连字符开头/结尾不能有连续连字符最长 64 字符。description不能含尖括号防止 XML 注入最长 1024 字符。3.3 启用状态配置技能的启用/禁用由extensions_config.json管理它同时管 MCP 服务器和技能。路径发现顺序是显式传入的config_path→ 环境变量DEER_FLOW_EXTENSIONS_CONFIG_PATH→backend/extensions_config.json→ 项目根extensions_config.json→ 旧文件名mcp_config.json。{ mcpServers: {}, skills: { deep-research: { enabled: true }, my-translator: { enabled: true }, video-generation: { enabled: false } } }判定逻辑很简单配置里写了enabled: false就禁用没出现在skills字段里的public和custom默认启用。也就是说你新建的技能不用手动加进配置它会自动生效。3.4 带资源的技能配置如果技能要引用外部文档或脚本加上子目录并在正文里用read_file引用## Workflow ### Step 1: Read Report Template Load the report template: read_file /mnt/skills/custom/my-report-generator/templates/quarterly-report.md ### Step 2: Generate Report Follow the format guide at: references/report-format-guide.md ### Step 3: Export PDF Execute the generation script: bash python /mnt/skills/custom/my-report-generator/scripts/generate_pdf.py \ --input /mnt/user-data/workspace/report.md \ --output /mnt/user-data/outputs/report.pdf注意容器内路径是 /mnt/skills/custom/{name}/...和你本地的 skills/custom/{name}/... 是映射关系写引用时用容器路径。 ### 3.5 通过 API 注册与刷新 DeerFlow Gateway 提供了完整的技能管理 REST API | 接口 | 方法 | 说明 | | --- | --- | --- | | /api/skills | GET | 列出所有技能public custom | | /api/skills/custom | GET | 列出自定义技能 | | /api/skills/custom/{name} | PUT | 编辑自定义技能含安全扫描 | | /api/skills/{name} | PATCH | 更新技能状态启用/禁用 | | /api/skills/install | POST | 从 .skill 归档安装 | 每次状态变更后API 会调用 refresh_skills_system_prompt_cache_async() 刷新系统提示词缓存。这一步很关键因为 Gateway 和 LangGraph Server 跑在不同进程里不刷新的话 Agent 感知不到变化。 bash # 列出所有技能确认 my-translator 已被发现 curl -s http://localhost:8000/api/skills | jq .skills[] | {name, category} # 禁用某个技能 curl -X PATCH http://localhost:8000/api/skills/video-generation \ -H Content-Type: application/json \ -d {enabled: false}4. 验证请求确认 Agent 真的识别并调用了技能配置写完不代表生效必须验证。技能系统的验证分三层文件层能解析、提示词层被注入、运行时被调用。4.1 文件层验证先确认SKILL.md能被正确解析。Front Matter 解析器是自建的轻量级实现支持三种值格式简单值、折叠块多行合并为单行、字面量块|保留换行。解析后name和description缺失就返回None技能被跳过。# 检查文件是否存在、Front Matter 是否完整 head -n 10 skills/custom/my-translator/SKILL.md # 通过 API 获取技能内容验证解析结果 curl -s http://localhost:8000/api/skills/custom/my-translator | jq .如果返回里能看到name和description说明文件层通过。4.2 提示词层验证技能信息通过get_skills_prompt_section()注入到系统提示词的skill_system段。每个技能条目包含name、description带[built-in]或[custom, editable]标签、location容器内路径。skill_system You have access to skills that provide optimized workflows for specific tasks. **Progressive Loading Pattern:** 1. When a user query matches a skills use case, immediately call read_file on the skills main file using the path attribute provided in the skill tag ... available_skills skill namemy-translator/name descriptionUse this skill when the user asks to translate text... [custom, editable]/description location/mnt/skills/custom/my-translator/SKILL.md/location /skill /available_skills /skill_system你可以打印构建好的系统提示词确认my-translator出现在available_skills里。如果没出现回到第 3 节检查extensions_config.json和缓存刷新。4.3 运行时验证这是最关键的一步。发一条明确匹配 description 的消息观察 Agent 是否调用read_file加载技能curl -X POST http://localhost:8000/api/chat \ -H Content-Type: application/json \ -d { message: 帮我把这段英文翻译成中文The quick brown fox jumps over the lazy dog., stream: true }在返回的工具调用轨迹里你应该看到类似[tool_call] read_file path: /mnt/skills/custom/my-translator/SKILL.md [tool_result] (技能内容加载成功) [assistant] 按技能工作流执行分析源文本 → 翻译 → 复核...看到read_file指向你的技能路径就说明整条链路通了。如果 Agent 直接翻译、没读技能说明 description 没匹配上或者技能没被注入提示词。4.4 渐进式加载的 token 对照验证时顺便理解一下为什么这套机制省上下文。三层加载的 token 消耗差异很大加载层级内容token 消耗触发时机第一层name description path~50 token/技能每次对话第二层完整 SKILL.md数百~数千 tokenAgent 判断需要时第三层references/scripts 等按需工作流执行中20 个技能在第一层只消耗约 1000 token全量加载可能要 50000 token。这就是为什么技能系统能在不炸上下文的前提下扩展能力。5. 本篇常见错排查401、local proxy failed 与技能不触发技能系统的报错往往不在技能本身而在模型入口或缓存。下面按真实报错逐个拆。5.1 401 UnauthorizedError: 401 Unauthorized {error: {message: Invalid API key, type: invalid_request_error}}这是模型入口的 Key 问题不是技能问题。检查三件套Base URL 是否为https://taotoken.net/apiKey 是否完整sk-开头Model ID 是否拼写正确。技能的安全扫描会调 LLMKey 错了扫描直接失败保存技能时会被 block。# 快速验证 Key 是否可用 curl -s https://taotoken.net/api/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head5.2 local proxy failedError: local proxy failed: connection refused这个报错通常出现在你配置了本地代理但服务没起来或者 Base URL 指向了本地端口。技能系统本身不需要代理把 Base URL 直接指向https://taotoken.net/api即可。检查环境变量里有没有残留的HTTP_PROXY/HTTPS_PROXY指向失效地址。5.3 reading choices 报错TypeError: Cannot read properties of undefined (reading choices)这是响应结构不符合预期常见原因是 Base URL 少了/api后缀或者用了非 OpenAI 兼容的路径。确认 Base URL 是https://taotoken.net/api请求路径是/chat/completions。技能触发时如果模型返回结构异常Agent 会拿不到决策结果表现就是“技能不触发”。5.4 OAuth 相关报错Error: OAuth token expired or invalid如果你用的是需要 OAuth 的客户端如某些 CLI 工具token 过期会导致模型调用失败。重新走一遍授权流程或者改用 API Key 方式。技能系统不关心你用哪种鉴权只要模型能通就行。5.5 技能存在但从不触发这是最隐蔽的一类。排查顺序先确认技能在提示词里打印系统提示词看available_skills有没有你的技能。没有就检查extensions_config.json是否把它禁用了或者缓存没刷新。再确认 description 匹配description 是触发匹配的唯一依据Agent 看不到技能正文。如果 description 写得太模糊比如只写“翻译技能”模型可能判断不出该在什么时候用。参考内置deep-research的写法明确列出触发场景。最后确认模型能力技能触发是模型决策能力太弱的模型可能忽略技能列表。换一个推理能力更强的 Model ID 再试。5.6 安全扫描误 blockScanResult(decisionblock, reasonpotential prompt injection detected)编辑自定义技能时security_scanner.py会用 LLM 对内容分类三级结果allow正常保存、warn保存但记录警告、block拒绝保存。如果 LLM 扫描不可用走保守回退——默认 block。检查技能内容里有没有看起来像系统指令覆盖、提权、数据外泄的表述改掉再存。6. 把技能系统用起来从自定义技能到长期 Agent 工作流到这里你已经能写 SKILL.md、注册技能、验证调用、排查常见错。最后说几个实战里真正省事的点。技能和工具的关系要摆正技能不替代工具它是工具之上的编排层。一个 PPT 生成技能可能组合web_search调研、write_file写 JSON、bash执行生成脚本、present_file展示多个工具。你写技能时重点是把“步骤顺序”和“资源引用”写清楚而不是重复描述工具怎么用。技能自演化值得开。当skill_evolution.enabled为 true 时Agent 完成任务后如果满足条件工具调用 5 次、踩过非显而易见的坑、用户纠正后生效、发现可复用工作流会考虑自动创建或改进技能。Agent 生成的技能同样要过安全扫描不用担心它乱写。版本追踪别忘了。每次自定义技能被改skills/custom/.history/{name}.jsonl会记录一条 JSONL包含时间戳、操作类型、操作者、修改前后内容、扫描结果。出问题时可以回滚。如果你要把这套技能系统接到长期编码或 Agent 工作流里Coding Plan 的额度更适合持续迭代https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。需要查接口细节时对照文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先验证模型对技能 description 的匹配能力去模型对话页面发几条测试消息最快https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。下一篇会拆 Sub-Agents 子智能体讲 Lead Agent 怎么通过task工具把复杂任务委派给多个子智能体并行执行。技能系统是“单个 Agent 怎么把一件事做规范”子智能体是“多个 Agent 怎么把一堆事并行做完”两者配合起来才是完整的编排能力。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑