Skip to content

2.3 工具执行流水线

本章概览:DSH 的工具(tool)是模型调用能力的唯一入口。本章拆解 ctx.tools 的完整执行管线:注册与作用域、四种呈现模式、预执行把关、单调 guard、around 派发、后执行、结果规范化与观察。

注册与作用域

ctx.tools.register(definition) 注册一个受信任的类型化工具定义:

  • 必备 output 声明:规范 output { schema, render, presentationMeta? }——工具体只返回声明 schema 的规范 JSON 值;
  • 作用域分层:普通插件上下文注册全局;通过 agent.ctx 注册则只对该 agent 生效,遮蔽同名全局工具;同层重名抛错;
  • ctx.tools.restrict(filter):agent 级 allow/deny 掩码(这是"可见性组合",不是权威边界——安全非目标见 scope Agent Note);
  • 注册即副作用,返回 disposer。

出处:packages/core/tools/README.mddeepseek-harness-src/packages/core/tools/README.md

呈现模式:native / code / both

tools.mode 配置决定工具如何呈现给模型:

模式行为
native(默认)可见工具作为函数定义(function calling)贡献
code贡献保留的 run_code 传输 + 生成的 tools:sdk 提示片段 + "只有 run_code 可被直接调用"规则(执行器强制,模型直呼其他工具解析为 UNKNOWN_TOOL
both两种形式都贡献,且不设该规则(native 调用会执行)

run_code 名称保留:不可注册、遮蔽、限制或移除。非 native 模式需要 ctx.codeRuntime(其 language 有已注册 SDK 渲染器;TypeScript 走 dsh-code-runtime-worker-thread)。单 agent 可用 ctx.tools.presentAs(mode) 遮蔽默认。

出处:packages/core/tools/README.mddeepseek-harness-src/packages/core/tools/README.md

执行管线(完整顺序)

官方顺序(可视化见 docs/tool-execution-pipeline.md):

text
tools/pre-execute(可重排的 allow/deny/ask 门)
  → ctx.tools.guard() 注册的单调 guard(返回字符串即最终拒绝理由)
  → tools/execute(around 派发:超时/重试/指标插件包裹)
  → tools/post-execute(可替换 content/value、附加上下文、block 反馈)
  → 定义拥有的 finalizeContent(快照于调用开始,只能替换最终 content)
  → tools/result(只读观察)

各阶段要点

  • tools/pre-execute:可重排的 allow/deny/ask 门,返回 PreToolDecisionaskctx.approval 服务(挂载时),否则退化为 deny;故意不提供输入改写
  • 单调 guardctx.tools.guard() 在 pre-execute 之后、派发之前运行;返回 reason 即拒绝,且后面的 waterfall 监听器不能把拒绝变回允许(单调性);
  • tools/execute:around 包裹规范化派发。包裹器只能替换 signal(注册表在调用体前重新融合原始调用者 signal);包裹器生成的 success 会按解析出的输出声明重新规范化;
  • tools/post-execute:接受可替换 contentvalue(二选一)、附加 additionalContexts;block 把反馈变成无值失败;content 替换不是机密边界(程序化消费方要防泄露应替换 value);
  • finalizeContent:同步且全函数,每个规范化结果恰好运行一次(包括绕过 post-policy 的失败),只能替换 content
  • tools/result:只读观察不可变的最终结果。同名 tool/result 是 loop 之后追加的持久会话事件——一个是实时,一个是持久。

结果形态

ToolExecutionResult 是判别联合:成功 { isError:false, value, content, meta?, additionalContexts? };失败 { isError:true, error:{ message, info? }, content, ... }。注册表在渲染前快照、验证、冻结规范值,再物化持久呈现字段。

并行执行策略

ctx.tools.executionMode(exec) 返回 parallel 仅当可见定义的 isConcurrencySafe(args) 分类器恰好返回 true;未知/隐藏/未声明/无效/抛出分类一律 exclusive(串行)。loop 维护有界滚动池并在启动前重新分类。

出处:packages/core/agent-loop/README.mdmaxParallelToolCalls 配置,默认 10;1 为串行)

取消语义

协作式且安静:每个类型化调用都带调用者拥有的 AbortSignal;工具体接收只读 exec.signal。调用体前取消 = ABORTED_BEFORE_DISPATCH;调用后取消只能把成功结果替换为 ABORTED;deny、包裹器失败、工具失败、post 策略失败、超时拥有的 TOOL_TIMEOUT 更具体。每个异步工具必须观察或转发 signal,且只在自有工作停止后 settle。

出处:packages/core/tools/README.mddeepseek-harness-src/packages/core/tools/README.md)与 cooperative-tool-cancellation Agent Note

UI 呈现意图

工具通过 presentCall / presentResult 返回 provider 中立的 card 标签渲染意图(generic / terminal / diff / locations),让 UI 呈现该工具自己的调用卡片。官方约定:"一个工具的 UI 渲染意图是其设计的一部分,事先决定;呈现方法是 args 的纯函数"(AGENTS.md)。

如何添加一个工具

官方 cookbook:docs/cookbook/adding-a-tool.md 提供分步指南;本站 4.1 添加一个工具 有中文讲解。

小结

工具流水线是"策略即插件"的样板:允许/拒绝、超时/重试、内容替换、UI 呈现各自是流水线上的独立阶段,可被任意插件监听/包裹,且注册表保证每个结果都规范化、冻结、可观察。全量工具目录(schema 与包归属)见 docs/tool-catalog.md

参考资料

本文档为学习用途的原创讲解,基于 MIT 许可的开源项目 deepseek-ai/deepseek-harness 编写;所有引用均注明出处。