[DeepAgents:LangChain的Harness-05]通过SkillsMiddleware将Skill引入LangChain

📅 2026/7/4 20:44:31
[DeepAgents:LangChain的Harness-05]通过SkillsMiddleware将Skill引入LangChain
Agent Skills是一种将专业领域知识、复杂工作流规范和操作指令进行打包封装的模块化工具。如果把LLM比作一个聪明但缺乏行业经验的应届生那么Agent Skills 就像是一本专门针对特定岗位的操作手册或SOP让智能体在特定场景下能像专家一样按规范执行任务。Agent Skills借助于渐进式披露Progressive Disclosure的设计原则将技能的元数据名称、描述、许可信息、兼容性信息、其他元数据和允许使用的工具集等和技能的主体内容详细说明和使用指导进行分离使得LLM能够在不被冗余信息干扰的情况下先了解技能的大致情况在需要时再深入了解技能的具体内容从而更高效地利用技能来完成任务。1. Agent Skills规范Agent Skills本质上是一个结构化的Markdown文件通常名为SKILL.md它不仅包含文字说明还支持代码逻辑和元数据。DeepAgents Skills遵循Agent Skills规范此规范为Skills定义了一个约定结构的目录此目录下存储的文件包含Agent可以使用的上下文信息SKILL.md核心文件定义了该技能什么时候用以及具体怎么做指令与工作流告诉AI处理特定问题的具体步骤如代码重构、周报撰写、数据分析流程辅助文件可选的脚本、示例代码或模板增强技能的落地能力。Agent Skills通过SkillsMiddleware以及作为辅助的FilesystemMiddleware引入DeepAgents。在正式介绍SkillsMiddleware的设计和实现原理之前我们先通过一个简单实例演示来感受一下Skills在LangChain中的编程体验。2. 基于Agent Skills的翻译助手在如下这个简单的演示实例中我们采用了一种极简的方式使用SkillsMiddleware旨在让大家体验一下Skills遵循的渐进式披露原则以及实现的方式。我们在StateBackend(详见“构建抽象的文件系统”)中创建了一个名为translator的Skill文件/skills/translator/SKILL.md用于指导LLM进行中文诗词的翻译。然后我们创建了一个Agent并在其中注册了SkillsMiddleware和FilesystemMiddleware(需要利用它提供的文件读取工具)。我们调用Agent来执行一个翻译任务从输出可以看出LLM完全是根据translatorSkill文件中提供的上下文信息来完成翻译任务。fromlangchain.agentsimportcreate_agentfromdeepagents.backends.stateimportStateBackendfromdeepagents.middlewareimportSkillsMiddleware,FilesystemMiddlewarefromdeepagents.backends.utilsimportcreate_file_datafromlangchain_openaiimportChatOpenAIfromdotenvimportload_dotenvimportasyncio load_dotenv()skill\ --- name: translator description: 能够将中文精确翻译成地道的英文。 --- # 详细指令 1. 具有**禅宗**风格。 2. 尽量能够*押韵*。 3. 提供 2-3 种翻译变体。 skills_files{/skills/translator/SKILL.md:create_file_data(skill)}skills_middlewareSkillsMiddleware(backendlambdart:StateBackend(rt),sources[/skills/])agentcreate_agent(modelChatOpenAI(modelgpt-5.2-chat),middleware[skills_middleware,FilesystemMiddleware()]# pyright: ignore[reportArgumentType])prompt\ 把这句诗翻译成英文千江同一月万户尽皆春。千江有水千江月万里无云万里天。 尽量使用translatorSkill来完成翻译。 asyncdefmain():resultawaitagent.ainvoke(input{messages:[{role:user,content:prompt}],files:skills_files})# type: ignoreformessageinresult[messages]:message.pretty_print()asyncio.run(main())输出 Human Message 把这句诗翻译成英文千江同一月万户尽皆春。千江有水千江月万里无云万里天。 尽量使用translatorSkill来完成翻译。 Ai Message Tool Calls: read_file (call_5YYt7rWIMum6ESA9fgMWgha8) Call ID: call_5YYt7rWIMum6ESA9fgMWgha8 Args: file_path: /skills/translator/SKILL.md offset: 0 limit: 200 Tool Message Name: read_file 1 --- 2 name: translator 3 description: 能够将中文精确翻译成地道的英文。 4 --- 5 6 # 详细指令 7 8 1. 具有**禅宗**风格。 9 2. 尽量能够*押韵*。 10 3. 提供 2-3 种翻译变体。 Ai Message 下面是基于 **translator** Skill要求禅宗风格、尽量押韵、提供多种变体给出的英文翻译供你选择或对比 --- ### 译文一偏禅意较自由押韵明显 *One moon reflects in rivers ten thousand wide, Spring fills each home on every side. Where there is water, there the moon appears; Where clouds are gone, the boundless sky is clear.* --- ### 译文二较忠实原意节奏平衡轻微押韵 *One moon shared by a thousand streams, Ten thousand homes bathed in spring’s dreams. A thousand rivers hold a thousand moons, Ten thousand miles of sky where no cloud looms.* --- ### 译文三更凝练偏现代诗感禅意含蓄 *One moon, a thousand rivers the same light; Ten thousand homes, all touched by spring tonight. Where water is, the moon is found; Where clouds are not, the sky knows no bound.* --- 如果你有**特定使用场景**比如书法题款、诗集发表、学术翻译或冥想文本我可以再帮你进一步调整语气或风格。3. 基于Skills的渐进式披露是如何实现的每个Skill包含元数据名称、描述和可用工具集等和主体内容元数据在Skill文件的前言部分以YAML格式定义主体内容则是对Skill的详细说明和使用指导。所有Skill的元数据被全量加载并作为系统提示词的一部分但是在整个会话周期内只会加载一次但是主体内容则采用按需加载这就是Skills模式遵循渐进式披露原则的一个主要的体现。由于提示词会引导LLM使用FilesystemMiddleware提供的read_file工具来读取translator.md的内容所以LLM回复的AIMessage中会携带一个针对read_file工具调用的ToolCall对象它的参数file_path指向translator.md文件的路径。Agent完成工具调用后Skill文件的内容以ToolMessage的形式被添加到对话历史中进而称为提示词的一部分提交给LLM。我们先来看看SkillsMiddleware的state_schema字段返回的状态类型SkillsState。派生于AgentState的SkillsState包含唯一的字段skills_metadata用于存储当前已加载的技能的元数据列表包括路径、名称、描述、许可信息、兼容性信息、其他元数据和允许使用的工具集等。classSkillsMiddleware(AgentMiddleware[SkillsState,ContextT,ResponseT]):state_schemaSkillsStateclassSkillsState(AgentState):skills_metadata:NotRequired[Annotated[list[SkillMetadata],PrivateStateAttr]]classSkillMetadata(TypedDict):path:strname:strdescription:strlicense:str|Nonecompatibility:str|Nonemetadata:dict[str,str]allowed_tools:list[str]当我们调用__init__方法创建SkillsMiddleware实例时需要利用backend和sources参数提供存储Skill文件的后台存储和目录列表。SkillsMiddleware通过重写的before_agent/abefore_agent方法来加载Skill元数据并通过返回的SkillsStateUpdate将它们写入Agent的状态中。为例避免重复Skill元数据的重复加载before_agent/abefore_agent会通过验证当前状态是否包含skills_metadata来确定是否之前已经完成了加载工作。classSkillsMiddleware(AgentMiddleware[SkillsState,ContextT,ResponseT]):def__init__(self,*,backend:BACKEND_TYPES,sources:list[str])-Nonedefbefore_agent(self,state:SkillsState,runtime:Runtime,config:RunnableConfig)-SkillsStateUpdate|Noneasyncdefabefore_agent(self,state:SkillsState,runtime:Runtime,config:RunnableConfig)-SkillsStateUpdate|Nonedefwrap_model_call(self,request:ModelRequest[ContextT],handler:Callable[[ModelRequest[ContextT]],ModelResponse[ResponseT]],)-ModelResponse[ResponseT]asyncdefawrap_model_call(self,request:ModelRequest[ContextT],handler:Callable[[ModelRequest[ContextT]],Awaitable[ModelResponse[ResponseT]]],)-ModelResponse[ResponseT]classSkillsStateUpdate(TypedDict):skills_metadata:list[SkillMetadata]Skill元数据会按照预定义的模板进行格式化并在重写的wrap_model_call/awrap_model_call方法中被注入到系统提示词中以指导LLM在推理过程中合理地调用和使用Skill。指导LLM调用read_file工具来读取Skill文件内容的提示词也是其中一个重要部分。对于我们的例子Skills相关的提示词会是如下这段文本调用read_file工具来读取Skill文件的奥秘就体现在这句话Read/skills/translator/SKILL.mdfor full instructions中。## Skills System You have access to a skills library that provides specialized capabilities and domain knowledge. **Skills Skills**: /skills/ (higher priority) **Available Skills:** - **translator**: 能够将中文精确翻译成地道的英文。 - Read /skills/translator/SKILL.md for full instructions **How to Use Skills (Progressive Disclosure):** Skills follow a **progressive disclosure** pattern - you see their name and description above, but only read full instructions when needed: 1. **Recognize when a skill applies**: Check if the users task matches a skills description 2. **Read the skills full instructions**: Use the path shown in the skill list above 3. **Follow the skills instructions**: SKILL.md contains step-by-step workflows, best practices, and examples 4. **Access supporting files**: Skills may include helper scripts, configs, or reference docs - use absolute paths **When to Use Skills:** - Users request matches a skills domain (e.g., research X - web-research skill) - You need specialized knowledge or structured workflows - A skill provides proven patterns for complex tasks **Executing Skill Scripts:** Skills may contain Python scripts or other executable files. Always use absolute paths from the skill list. **Example Workflow:** User: Can you research the latest developments in quantum computing? 1. Check available skills - See web-research skill with its path 2. Read the skill using the path shown 3. Follow the skills research workflow (search - organize - synthesize) 4. Use any helper scripts with absolute paths Remember: Skills make you more capable and consistent. When in doubt, check if a skill exists for the task!