高级 📋 6 个步骤 第 519 / 520 篇

Deep Agents 技能系统升级实操:Skill-Bound Tools、Pinned Skills 与线程内热更新

deepagents 0.7.22 把工具绑进技能:SKILL.md include_tools 按需披露保住提示缓存、pinned_skills 置顶免一轮 read_file、skills_metadata 置空热更新长会话技能库,附权限过滤与治理边界。

2026.10.10· 26 分钟阅读· 约 2760 字· 🧠 Deep Agents / 🧩 Agent Skills

技能(Skills)是当下给智能体灌领域知识的主流做法:一个文件夹、一份 SKILL.md,靠渐进式披露控制上下文成本。但 LangChain 在 10 月 7 日的官方博客里指出了企业规模下的三个真实痛点:技能和工具的披露是割裂的——智能体可能没读技能说明就乱调工具,或者读了说明还得自己去搜工具;用户明确点名要某个技能时,还得浪费一轮 read_file 往返;长会话跑着跑着,同事新加的技能它永远看不到。这次的 deepagents 更新把三件事补齐了:工具绑定技能(Skill-Bound Tools)、运行时置顶技能(Pinned Skills)与线程内技能热更新。官方自己的 GTM 智能体挂了五十多个销售技能,这套机制就是为那种规模设计的。本篇按官方博客路径,把三个能力逐个跑通。

🎯 适合人群:在用 deepagents 框架、技能库正在或即将膨胀的 Agent 开发者。前置要求:Python 环境;工具绑定与置顶相关能力需要 deepagents 0.7.22 及以上(线程内重载自 0.7.16 起支持),动手前先升级。

先理解:渐进式披露为什么需要这次改造

deepagents 里技能分三级加载:发现——启动时系统提示词里只有每个技能的名称与一句话描述,一个闲置技能在上下文里只占一行;激活——任务匹配到某个技能时,智能体用 read_file 读完整的 SKILL.md;执行——按指令需要再读 scripts、references 等附属文件。这套机制让上千个技能的库也能保持上下文轻盈。改造前的问题是工具不在这套体系里:工具列表是随请求整体给出的,技能里写的操作步骤对应不上按需加载的节奏。这次更新把工具纳入渐进式披露——绑定到技能的工具,在智能体读到该技能之前根本不出现在上下文里,提前调用会报未知工具错误;读到了,工具才随一条新系统消息进场。

版本敏感,先升级再动手。线程内热更新在 0.7.16(9 月 21 日)进入,工具绑定在 0.7.22(10 月 5 日)进入。本篇代码按官方博客叙事给出关键形态,SkillsMiddleware 的完整构造参数以你安装版本的官方 reference 为准——参数名在快速迭代期可能微调。

Step 1:升级并搭一个带技能库的基线 Agent

1 确认版本,准备技能目录
# 升级到带本次改造的版本
pip install -U deepagents
python -c "import deepagents; print(deepagents.__version__)"
# 工具绑定需 0.7.22+;热更新 0.7.16+ 即可

# 准备一个技能库目录
# ./skills/
# ├── call-transcripts/
# │   └── SKILL.md
# ├── meeting-prep/
# │   └── SKILL.md
# └── competitive-intel-card/
#     └── SKILL.md

每个技能就是「目录 + SKILL.md」:YAML frontmatter 写名称与描述,正文写智能体要遵循的操作指令。建一个常规的 deep agent,把技能库挂上,先确认基线行为:启动后系统提示词里只有三个技能的名字与描述,不读正文、不载工具。这就是后面所有改造的对照组。

💡 技能描述的质量直接决定命中率:描述里写清「什么时候该用我」,比堆关键词有效得多。智能体只凭这一行描述决定要不要读全文,写得含糊它就永远不激活。

Step 2:给技能声明工具绑定

2 frontmatter 里写 include_tools,工具交给 SkillsMiddleware
# skills/call-transcripts/SKILL.md
---
name: call-transcripts
description: 搜索销售通话记录并阅读转写文本,用于复盘与竞品情报整理
metadata:
  include_tools:
    - search_calls
    - get_transcript
---

# 通话转写使用规范

1. 用 search_calls 按客户名与日期范围检索
2. 用 get_transcript 拉取全文,引用时保留时间戳
3. 复盘输出按「异议—回应—结果」三段组织

关键接线变化:这两个工具不放进 Agent 的常规工具列表,而是传给 SkillsMiddleware,由它按技能激活节奏披露。官方博客的表述是把这些工具交给 SkillsMiddleware(tools=[...]) 而不是 Agent 本身;技能还可以用标签(labels)声明工具组,由解析函数映射到具体工具——比如「某台 MCP Server 上的全部工具」或「按用户权限过滤后的子集」,适合一个技能对应一批工具的场景。

💡 判断哪些工具该绑定:凡是「不读使用规范就容易用错」的工具都适合绑——转写检索、CRM 查询、报表生成这类有固定姿势的业务工具;纯计算、格式转换类无姿势工具留在常规列表即可,别为绑定而绑定。

Step 3:验证「先读技能,工具才出现」

3 未读先调报未知工具,读到后随新系统消息进场
# 验证对话一:不提技能,直接让智能体检索通话
# 预期:调用 search_calls 失败 —— 工具不在上下文,报未知工具

# 验证对话二:让智能体「按 call-transcripts 技能复盘上周通话」
# 预期:智能体读 SKILL.md,随后 search_calls 与 get_transcript
#       以一条新系统消息的形式加入对话,调用成功

这个顺序约束是本次改造的核心价值:智能体在能调用工具之前必然已经读过怎么用。另一个容易被忽略的收益在提示缓存上——过去往对话中途加工具,意味着修改请求的工具列表,整段前缀缓存作废,长对话重新计费;在 Anthropic 与 OpenAI 的较新模型上,绑定工具以新系统消息的形式追加在缓存前缀之后,前缀不动、缓存保住。其他模型走旧的追加行为,缓存会失效。

缓存保住与否取决于模型。官方明确「中途加工具不动缓存前缀」只在支持对话中途新增工具的 Anthropic 与 OpenAI 模型上成立;换别的提供商,工具照样能加载,但缓存失效的旧问题会回来。长会话成本敏感的话,选模型时把这一点算进去。

Step 4:Pinned Skills——用户点名即前置加载

4 斜杠命令由应用层解析,置顶发生在模型调用之前
# 用户输入 /meeting-prep 时,应用层识别命令后置顶技能:
result = agent.invoke(
    {"messages": [{"role": "user",
                   "content": "/meeting-prep 准备明天与华东客户的会议"}]},
    pinned_skills=["meeting-prep"],   # 指令在模型调用前就进上下文
)
# 置顶技能绑定的工具也会随之到位

置顶解决的是确定性问题:用户敲了 /meeting-prep,意图毫无歧义,没必要再让模型自己「发现并决定读哪个技能」——应用层直接把技能指令插进下一轮模型调用之前,省掉一轮 read_file 往返,行为从「模型自己挑」变成「应用保证加载」。注意分界:框架本身不解析斜杠命令,检测 /xxx 是你应用层的活,框架只负责置顶动作。

💡 置顶不仅省一轮往返,更是治理手段:内部客服系统可以把「工单处理规范」设为常置顶,保证每轮都带着规范干活,而不是赌模型每轮都记得去读。

Step 5:长会话热更新技能库

5 skills_metadata 置空,下一轮重扫技能库
# Python:强制本次调用重扫技能源
result = agent.invoke(
    {"messages": messages},
    skills_metadata=None,
)

# JavaScript 对应写法
# agent.invoke({ messages }, { skillsMetadata: null })

deepagents 会把发现阶段拿到的技能元数据存在 Agent 状态里,后续轮次复用——这本是省掉重复扫描的优化,副作用是长跑线程对增删改无感。置空 skills_metadata 后,下一轮运行会重扫配置的技能源并替换存量目录:同事刚提交的技能、刚改的描述、刚下线的旧版,全部即时生效,不用重开会话。适用场景是值班型长会话、跨天的多轮项目助理这类「会话活得比技能库变更周期长」的场合。

💡 重扫是有成本的:技能目录很大时,每次 invoke 都置空会让发现阶段开销回来。建议按需使用——收到技能库变更通知的那一轮再置空,平时保持缓存元数据。

Step 6:规模化之后,治理边界要想清楚

6 延迟加载管上下文,管不了权限与质量
# 团队技能库的三条治理建议
# 1) 技能入库走评审:SKILL.md 是指令,写错会稳定复现错误行为
# 2) 标签解析函数里做权限过滤:
#    用户权限不同,同一个 label 解析出的工具子集不同
# 3) 用正式环境做回归:技能或绑定关系变更后,
#    跑一遍标准任务清单,确认激活与工具调用行为没漂移

官方在博客里给这套机制的场景画得很清楚:技能库涨到几十上百个、跨团队共享、企业当资产管理时,绑定、置顶、热更新才真正发力;个人开发者三五个技能,感知不明显。同时要警惕一个误区——「工具延迟出现」不等于「工具受控」:权限校验、版本管理、测试与可观测性一样不能少,加载时机只是把暴露面收窄了。

提前调用失败是新契约的一部分。打开工具绑定后,任何「不读技能就调绑定工具」的路径都会报未知工具错误——这通常是对的(逼智能体先读说明),但如果你有外部编排逻辑绕过技能直接派活,要先把这些路径理顺,否则升级后会出现一批「莫名失败」的调用。

常见问题 FAQ

Q:置顶技能和让模型自己发现,怎么选?用户明确点名(斜杠命令、固定入口按钮)走置顶,确定且省一轮;开放任务让模型自己发现,靠描述匹配。两者共存:置顶是确定性通道,发现是兜底通道。

Q:绑定的工具会被计入每次请求吗?不会。绑定工具在技能被读取前不进上下文;读取后以新系统消息追加,支持中途加工具的模型上不影响缓存前缀。

Q:一个技能能绑几十个工具吗?技术上可以,但建议用 labels 走解析函数分组映射(比如整台 MCP Server 的工具、按权限过滤的子集),frontmatter 里逐个列名单在规模化后会难以维护。

Q:和工具搜索(tool search)冲突吗?不冲突,是两种披露策略:工具搜索按需检索全量工具池,绑定按技能组织披露。官方的定位是绑定让「工具与教会它使用方法的说明」同进同出,二选一或混用都行。

← 返回教程中心