基于SKILL.md的深度智能体:一种可加载技能的LangChain协调器
在LangChain上构建一个通用的深度智能体,它能扫描技能文件夹,根据SKILL.md描述进行路由,共享AGENTS.md中的记忆,并且无需修改代码即可获得新能力。
如果一个智能体没有固定的能力列表,只能通过观察周围环境来发现自己的能力会怎样?这里采用的就是这样的方法:在 LangChain 上构建一个可运行的深度智能体,它根据需求加载 SKILL.md 文件来回答查询。没有硬编码的流程链,也没有自定义的路由器,只有一个通用的协调器、一个存放技能的文件夹,以及负责处理复杂任务的 deepagents 库。
固定工具集的问题
大多数 LangChain 教程都采用相同的步骤:定义一些工具,将它们绑定到模型上,构建一个图结构,这样就完成了。这样得到的智能体只是表层智能体,其能力列表被固定在了代码中。
另一种方案是使用那种在检查之前并不知道自己能做什么的协调器。在运行时,它会扫描skills/目录,先读取元数据,只有当某个技能符合请求时才会加载完整指令。无需硬编码“该智能体负责研究并撰写内容”,只需将research/SKILL.md和writer/SKILL.md放入相应文件夹,智能体便会自行处理其余工作。明天你可以添加一个code-reviewer技能,而无需修改任何代码它就能被识别使用。这正是SKILL.md模式在LangChain中的应用。
各组件如何协同
agent.py的运行流程由四个核心理念驱动:
- 首先进行规划。协调器总会先制定计划,将用户的宏观目标转化为具体的技术步骤。
SkillsMiddleware逐步获取这些技能,并仅在需要时加载完整文档。./workspace/目录内以保持数据持久性,而根目录则保留用于配置和存储技能。整个项目结构简洁,仅三个文件即可完成核心功能。
步骤1:项目设置
依赖项存储在pyproject.toml中:
# pyproject.toml
[project]
name = "deep-agents-langchain"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"deepagents>=0.4.12",
"langchain-anthropic>=1.4.0",
"langchain-openai>=1.1.12",
"python-dotenv>=1.2.2",
"streamlit>=1.55.0",
"tavily-python>=0.7.23",
]
最主要的是 deepagents,这是 LangChain 的开源库,用于实现深度智能体模式。它开箱即用,可提供通过 write_todos 进行的规划功能、文件系统工具、通过 task 创建子智能体、上下文压缩功能,以及非常重要的技能加载功能。
步骤 2:定义工具
在 agent.py 中,唯一的自定义工具是一个标准的 Tavily 搜索封装:
import os
from typing import Literal
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI
from tavily import TavilyClient
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
load_dotenv()
# --- Generic Tools ---
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
def internet_search(
query: str,
max_results: int = 5,
topic: Literal["general", "news", "finance"] = "general",
):
"""Search the web for current information."""
return tavily.search(query, max_results=max_results, topic=topic)
其他所有内容,包括规划、文件读写、子智能体以及技能加载,都来自 deepagents。
第3步:智能体工厂
所有组件都在这里整合在一起:
def get_deep_agent():
model = ChatAnthropic(
model="claude-3-5-sonnet-20240620",
temperature=0,
)
return create_deep_agent(
model=model,
system_prompt="""You are a generic Deep Agent orchestrator.
1. Use `write_todos` to plan complex requests.
2. You have access to skills in the `skills/` directory.
- You ONLY see names and descriptions initially.
- For specialized tasks, load the matching SKILL.md first.
3. Use the `task` tool to delegate to subagents.
4. ALL outputs go to `./workspace/` exclusively.""",
tools=[internet_search],
skills=["./skills"], # <-- This is the magic line
memory=["./AGENTS.md"],
backend=FilesystemBackend(root_dir="."),
name="generic_deep_agent",
)
有三个参数值得仔细研究。
skills=[“./skills”]会指示deepagents扫描该目录,解析其中每个SKILL.md文件中的YAML前置信息,并将技能目录放入系统提示中。智能体看到的内容大致如下:
Available Skills:
- research: "Conducts comprehensive web research on any topic..."
- writer: "Specialized in writing high-quality content..."
这两项技能的成本约为200个令牌。智能体会读取目录并决定为该请求加载哪项技能。这纯粹是LLM路由机制,不使用任何分类器、嵌入向量或正则表达式。
memory=[“./AGENTS.md”]会将项目级的规范加载到系统提示中。它作为主智能体及所有子智能体的共享上下文,相当于团队内部的“工作规范”页面。
backend=FilesystemBackend(root_dir=”.”)为智能体提供基于项目文件夹的文件操作工具(read_file、write_file、edit_file),从而使文件系统成为智能体的持久工作空间。
第4步:编写技能
一个设计得极为简单的检索技能:
---
name: research
description: >
Conducts comprehensive web research on any topic using search APIs
and web scraping. Use when the user asks for research, information
gathering, competitive analysis, or needs current data from the web.
license: MIT
compatibility: Requires internet access and Tavily API key
allowed-tools: internet_search Read Write
---
# Web Research Skill
## Instructions
1. Parse the research query to identify key topics.
2. Use the `internet_search` tool to gather initial results.
3. If results are insufficient, try alternative search queries.
4. Synthesize findings into a structured summary.
5. Save detailed findings to `./workspace/` as a markdown file.
还有写作技巧:
---
name: writer
description: >
Specialized in writing high-quality, creative, and technical content.
Use when the user needs a blog post, report, technical guide,
or any form of structured writing.
license: MIT
---
# Creative Writer Skill
## Instructions
1. Review the input notes or research data provided.
2. Define an outline (Introduction, Body, Conclusion).
3. Use a tone appropriate for the target audience.
4. Ensure all claims are backed by provided data.
5. Save the final draft to `./workspace/`.
每个文件都包含 YAML 格式的前置信息,用作该技能的“身份证”,其后是作为操作指南的 Markdown 正文。智能体首先读取一级的前置信息,只有在二级时才会读取正文内容。这一设计遵循 agentskills.io 发布的规范。
第 5 步:AGENTS.md 中的共享内存
该文件始终会被加载。它明确了每个智能体的职责以及团队的运作方式:
# Project Context: Deep Agents Demo
## Conventions
- Skills are stored as directories under `skills/`.
- Every skill must have a `SKILL.md` file.
- Subagents should be used for complex, multi-step tasks.
- All intermediate work goes to `./workspace/`.
## Known Entities
- **Main Agent**: The orchestrator who plans and delegates.
- **Researcher**: Specialized in web search and data aggregation.
- **Writer**: Specialized in formatting and synthesizing information.
路由机制的实际运作方式
不存在路由器或分类器,因为路由工作是由大语言模型本身完成的。当库构建系统提示时,会添加类似如下的文本:
You have access to a library of skills in the `skills/` directory.
You ONLY see names and descriptions initially.
For any specialized task, look for matching skills and use
`read_file` to load the SKILL.md before executing.
Available skills:
- research: "Conducts comprehensive web research..."
- writer: "Specialized in writing high-quality content..."
模型会读取用户的消息和技能描述,然后决定是调用 read_file("skills/research/SKILL.md") 还是不进行任何操作。整个决策过程都在变换器的前向传播过程中完成,无需外部逻辑介入。换句话说,技能描述就是路由引擎,只要编写得当并包含触发词与否定边界即可。
Streamlit 前端
app.py 将所有内容封装在 Streamlit 界面中,实时展示智能体的思考过程。LangGraph 的 stream("updates") 会在每个节点执行时生成一个事件,应用程序会将这些事件解析为工具调用、技能加载状态、计划更新以及最终响应。
无需修改代码即可添加技能
假设你需要一个代码审查技能,只需在其他技能文件夹旁边创建一个新的文件夹即可:
skills/
├── research/
│ └── SKILL.md
├── writer/
│ └── SKILL.md
└── code-reviewer/
└── SKILL.md
然后编写它的 SKILL.md 文件:
---
name: code-reviewer
description: >
Reviews code for bugs, security issues, and best practices.
Use when the user asks for a code review, security audit,
or wants feedback on code quality. Do NOT use for writing
new code or debugging runtime errors.
license: MIT
allowed-tools: Read Write
---
# Code Review Skill
## Instructions
1. Read the target file using `read_file`.
2. Analyze for: bugs, security issues, performance, readability.
3. Write a structured review to `./workspace/review.md`.
重新启动应用后,智能体就知道如何审查代码了。agent.py以及系统提示语都未被修改,你只是添加了一个文件夹而已。同样的方法可以用来打造更复杂的深度智能体。
从中得到的经验
- 技能描述比技能指令更重要。如果描述不够清晰,该技能就永远不会被触发。调整
description字段中的触发词以及“禁止用于……”之类的负面限制条件,所花费的时间比编写技能内容本身还要长,因为技能内容才是决定执行逻辑的关键。 - 文件系统的重要性常常被低估。许多智能体教程都将所有内容都保存在消息历史中,这种方式只适合简单的演示,无法应对多步骤任务。将中间结果保存到
./workspace/并让子智能体读取这些结果,才能确保各部分能够正确协同工作。
AGENTS.md负责将各部分整合在一起。如果没有这个文件,协调器及其子代理将各自独立工作;有了它,它们就能共享规范、了解项目结构,避免重复劳动,这是一个虽小却作用巨大的文件。生产版本还会添加什么
这款应用刻意保持了极简设计。实际部署时可能会加入 LangMem 提供的持久化存储功能,以实现跨会话的事件与语义检索;集成 MCP 以支持 Slack、Jira 和数据库等企业工具;利用 LangGraph 的中断机制设置人工干预检查点;针对长时间的研究任务进行上下文压缩;当然还有更多技能模块,每个模块都只是一个包含 SKILL.md 文件的文件夹。
发展方向似乎很明确:构建智能体并非在于编写更多代码,而在于撰写更优质的 SKILL.md 文件。框架负责底层实现,技能模块承载专业知识,而大语言模型则决定何时使用哪种技能。