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 工作原理
相关推荐
kishu_iOS&AI8 小时前
LLM —— LangChain
人工智能·langchain
DO_Community8 小时前
Mythos级最强 AI 模型 Claude Fable 5 现已上线 DigitalOcean无服务器推理
人工智能·serverless·agent·ai编程·claude
木白CPP9 小时前
Claude Code 自用高效插件
ai·ai编程
沉默王二9 小时前
老板:“你是怎么使用 AI 的,真能做到不手写代码?为什么 Codex 在我手里感觉是个智障。。”我:“这样,然后再这样。。”老板直接跪了。
人工智能·agent·ai编程
老梁agent9 小时前
Agent 返回 JSON 而不是闲聊:LangChain4j 结构化输出实战
物联网·langchain
peterfei9 小时前
我把 12 个经典方法论做成了 AI Skill,现在你一句话就能激活一套思维框架
ai编程
DC大锅9 小时前
Claude Code 安装教程
ai编程
AI原来如此10 小时前
Claude Opus与GPT-5激战,国内API中转站如何应对2026模型迭代潮?
大数据·人工智能·gpt·ai·大模型·ai编程
打小就很皮...10 小时前
基于 Python + LangChain + React 实现智能发票识别与验真系统实战
前端·react.js·langchain·ocr·发票识别