Agent Skills详解:用SKILL.md与allowed-tools构建可复用的技能中间件
1. 从一堆散装提示词到可复用技能Agent Skills 要解决的真实问题如果你正在用 deepagents、LangChain 或者自己搭的 Agent 框架做业务大概率遇到过这个场景某个复杂任务比如查数据库→清洗→生成报表→发邮件你调了很久的提示词才让模型稳定跑通结果换一个会话、换一个入口模型又开始自由发挥步骤顺序全乱。你把那段提示词复制到系统提示里上下文窗口立刻被吃掉一大块其他任务的表现跟着下降。Agent Skills 就是冲着这个矛盾来的。它把完成某类任务的完整流程从主提示词里抽出来封装成一个独立文件夹核心是一个SKILL.md文件。Agent 平时只知道有哪些技能存在名称加一句描述真正需要时才把完整指令读进上下文。这套机制叫渐进式披露Progressive Disclosure本质上是给 Agent 装了一套按需查阅的工作手册。它适合谁三类人最该关注一是手里已经有一堆跑通的提示词、想沉淀成团队资产的开发者二是用 deepagents 做多步骤任务、被上下文长度和输出不稳定折磨的工程师三是想把某个垂直领域的操作规范打包给 Agent 用的业务方。这篇不讲概念史直接给可复制的SKILL.md骨架、SkillsMiddleware的注册配置以及一次能跑通的端到端验证。你跟着敲完就能把零散提示词变成可挂载、可约束、可复用的技能模块。2. 前置准备TaoToken 接入与 deepagents 环境2.1 为什么这里用 TaoToken 做模型接入Agent Skills 本身是框架层的能力但它要跑起来得有个稳定的模型后端。我实测下来用 TaoToken 的兼容接口接 deepagents 比较省事一个 Key 就能切换不同模型调试技能契约时不用反复改环境变量。它的接口地址是https://taotoken.net/api兼容 OpenAI 风格的调用方式deepagents 底层的 LangChain 模型封装可以直接对接。你需要先去控制台拿一个 API Key。打开 TaoToken 控制台 创建密钥复制出来备用。如果你还没注册从 官网入口 进去即可。2.2 安装依赖deepagents 目前通过 pip 安装同时需要 LangChain 的核心包。建议单独建一个虚拟环境避免和现有项目冲突。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install deepagents langchain-core langchain-openai如果你打算用技能里自带的脚本执行方式后面示例三会讲还需要tavily-python或者直接用requests这个按需装。2.3 配置模型新建一个agent/my_llm.py把 TaoToken 的接口接进来。注意base_url用 API 地址不要带多余路径。# agent/my_llm.py import os from langchain_openai import ChatOpenAI llm ChatOpenAI( modelclaude-sonnet-4-5, # 按你控制台可用的模型名填 api_keyos.environ.get(TAOTOKEN_API_KEY), base_urlhttps://taotoken.net/api, temperature0.2, )把 Key 写进环境变量别硬编码在代码里export TAOTOKEN_API_KEY你的Key到这里前置就绪。接下来是核心怎么写SKILL.md以及怎么把它挂到 Agent 上。3. 可复制配置SKILL.md 骨架与 SkillsMiddleware 注册3.1 SKILL.md 的两段式结构一个技能就是一个文件夹里面必须有SKILL.md。它由两部分组成YAML 前置元数据frontmatter和 Markdown 指令正文。元数据负责让 Agent 快速识别正文负责告诉它怎么做。先看骨架你可以直接复制改--- name: web-search description: 当用户的问题需要联网检索最新信息、实时数据或背景资料时使用此技能。 allowed-tools: execute --- # Web Search 技能 ## 何时使用 - 用户询问最新新闻、事件进展 - 需要实时数据、股价、天气等 - 你的内部知识无法回答且需要联网的问题 ## 如何执行 你拥有 execute 工具可以运行 Shell 命令。按以下格式执行检索脚本 bash python skills/web-search/search.py --query 检索关键词 --topic general --max-results 5输出要求先给出答案摘要再列出来源链接如果结果为空明确告知用户未找到不要编造几个字段的约束要记牢。name 必须是小写字母、连字符和数字1 到 64 字符不能用下划线或空格通常和文件夹同名。description 是 Agent 决定要不要调用这个技能的第一道门一定要写清何时使用和解决什么问题1 到 1024 字符。allowed-tools 是可选的信任列表告诉模型执行此技能时可以用哪些工具。 注意allowed-tools 目前更多是给模型的提示hint中间件并不会强制拦截。也就是说它约束的是模型被引导去用哪些工具而不是运行时硬隔离。真正的安全边界还得靠工具本身的权限设计。 ### 3.2 用 SkillsMiddleware 挂载技能 deepagents 里加载技能有两种方式。一种是直接在 create_deep_agent 里传 skills[skills] 参数最省事另一种是显式构造 SkillsMiddleware适合需要自定义后端、多来源加载的场景。这里重点讲第二种因为它更能体现工程化控制。 目录结构长这样 text project/ ├── agent/ │ └── my_llm.py ├── skills/ │ └── web-search/ │ ├── SKILL.md │ └── search.py └── main.py注册中间件的代码import os from deepagents import create_deep_agent from deepagents.backends import FilesystemBackend from deepagents.middleware import SkillsMiddleware from langchain_core.tools import tool from agent.my_llm import llm # 通用命令执行工具所有技能共用 tool def execute(command: str) - str: 执行 Shell 命令并返回输出用于运行技能脚本。 import subprocess try: result subprocess.run( command, shellTrue, capture_outputTrue, textTrue, timeout60, cwdos.getcwd() ) return result.stdout result.stderr except subprocess.TimeoutExpired: return 命令执行超时60秒 backend FilesystemBackend(root_diros.getcwd(), virtual_modeTrue) skills_middleware SkillsMiddleware( backendbackend, sources[skills], ) agent create_deep_agent( modelllm, tools[execute], system_prompt你是研究助理。需要联网检索时使用 web-search 技能。, middleware[skills_middleware], )FilesystemBackend的root_dir决定技能从哪个根目录找virtual_modeTrue会把路径限制在根目录内避免技能脚本越权访问。sources是个列表意味着你可以同时挂多个技能目录比如[skills, team-skills]方便团队共享和私有技能分离。3.3 技能自包含脚本的写法技能文件夹里除了SKILL.md还可以放脚本、模板、参考文档。Agent 通过execute工具运行脚本这样技能就是自包含的不依赖主程序里的工具定义。search.py的骨架#!/usr/bin/env python3 import os, sys, json, argparse import requests TAVILY_API_KEY os.environ.get(TAVILY_API_KEY) if not TAVILY_API_KEY: print(错误: 请设置环境变量 TAVILY_API_KEY, filesys.stderr) sys.exit(1) def search(query, max_results5, topicgeneral): url https://api.tavily.com/search payload { api_key: TAVILY_API_KEY, query: query, max_results: max_results, topic: topic, include_answer: True, } resp requests.post(url, jsonpayload, timeout30) resp.raise_for_status() return resp.json() def main(): parser argparse.ArgumentParser() parser.add_argument(--query, -q, requiredTrue) parser.add_argument(--max-results, -n, typeint, default5) parser.add_argument(--topic, -t, defaultgeneral) args parser.parse_args() result search(args.query, args.max_results, args.topic) if result.get(answer): print(f答案摘要: {result[answer]}\n) for i, item in enumerate(result.get(results, []), 1): print(f{i}. {item.get(title)}) print(f 链接: {item.get(url)}) print(f 内容: {item.get(content, )[:300]}...\n) if __name__ __main__: main()这样SKILL.md里只需要写用 execute 运行这条命令具体逻辑全在脚本里技能的可移植性就上来了。4. 验证请求一次端到端跑通配置写完得验证技能真的被加载、被调用、被约束。分三步走。4.1 验证技能被识别先跑一个最小请求看 Agent 是否知道有这个技能。在main.py里from langchain_core.messages import HumanMessage resp agent.invoke({ messages: [HumanMessage(帮我查一下最近的人工智能行业新闻)] }) print(resp[messages][-1].content)运行python main.py。如果技能加载成功你会在输出里看到 Agent 调用了execute工具命令里包含python skills/web-search/search.py --query ...。这一步的关键是看它有没有主动去读技能而不是凭内部知识瞎答。4.2 验证 allowed-tools 的引导效果把SKILL.md里的allowed-tools改成execute然后在系统提示里故意不给其他工具。再跑一次观察 Agent 是否只用execute完成任务。如果它试图调用不存在的工具说明allowed-tools的引导没生效需要检查description是否写清了执行方式。4.3 验证渐进式披露这一步最能体现 Skills 的价值。在技能目录里再放一个reference/api-doc.md内容写详细参数说明但SKILL.md正文里只写详细参数见 reference/api-doc.md。跑一个简单请求观察 Agent 是否只在需要时才去读那个参考文件。如果它一上来就把整个参考文档读进上下文说明你的SKILL.md正文写得太啰嗦把该外置的内容留在了主文件里。提示验证阶段建议把temperature调到 0.2 以下减少模型自由发挥带来的干扰方便定位是配置问题还是模型随机性。跑通后你会看到类似这样的输出结构Agent 先输出一段我将使用 web-search 技能检索然后调用execute拿到脚本返回的 JSON 文本最后整理成带来源的回答。整个过程技能指令是按需注入的主提示词始终很轻。5. 本篇常见错排查5.1 技能没被加载检查 name 和文件夹名最常见的报错是 Agent 完全不知道技能存在。先确认SKILL.md的name字段符合规范小写字母、连字符、数字不能有下划线或空格。web_search这种写法会被跳过必须写成web-search。其次确认sources路径对FilesystemBackend的root_dir加上sources要能拼出技能文件夹的真实路径。5.2 技能被加载但从不调用description 没写清触发条件如果 Agent 知道技能存在却不用八成是description写得太泛。像用于搜索这种描述模型判断不出什么时候该用。改成当用户询问最新新闻、实时数据或需要联网检索时使用把触发场景写具体。这是 Agent 调用技能的第一道门值得反复打磨。5.3 脚本执行报错路径和权限技能脚本用相对路径时execute工具的工作目录要和脚本预期一致。建议在execute里显式设置cwd或者在SKILL.md里写绝对路径。另外virtual_modeTrue会限制文件访问范围如果脚本需要读技能目录外的文件要么调整root_dir要么把依赖文件放进技能文件夹。5.4 上下文还是爆了SKILL.md 正文太长Skills 的卖点是按需加载但如果你把 5000 字全塞进SKILL.md正文每次调用还是会把上下文撑满。正确做法是SKILL.md保持精简建议 5k tokens 以内详细 API 文档、代码示例放到reference/子文件夹正文里只写需要时查阅 reference/xxx.md。这样渐进式披露才真正生效。5.5 allowed-tools 没起作用它只是提示前面强调过allowed-tools目前是给模型的提示不是运行时强制。如果你需要硬约束得在工具层做权限校验比如在execute里拦截危险命令。别指望allowed-tools能挡住越权调用它只是引导模型往安全方向走。6. 把技能沉淀成团队资产下一步怎么走技能跑通之后真正有价值的是把它变成可共享、可版本管理的模块。我的做法是把skills/目录纳入 Git每个技能一个文件夹SKILL.md里写清契约脚本和参考文档放子目录。团队里谁需要某个能力直接把文件夹复制过去Agent 立刻具备对应技能不用改主程序一行代码。如果你要长期做编码类 Agent 或者多步骤自动化任务建议把模型接入也固定下来。TaoToken 的 Coding Plan 适合这种持续调用的场景配合技能模块能省不少调试成本。想先验证模型对话效果可以从 模型对话入口 试起。接入细节和参数说明都在 接入文档 里遇到报错先翻文档比瞎试快。最后留一个实用技巧技能写完后用真实任务做一轮评测记录哪些请求触发了技能、哪些没触发、输出是否稳定。基于评测结果迭代description和正文指令比凭感觉改有效得多。技能不是写完就完事它和代码一样需要持续维护。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →