第12讲 · 工具注册表与执行流水线

《DeepSeek Harness 从上手到精通》系列 · 第四阶 工具开发篇

🎯 目标:理解工具从"被点名"到"结果返回"的完整链路 难度 ★★☆ ⏱ 约 25 分钟 前置:第 11 讲已写好自定义工具

第 11 讲里,我们写了一个工具并挂到了 ctx.tools 上。但"挂上去"只是故事的开头——模型为什么会挑中它?点名之后谁来把关?结果怎么回到模型上下文?本讲把这条链路从头到尾拆开看。系列基于 deepseek-ai/deepseek-harness0.1.0-rc.5,MIT),preview 阶段接口可能微调,以官方 README 为准。


一、作用域化注册表:每个 agent 有自己的"工具抽屉"

dsh 的工具不是挂在一个全局大池子里、谁都能用。它维护的是一张作用域化注册表:不同的 agent(主 agent、subagent、不同 profile 下的 agent)能看到不同的工具子集。

这带来两个直接好处:

  • 隔离:给子代理只暴露它该用的工具,避免它误调危险命令;
  • 聚焦:工具越少,模型"挑错工具"的概率越低,调用更准。
工具注册表与执行流水线
图 1 模型点名 → 作用域注册表查找 → 把关流水线 → 执行 → 事件记录 → 结果回填。

第 8–9 讲我们用 patch.yml 从注册表"摘除"内置工具,本质上就是在改这张作用域注册表。理解这一点,定制就从"玄学"变成"改配置"。

二、把关流水线:guard → approval → 执行 → 把关记录

模型挑中一个工具后,并不会立刻执行。dsh 会依次经过一道流水线:

环节作用典型用途
guard静态前置校验,不弹窗参数非法、频率超限、作用域不符
approval敏感操作弹审批(第 2/10 讲)写文件、跑命令、联网
执行真正调用你的函数业务逻辑本身
事件记录tool/* 事件可审计、可 resume

关键区别:guard 是静默的,校验不过直接拒绝、不弹窗;approval 才是会打断流程、等你点头的那道。本讲的"产出"就落在 guard 上。

三、tool-catalog:知道自己这套配置下有哪些工具

dsh 有一个生成式目录 tool-catalog.md,它会根据你当前的 profile / patch 自动列出"此刻模型能看到的全部工具"。这是排查"模型为什么不调我的工具"的第一现场。

# 打印当前配置下实际可见的工具清单(含 scope) npx @deepseek-ai/dsh --profile web --dump-tool-catalog

拿到清单后,确认你的工具确实在列、scope 没被意外收窄,再去看模型为什么没选它(往往就是第 11 讲说的"描述写得不够清楚")。

四、长时任务与 job 三件套

有些工具跑得久(构建、爬虫、批量处理)。dsh 把它们放进统一的后台任务运行时,并提供三个管理工具:

  • job_list:列出当前在跑的后台任务;
  • job_output:取某个任务的增量输出;
  • job_kill:中止失控的任务。

如果你的自定义工具是"长跑型",记得在内部用 ctx.jobs 登记,模型才能对它做列表 / 取输出 / 中止,否则它会变成一个"黑盒卡死"。

五、动手练习:给第 11 讲工具加一道频率 guard

回到第 11 讲那个工具,给它加一道"每分钟最多 5 次"的频率 guard,超限直接拒绝(静默、不弹窗)。下面是一段示意:

// 频率 guard:滑动窗口,限 5 次/分钟 const calls: number[] = []; export function rateLimitGuard(_ctx: unknown, _call: unknown) { const now = Date.now(); // 只保留最近 60 秒内的调用时间戳 while (calls.length && now - calls[0] > 60_000) calls.shift(); if (calls.length >= 5) { return { ok: false, reason: "调用过于频繁,请稍后再试(限 5 次/分钟)" }; } calls.push(now); return { ok: true }; }

挂载时把 rateLimitGuard 注册为该工具的 guard 字段(具体字段名以 packages/core/tools 的类型定义为准),然后连续快速触发 6 次,第 6 次应当被静默拒绝。验证通过后,--patch 卸载即撤销,体现 Cordis 的可逆副作用。

六、常见坑

  • 工具注册了但模型不调:先 --dump-tool-catalog 确认在作用域内,再改描述;
  • guard 和 approval 搞混:guard 不弹窗、适合"硬规则",弹窗请留给真正需要人拍板的敏感操作;
  • 长时任务卡死:没登记到 ctx.jobs,模型无法中止,只能手动重启;
  • scope 被 patch 误删:改 profile 时顺手把自定义工具的作用域收窄了,模型直接"看不见"它。

七、官方文档对应章节

  • docs/ 中 tool-catalog、tools、approval 相关章节
  • packages/core/agent-loop 的"工具执行流水线"源码导读(第 5 讲已铺垫)
  • cookbook 中"加一个工具"实操段

本讲内容基于 DeepSeek Harness 官方文档与项目源码整理,仅供学习参考,具体命令与配置请以官方最新版本为准。系列文章配合源码仓库食用效果更佳:https://github.com/deepseek-ai/deepseek-harness

咨询 DeepSeek Harness 相关问题,请加微信:A0qingfengyuan_01

个人观点,仅供参考,如有不对之处,请多包涵,欢迎指出。本文由 AI 协助完成!