langchain deepagents 框架使用带脚本的Skill

带脚本文件的 Skill 技能系统:原理、实践与避坑指南


一、📖 背景介绍

本文以 ArXiv 论文搜索 为实战案例,展示了如何在 deepagents 框架中使用带脚本文件的 Skill 技能,让 LangChain Agent 自动发现技能、读取技能说明、并通过 Python 脚本执行器工具完成实际搜索任务。

整个系统由三部分协同工作:

  • arxiv-search/SKILL.md:技能描述文件,告诉 Agent 该技能的功能与调用方式
  • arxiv-search/arxiv_search.py:实际执行搜索逻辑的 Python 脚本
  • execute_python_script:注册到 Agent 的工具,负责以子进程方式执行上述脚本

二、带脚本文件的技能原理

SKILL.md 格式对比

特性 纯文本技能 带脚本技能
SKILL.md 格式 YAML frontmatter + 使用说明 YAML frontmatter + 脚本调用命令
执行方式 Agent 直接按说明操作 Agent 读取说明后调用脚本执行工具
依赖工具 不需要额外工具 需要绑定 execute_python_script 工具
扩展能力 受限于 Agent 本身能力 可执行任意 Python 逻辑

技能文件结构

复制代码
skills_dir/
└── arxiv-search/
    ├── SKILL.md          ← 技能描述(YAML frontmatter + 调用说明)
    └── arxiv_search.py   ← 实际执行脚本

SKILL.md 的 YAML frontmatter 格式(关键):

markdown 复制代码
---
name: arxiv-search
description: Searches arXiv for preprints...
license: MIT
---

Run the bundled Python script:
.venv/bin/python [YOUR_SKILLS_DIR]/arxiv-search/arxiv_search.py "query" --max-papers N

执行流程

用户输入: 搜索 arXiv 论文
Agent 收到请求
系统提示词中有技能的描述
Agent 调用 read_file 读取 SKILL.md
Agent 解析调用命令格式
Agent 调用 execute_python_script 工具
工具用 subprocess 启动 Python 子进程
arxiv_search.py 执行 arXiv API 查询
子进程 stdout/stderr 返回给工具
工具将结果字符串返回给 Agent
Agent 整理输出结果给用户

脚本执行原理

arxiv_search.py Python subprocess execute_python_script Agent arxiv_search.py Python subprocess execute_python_script Agent command = "/path/arxiv_search.py 'query' --max-papers 5" shlex.split(command) → [path, 'query', '--max-papers', '5'] subprocess.run([sys.executable, path, args...]) 启动并执行 stdout 输出论文列表 returncode=0, stdout="Title:..." 返回论文列表字符串


三、运行时消息分析

系统提示词注入了 5 段内容:基础 Agent 角色、Todo 工具说明、文件操作规范、子 Agent 说明,以及最关键的第 5 段 Skills System,告知 Agent 当前可用的技能列表及读取方式。
execute_python_script 工具 read_file 工具 Agent 用户 execute_python_script 工具 read_file 工具 Agent 用户 系统提示词中看到 arxiv-search 技能条目 判断结果不够精确,换更精确查询词 请帮我在 arxiv 搜索深度学习在游戏领域的论文,返回5篇 读取 skills_dir/arxiv-search/SKILL.md 返回 SKILL.md 内容(含脚本调用命令) command = "arxiv_search.py 'deep learning games' --max-papers 5" 返回论文列表(混有不相关结果) command = "arxiv_search.py 'deep learning video games reinforcement' --max-papers 5" 返回更精准的论文列表 输出5篇相关论文

消息轮次说明:

轮次 角色 动作
0 HumanMessage 用户提问
1 AIMessage Agent 决定先读取技能文件
2 ToolMessage 返回 SKILL.md 内容
3 AIMessage Agent 解析命令,调用执行工具
4 ToolMessage 返回第一次搜索结果(不够精确)
5 AIMessage Agent 自主判断需要优化查询词
6 ToolMessage 返回第二次更精准搜索结果

四、易错问题与解决方案

问题 1:SKILL.md 格式错误,技能无法加载

错误现象: 技能没有被 SkillsMiddleware 加载,Agent 感知不到技能。

原因: SKILL.md 使用了 Markdown 表格格式,而不是 YAML frontmatter 格式。

markdown 复制代码
# ❌ 错误格式(表格)
| name | description |
|------|-------------|
| arxiv-search | ... |

# ✅ 正确格式(YAML frontmatter)
---
name: arxiv-search
description: ...
---

问题 2:工具过度设计,引入不必要的 Pydantic 模型

错误现象: 出现 PydanticJsonSchemaWarning: Default value is not JSON serializable

原因: 对一个只有路径字符串输入的简单工具,使用了复杂的 ExecutePythonInput(BaseModel) + args_schema,导致序列化失败。

解决方案: 简单工具直接用 @tool 装饰器,无需 Pydantic 模型。


问题 3:args_schemaBaseTool 的保留字段,被 LLM 误用为参数名

错误现象(反复出现):

python 复制代码
# LLM 始终传递
{'args_schema': '/path/to/script.py "query" --max-papers 5'}
# 导致 Pydantic 报错
args_schema: Input should be a subclass of BaseModel

原因: args_schemaBaseTool 的内置属性,Pydantic 验证时把 LLM 传来的字符串值直接赋给该属性(期望是 BaseModel 子类),而不是转发给 _run 方法。LLM 之所以用这个名字,是因为在未显式声明 schema 时,LangChain 会把整个类属性(包括 BaseTool.args_schemaBaseTool.description)都暴露在 tool schema 中,LLM 从中错误推断出参数名。

解决方案: 彻底放弃 BaseTool,改用 @tool 装饰器:

python 复制代码
# ❌ 有隐患
class ExecutePythonTool(BaseTool):
    args_schema = ExecutePythonInput  # 保留字,LLM 被误导

# ✅ 彻底解决
@tool
def execute_python_script(command: str) -> str:
    """..."""  # LLM 只看到 command 一个参数

问题 4:LLM 使用 description 作为参数名

错误现象:

python 复制代码
{'args': {'description': '/path/to/script.py "query" --max-papers 5'}}

原因: 使用 BaseTool 且没有显式 args_schema 时,LangChain 自动推断 schema 会把父类的 description: str 字段也暴露出来,LLM 误认为这是输入参数名。

解决方案: 同上,使用 @tool 装饰器彻底规避。


易错点总结


否,使用 @tool 装饰器
定义 LangChain 工具
使用 BaseTool 继承?
⚠️ 风险: args_schema / description 字段名冲突
LLM 误用保留字段名传参
❌ Pydantic 验证失败
✅ 只暴露函数参数名给 LLM
LLM 正确传递 command 参数
✅ 工具正常执行


五、参考资料

资料 说明
LangChain Tools 文档 @tool 装饰器与 BaseTool 的正确使用方式
Agent Skills 规范 SKILL.md YAML frontmatter 格式标准
Pydantic v2 文档 BaseModel、Field 的正确使用方式
deepagents.middleware.skills 源码 SkillsMiddleware 加载逻辑:扫描子目录 → 解析 YAML frontmatter → 注入系统提示
langchain_core.tools.base.BaseTool 源码 args_schemadescription 等保留字段定义,_parse_input 工作原理
相关推荐
量子位2 小时前
字节版龙虾架构火爆GitHub!开源获35k+ Star,内置Skill全家桶,原生适配飞书
github·ai编程
楠木6852 小时前
RAG 资料库 Demo 完整开发流程
前端·ai编程
幸福的猪在江湖3 小时前
🚀 Claude Code 入门完全指南(一):安装与首次体验
aigc·ai编程
岛雨QA3 小时前
Skill学习指南🧑‍💻
人工智能·agent·ai编程
多年小白4 小时前
今日AI科技简报 | 2026年3月19日
人工智能·科技·ai编程
冗量4 小时前
langchain的学习路径
python·langchain
小仓桑4 小时前
【Agent智能体项目实战五】LangChain访问阿里云嵌入模型
langchain·agent
蔚天灿雨5 小时前
Kage:在 Codex、Claude 和 QoderCLI 等 CodingAgentCLI 之间 Fork 与迁移 Session
人工智能·ai·agent·ai编程
AI成长日志5 小时前
【Vibe Coding专栏】easy-vibe与vibe-vibe对比分析:两大vibecode项目技术架构、适用场景与选型指南
架构·ai编程