ARCHITECTURE · 07
工具系统:DeepSeek Harness 的工具如何被看见和执行
直接答案
DeepSeek Harness 里,ctx.tools 是带作用域的工具注册表,外加一条带把关的执行流水线。工具对模型只暴露名称、描述和参数结构,执行函数和超时预算永远不会发给模型。每次调用按固定顺序走完整条流水线:先落日志,经审批与守卫把关,执行后可被替换或补充,最后以冻结结果再次落日志。ToolDefinition:一个工具由什么组成
一个工具定义(ToolDefinition)包含:
- 面向模型的
ToolSchema:名称、描述、参数结构; - 必需的规范输出声明
output; execute(执行函数);- 可选的
finalizeContent(结果后处理); - 调度元数据:
timeoutMs(超时预算)、isConcurrencySafe(是否可并行); - UI 展示函数:
presentCall/presentResult。
第一方工具用 defineTool DSL(领域专用写法)定义,参数类型自动推导;参数不匹配抛 ToolArgsError(INVALID_ARGS),输出不合声明抛 ToolOutputError(INVALID_TOOL_OUTPUT)。
泄露边界:模型只能看到冰山一角
注册表生成模型可见列表(schemas())时,只按显式允许列表构建 ToolSchema[]——只有 name、description、parameters 三样。execute、timeoutMs、UI 回调等绝不能泄漏到模型请求。这条边界是安全设计:模型不需要、也不应该知道一个工具"打算多久超时"。
执行流水线:一次工具调用的完整旅程
按官方 docs/tool-execution-pipeline.zh.md 流程图,一次调用依次经过(在轮次流程中的位置见 Agent Loop页第 3 节):
tool/call:调用先落会话日志(先记账,后办事);tools/pre-execute:allow / deny / ask 三段决策(waterfall 模式),钩子和审批挂在这里;- 单调守卫:已经 deny(拒绝)的不能被后面翻案,守卫身份受保护;
tools/execute:环绕分派——处理超时、重试、指标;- 工具体真正执行;
tools/post-execute:可以接受、阻断、替换结果或追加上下文;finalizeContent:结果后处理;tools/result:产出冻结的权威结果;tool/result:结果落会话日志(日志侧见会话页)。
审批细节:一次性询问由 ctx.approval 在单调守卫之前处理;如果没有任何回答方在线,审批以 unavailable 关闭失败——也就是默认拒绝。没人批,就不执行。
注册成功 ≠ 模型可见:过滤与遮蔽
ToolRestriction(工具约束)按作用域过滤继承来的全局工具:多个约束取交集;作用域自己注册的工具不受约束;只写 deny 列表的过滤器放行未列出的继承工具,写 allow 列表就排除其余。
被过滤掉的全局工具,既不出现在提示词里也拒绝执行——对模型来说,它和"根本不存在的工具"无法区分。所以排查"模型为什么不用某工具"时,先查过滤与作用域遮蔽(规则见插件系统页第 5 节),再怀疑模型。
两个反直觉的执行约定
timeoutMs是协作式预算:它只是给工具体的建议,永远不会发给模型;注册表无法硬杀同进程代码——写工具的人要自己尊重预算。- 并行是显式 opt-in(主动声明):只有
isConcurrencySafe返回true的工具才会加入并行组,默认是串行语义。
工具目录与统一入口
官方维护一份生成的工具目录 docs/tool-catalog.md(约 60+ 工具)。常见的工具按用途分组如下:
- 终端与 Shell:
bash/pwsh、terminal_*; - 文件读写与搜索:
read/write/edit/glob/grep; - 网络:
web_search/web_fetch; - 任务与流程:
skill、todo_write、workflow、ralph、ask_user_question、exit_plan_mode; - 代码与会话:
subagent、run_code(Code Mode)、lsp、session_*查询工具、job_*等。
注意 cordis_* 系列工具官方标注"不在任何随附树中"——属于刻意 opt-in,默认配置里没有它们。
MCP 工具和 skill 加载器都以普通工具身份注册进 ctx.tools,走同一条流水线——外部工具不是旁路通道(MCP 侧见 MCP 桥接页,skill 侧见技能页)。
EVIDENCE
证据与来源
本页包含:官方事实
| # | 事实声明 | 状态 | 来源 |
|---|---|---|---|
| 1 | ctx.tools 是作用域化注册表 + 带把关的执行流水线 | 官方事实 | |
| 2 | ToolDefinition 组成(schema / output / execute / finalizeContent / 调度元数据 / UI 函数) | 官方事实 | |
| 3 | 泄露边界:schemas() 只含 name / description / parameters | 官方事实 | |
| 4 | defineTool DSL 与两类错误(ToolArgsError / ToolOutputError) | 官方事实 | |
| 5 | 执行流水线九步顺序 | 官方事实 | |
| 6 | 审批在无回答方时以 unavailable 关闭失败(默认拒绝) | 官方事实 | |
| 7 | ToolRestriction 交集语义、deny / allow 差异 | 官方事实 | |
| 8 | 被过滤工具与不存在的工具无法区分 | 官方事实 | |
| 9 | timeoutMs 协作式、不发给模型、无法硬杀同进程代码 | 官方事实 | |
| 10 | 并行执行显式 opt-in(isConcurrencySafe) | 官方事实 | |
| 11 | 工具目录约 60+、cordis_* 刻意 opt-in | 官方事实 | |
| 12 | MCP 工具、skill 加载器走同一流水线 | 官方事实 |