6.2 Skill 在 LangChain 中的使用#
在第 6.1 节中,我们围绕 Skill 的概念、目录结构以及它与 Prompt、Tool 之间的区别进行了系统介绍。可以看到,Skill 的核心价值在于把一类任务所需的方法、规则和参考材料沉淀为可复用的能力单元,从而让智能体在面对复杂任务时不必从零组织行为。
在本节内容中,我们将以 LangChain 提供的 deepagents 库为基础,介绍 Skill 在工程层面的加载与调用方式。在介绍过程中,我们会先解释 Skill 在 Agent 内部是如何被暴露与匹配的,再说明 create_deep_agent、LocalShellBackend 与 Skill 之间的关系,最后通过一段完整示例串联起从注册到执行的完整流程。
6.2.1 Skill 在 Agent 中的加载机制#
要理解 Skill 的使用方式,首先需要明确它在大模型运行时是如何被“看到”的。在第 4.2 节中介绍 Function Calling 时,我们已经看到,工具之所以能够被模型调用,是因为它被显式注册到了工具列表中,模型会看到每个工具的名称、说明和参数 schema,并在需要时发出调用请求。Skill 与之有相似之处,但存在两个关键差异。
第一,Skill 不是被立刻注册到工具列表里的原子能力,而是以一段可读说明的形式被预先暴露给模型。LangChain 会在创建 Agent 时把每个 Skill 目录中的 SKILL.md 解析出来,并将其中 name 与 description 两个字段拼接到系统提示词中。这样,模型在每一次推理时都能看到当前可用的 Skill 列表及其用途描述,但此时 Skill 还没有真正参与对话。
第二,Skill 的真正启用是由模型在推理过程中根据用户问题与 Skill 描述的匹配程度自主决定的。当用户提出与某个 Skill 描述高度契合的问题时,模型会主动决定加载该 Skill;加载完成后,Skill 中 SKILL.md 的正文内容、参考说明以及辅助脚本会被注入到上下文里,作为本轮对话的执行依据。
理解这两点之后,可以把 Skill 在 Agent 中的运行流程概括为图 6-2 所示的3个阶段:先暴露描述,再按需加载,最后依据正文完成执行。需要说明的是,这一流程并不改变 Agent 内部已经具备的 ReAct 循环结构,Skill 只是为模型在循环中提供了更高层的方法指导。
6.2.2 DeepAgents 介绍#
在介绍完 Skill 都加载机制以后,我们再来看如何使用 L angChain 中的 create_deep_agent 来载入 Skill 文件。在 LangChain 中,深度智能体(Deep Agent)由 deepagents.create_deep_agent 工厂函数统一创建。create_deep_agent 本质上仍然是基于 LangGraph 实现的,因此它具备第 4.9 节中介绍过的状态管理、消息循环与工具调用能力。create_deep_agent 与第 5.10 节中介绍过的 create_agent 的差异在于,前者在单一智能体的基础上进一步提供对文件系统、子任务和 Skill 的内建支持,从而更适合承担长链路、跨步骤的复杂任务。
在通过 create_deep_agent 创建 Agent 时至少需要提供3个核心参数:模型(model)、后端(backend)以及 Skill 列表(skills),其中:
-
model用于指定驱动 Agent 的大模型。它可以是任何符合 LangChainBaseChatModel接口的对象,例如我们在前面章节中已经多次使用过的千问大模型。 -
backend用于指定 Agent 执行文件操作、命令运行等副作用动作时所依赖的执行环境。在deepagents中,Backend 是一类可插拔的抽象实现,开发者既可以选择一个隔离的沙箱后端,也可以直接让 Agent 操作本地文件系统。在本节示例中,我们使用的是LocalShellBackend,它会将 Agent 的所有文件操作与命令执行限制在指定的根目录root_dir之下。 -
skills是一个字符串列表,列表中每个元素都对应一个 Skill 目录路径。LangChain 会按照第 6.1 节中介绍的目录结构解析每个 Skill,并把解析出的name与description拼接到系统提示词中。LocalShellBackend之所以重要,是因为 Skill 在被加载之后,其内部往往需要执行脚本、读取参考文件甚至生成产物,这些动作都依赖于 Agent 拥有一个明确的执行环境。
6.2.3 基于 Skill 的 Agent 调用流程#
在介绍完相关原理机制以后,接下来介绍如何使用 create_deep_agent 来载入我们在第6.1节中介绍过的 Skill ,并完成相应的任务。现在,假设我们希望让一个 Agent 在接收到“解释 e^x 性质”这样的请求时,能够自动调用 Skill 完成解释,并生成对应的 html 解释页面,示例代码如下:
1 from deepagents import create_deep_agent
2 from deepagents.backends.local_shell import LocalShellBackend
3 from langchain_core.tracers import ConsoleCallbackHandler
4 from qwen import get_llm_model
5
6 if __name__ == '__main__':
7 backend = LocalShellBackend(root_dir="./")
8 agent = create_deep_agent(
9 model=get_llm_model(model='qwen3.7-plus'),
10 backend=backend, skills=["./skills/"])
11 result = agent.invoke(
12 {"messages": [{"role": "user", "content": "请解释一下e^x这个函数的性质"}]},
13 config={"configurable": {"thread_id": "1"},
14 "callbacks": [ConsoleCallbackHandler()]})
15 print("\n\n========>")
16 print(result)在上述代码中,第 7 行实例化 LocalShellBackend 并将其根目录设置为当前工程目录。root_dir 的作用是限制 Agent 后续所有文件操作与命令执行都发生在当前目录之内,从而避免误操作扩散到工程之外。这一行也是 Skill 真正能够安全执行其内部脚本的前提条件。第 8~10 行调用 create_deep_agent 创建一个深度智能体,并把模型、后端和 Skill 目录一次性传入,其中 get_llm_model 返回一个经过认证的千问大模型实例,该函数在前面的章节中已经多次出现,这里就不再赘述。
同时,在 create_deep_agent 内部,LangChain 会完成以下 3 件准备工作:① 扫描 skills=["./skills/"] 指定的目录,解析每个 Skill 的 SKILL.md,把 name 与 description 拼入系统提示词;② 初始化一个基于 LangGraph 的状态图,用于承载后续的消息循环与状态管理;③ 将 LocalShellBackend 接入到状态图中,使 Agent 具备执行文件操作与命令运行的能力。
第 11~14 行调用 agent.invoke 发起一次完整对话,其中指定 callbacks 参数时为了输出整个过程的调试信息,便于我们观察,完整内容可参见 Code/Chapter06/C01_skill_usage_output.txt 文件。
最后,当整个过程执行完毕以后,将会在 /tmp 目录下生成一个名为 math-ex-demo 的文件夹,里面包含数据文件 data.json 和可视化页面 index.html 。 使用浏览器打开 index.html 文件后,就回看到类似如图6-3所示的内容。
以上完整示例代码及技能文件可参见 Code/Chapter06/C01_skill_usage.py 文件。
6.2.4 小结#
至此,关于 Skill 的基本使用方法就介绍完了。可以看到,Skill 的真正威力并不只在于它被注册到了 Agent 上,而在于它把任务方法、参考材料与执行脚本沉淀为可复用的能力单元,从而让 Agent 能够在面对重复性复杂任务时保持稳定输出。在后续章节中,我们将进一步介绍 MCP 等更高层次的能力扩展机制。
引用#
[1] LangChain. Skills (Deep Agents). https://docs.langchain.com/oss/python/deepagents/skills
[2] LangChain. Skills (Multi-agent). https://docs.langchain.com/oss/python/langchain/multi-agent/skills
[3] LangChain. create_deep_agent API Reference. https://docs.langchain.com/oss/python/deepagents/reference