工具可见集合观测与性能实验
这篇把“工具太多会不会影响模型”变成可以检查的问题。先记住边界:本篇给出观测格式和实验方法,不声称已经测出了某个模型的 token、首字节延迟、总延迟或回答质量。
如果你还没分清“插件、patch、fork 和注入”分别是谁负责,先读工具预算与插件责任决策卡;本篇只负责把工具集合变成可记录、可比较的实验对象。
本篇的三层来自工具可见性与非侵入扩展,那一页有一个可以逐层收窄的组件:勾掉 Bundle 改变已注册集合,换 agent 作用域改变可解析集合,换策略改变允许执行的集合。先在那里看清三层怎样嵌套,再回到本篇设计观测格式。组件给的是教学模型,不是任何真实部署的工具清单。
先把一个问题拆成三层和一条呈现线
同一个工具在 DSH 里要分成三层状态,再加一条“怎样呈现给模型”的线。只看到工具名称出现在代码里,不能推出它已经进入每一轮模型请求。
| 层次 | 初学者可以怎样理解 | 适合记录什么 |
|---|---|---|
| 已注册 | 运行时知道这个工具存在,可能可以查到它的定义 | 工具名、来源、版本、注册或注销事件 |
| 当前 agent 可解析 | 同一作用域的 get() 和工具分发查找能解析这个工具 | 工具名、作用域、查找结果 |
| 实际模型呈现 | presentAs(native / code / both) 与最终提示词组装决定模型收到原生 schema、Code Mode 入口,还是两者 | 呈现方式、最终工具字段、schema 摘要、顺序 |
| 执行允许 | 这一次调用经过策略、审批、guard、沙箱和宿主权限检查 | 工具名、允许/拒绝、策略原因、执行结果 |
官方的 ToolProviderResult 还把“模型可见的 schemas”和“限制前的 knownNames”分开;工具 registry 的 schemas(scope) 则是作用域解析结果的投影。这样工具顺序检查可以知道完整候选集合,而最终组装仍然可以按呈现方式收束。这个设计正好说明:注册集合、解析集合、模型呈现和执行权限不能混成一个列表。
可以把一次调用前后的关系画成这样:
插件加载
-> 注册集合
-> agent 作用域与 restrict()
-> 当前 agent 可解析的工具
-> presentAs(native / code / both)
-> 实际组装出的模型工具字段
-> 模型选择工具
-> pre-execute / guard / approval / sandbox
-> execute / post-execute
-> result 观察与 Session 记录restrict() 会同时影响某个 agent 作用域的 get() 和由该 agent 发起的 execute() 查找,使被排除工具在这一作用域中表现为未知;在 native 呈现下,它也不会进入该次原生 schema 组装。presentAs() 主要改变工具怎样呈现给模型,同样不增加执行权限。文件系统、网络、子进程和凭据各有专门的策略与宿主能力边界,第 22 课对这条边界有完整表述。
不要只测 schema 字节数
schema 的 UTF-8 字节数是一个好用的起点,但它只回答“序列化后的描述有多大”。它不能单独回答模型是否更会选工具、任务是否更容易完成,或者 provider 是否真的更快。
| 指标层 | 至少记录什么 | 不能单独推出什么 |
|---|---|---|
| 上下文成本 | 可见 schema 字节、估算 token、最终 prompt 字节 | 真实 provider token 或缓存命中 |
| 工具发现与选择 | 找到工具的成功率、漏选率、选错率、重复调用率 | 工具越少一定越好 |
| 时间成本 | 发现耗时、首个工具调用时间、首 token、总延迟 | 变短一定来自工具集合 |
| 任务效果 | 成功率、正确性、证据完整度、人工盲评 | 一次成功案例的普遍收益 |
| 稳定性 | 超时、重试、取消、失败恢复、循环次数 | 没有错误就代表设计完美 |
| 安全边界 | 越权尝试、错误工具暴露、敏感参数泄漏、审批结果 | 可见集合就是 OS 沙箱 |
| 运行成本 | provider token、调用次数、缓存字段、费用 | 本地字节数就是账单成本 |
工具延迟加载至少可以比较几种策略:全部暴露、按 Profile 暴露、按任务作用域暴露、先给轻量目录再展开 schema、先由路由器筛选候选,或失败后扩大搜索范围。每种策略都要记录“找得到、选得对、用得成、失败能恢复”这四个结果。
宿主应该观测哪四个时点
如果你是宿主维护者,或者维护一个明确标注为 patched fork 的发行版,建议至少保留下面四个快照。普通插件作者只能使用宿主公开的观测接口,不能为了补齐快照而偷偷读取私有 Map、模块缓存或内部 Loader 状态。
| 时点 | 需要回答的问题 | 不要越界解释成什么 |
|---|---|---|
| 注册集合 | 运行时到底装载了哪些工具?来源和版本是什么? | 不等于本次模型已经看见 |
作用域解析/restrict() 后集合 | 这个 agent 的作用域筛掉了哪些工具?同一作用域的 get/execute 是否也把它视为未知? | 不等于 OS 权限已经收紧 |
| 实际模型呈现与组装 | 本次模型请求最终拿到了哪些原生 schema、Code Mode 入口和顺序? | 不等于模型一定会调用它 |
| 执行策略决定 | 调用到达后为什么允许、拒绝或等待审批? | 不等于工具身体已经成功运行 |
工具注册/注销或作用域限制发生变化时,官方 tools/change 事件可以作为变化提示。tools/pre-execute、tools/execute、tools/post-execute 分别位于执行流水线的不同阶段,tools/result 适合观察最终结果。它们可以帮助你记录生命周期,但不能替宿主提供不存在的“实际 prompt 快照”。
宿主可以直接导出一份脱敏调试快照
本学习仓库在 ToolRuntime 上增加了只读的 ctx.tools.debugSnapshot(scope?),用于让宿主观察工具集合,而不是让普通插件读取私有 registry。它返回深度冻结、可 JSON 序列化的名称和成本信息,不执行工具,不替换提示词,也不包含 execute、presenter 回调、参数、凭据或用户内容;设计记录见脱敏 ToolRuntime 调试快照。
把返回值先按下面六个字段读,不要一上来把它当成模型请求的完整 prompt:
| 字段 | 初学者解释 | 适合得出的结论 |
|---|---|---|
registered | 被检查的那一层自己注册了哪些名称 | 哪些名称由这一层拥有 |
known | 作用域遮蔽完成、限制之前的候选名称 | 限制前这个 agent 可能继承哪些工具 |
visible | 限制、遮蔽和呈现 transport 加入后的运行时解析集合 | 这一路径能否解析这些名称 |
hiddenByRestriction | 被作用域 allow/deny 隐藏的继承名称 | 哪些名称因限制从候选集合消失 |
visibleSchemas | 真正投影给模型 wire 层的名称和 UTF-8 字节数 | 原生 schema 或 run_code 入口的大小 |
visibleSchemaUtf8Bytes | visibleSchemas 字节数之和 | 两份固定快照的本地序列化成本差异 |
Code Mode 下尤其要分开看:visible 可能同时包含 SDK 可到达的业务工具和 run_code,而 visibleSchemas 可能只包含直接给模型的 run_code schema。UTF-8 字节数是稳定的序列化大小指标,不是 provider tokenizer 的真实 token 数,也不等于完整系统提示词大小。
这份 API 解决的是“宿主到底组合出了什么”的观测问题,不是权限隔离 API。即使 visible 数量减少,文件系统、网络、子进程、凭据和操作系统权限仍要由各自的宿主策略单独证明;普通插件也不应为了补充字段而读取私有 Map 或修改 Loader。
脱敏快照应该长什么样
下面是一个可以交给离线检查器的最小示例。它只放工具名、来源、版本和 schema 形状,不放完整 prompt、参数值、凭据、用户内容、绝对路径或文件正文。
{
"profile": "normal",
"agent": "default",
"registered": [
{ "name": "read_file", "source": "example", "version": "1.0.0" },
{ "name": "search_text", "source": "example", "version": "1.0.0" }
],
"visible": [
{
"name": "read_file",
"presentation": "native",
"schema": {
"type": "object",
"properties": { "path": { "type": "string" } },
"required": ["path"]
}
}
],
"execution": [
{ "name": "read_file", "allowed": true, "reason": "policy" }
]
}这里的 registered 有 2 个工具,visible 只有 1 个模型呈现条目,execution 只说明这一次 read_file 的策略结果。它没有证明 search_text 被删除,也没有证明 read_file 的路径一定安全;这正是分层记录的价值。若实验使用 code 模式,还要另行记录 run_code、SDK 段和绑定工具集合,不能把 visible 直接解释成原生 schema 数量。
仓库附带的离线检查器只是一个离线检查器。它读取你导出的 JSON,不启动 DSH、不连接模型、不修改注册表,也不会替你生成真实 token。第一次使用可以这样做:
node study-tools/inspect-tool-visibility.mjs study-tools/tool-visibility-snapshot.example.json它会输出已注册数量、可见数量、注册但不可见的工具、可见但未登记的工具、schema 的 UTF-8 字节数和执行允许/拒绝数量。输出中的粗略 token 数只用来帮助比较快照,必须看成启发式估计,不是任何 provider 的 tokenizer 结果。
你第一次运行后应该看到什么
当前仓库提交的教学夹具(study-tools/tool-visibility-snapshot.example.json,比上面的最小示例多一个 run_command)会得到一份类似下面的摘要。数字属于这份夹具文件,不是 DSH 默认工具数量,也不是上面那个两工具示例的输出;以后夹具改变时,先看字段含义,再比较数字:
profile: normal agent: default
registered: 3 visible: 1
registeredButNotVisible: run_command, search_text
visibleSchemaUtf8Bytes: 77
execution: allowed 1 / denied 1 / unknown 0如果你看到“注册 3 个、可见 1 个”,正确的第一句话是“这份离线快照记录了 3 个注册项,其中 1 个进入了可见集合”;不能直接说“模型已经收到 1 个 schema”。还要继续看 presentation、最终 prompt 组装和 provider 返回的 token 字段。若命令报“找不到文件”,先确认当前目录是仓库根目录,并把命令中的示例路径写完整;不要为了绕过路径问题去运行真实 DSH。
先做 A/B 结构预检,再谈性能
把两个 JSON 快照直接拿去比较,容易把“工具 schema 变了”“Profile 变了”或“注册集合也变了”误当成可见数量的效果。仓库附带的A/B 结构预检器把比较接口收窄为两个文件:它要求 profile、agent、registered 和可选的 fixed 实验条件一致;profile 和 agent 不能省略或写空,只允许 visible 集合和执行结果出现差异;共同可见工具的 schema、呈现方式和相对顺序也必须保持不变。
先用仓库里的两组教学快照练习:
node study-tools/compare-tool-visibility-ab.mjs study-tools/tool-visibility-ab.a.example.json study-tools/tool-visibility-ab.b.example.json输出中的 valid: true 只表示“这两组快照适合进入下一步实验”,不是 provider 性能已经测完。命令会同时报告可见数量、schema 字节数和新增/移除工具;如果 valid: false,先修复实验条件,不要继续收集延迟数字。
这层预检器故意不读取 DSH 私有 registry,也不启动模型。它位于宿主观测接口和真实 provider 实验之间:宿主负责导出脱敏快照,预检器负责检查比较条件,实验运行器再负责记录 provider token、缓存字段、首 token 延迟、总延迟、工具错误、盲评质量和成本。
先建立不依赖 provider 的本地基线
如果还没有 API key,可以先运行离线性能基准。它复用上面的 A/B 结构预检,然后重复测量 JSON 解析、可见名称集合差异和 visible 列表序列化:
node study-tools/benchmark-tool-visibility-ab.mjs study-tools/tool-visibility-ab.a.example.json study-tools/tool-visibility-ab.b.example.json --iterations 1000 --warmup 100这一步会给出可见工具数、visible JSON 字节数、schema 字节数和 bytes / 4 粗略代理,也会报告当前 Node、平台和架构。它能回答“这两份固定快照的本地准备成本如何”,不能回答 provider tokenizer 的真实 token、网络延迟、首 token、总延迟或模型质量。先保存这份基线,未来拿到真实 provider 后,再用同一批脱敏快照和固定任务补做真正的 A/B 实验。
再往前一步:让真实宿主参与,但仍不调用模型
仓库还提供一个更接近 DSH 运行时的离线实验:
pnpm run build:lib:host
pnpm run study:runtime-benchmark -- --iterations 200 --warmup 25如果完整的 build:lib:host 因为你本地的站点类型依赖失败,可以先按构建日志修复依赖,再运行;不要把“脚本找不到 debugSnapshot()”误解成宿主 API 不存在。这个实验直接加载当前工作树已经构建出的 @deepseek-ai/dsh-tools、@deepseek-ai/dsh-system-prompt 和 @deepseek-ai/dsh-scope,然后:
- 用真实
ToolRuntime注册 24 个学习夹具工具。 - A 组读取全局 native 视图。
- B 组在同一个 agent 作用域调用公开
restrict({ allow }),只保留read_file、search_text、show_status。 - 分别调用
debugSnapshot()、schemas()和SystemPrompt.assemble(),记录工具数量、wire schema 的 UTF-8 字节数和本地准备阶段耗时。
这比“手写两个 JSON 快照”多了一层运行时证据,但仍然不是模型性能实验。它没有加载真实 Profile、安装 Bundle、执行文件或网络工具、调用 provider,也没有得到 tokenizer、缓存、首 token、总延迟或任务质量。报告里的计时只适合在相同机器和相同版本上做相对观察;不要把一次 A 组比 B 组快的输出写成“工具少一定让模型更快”。
此实验使用的是学习仓库当前工作树中新增的 debugSnapshot() 观测接口,不是固定上游提交已经承诺的公共 API。若把它带入产品,应由宿主维护者审阅 API 稳定性、隐私字段、版本兼容和删除策略;普通插件不应自行读取私有 registry。
本仓库的一次真实宿主运行记录
下面不是手写 JSON 的演示,而是本学习仓库在 Windows 本机实际运行 ToolRuntime、作用域限制和系统提示词组装得到的一次记录。这样读者可以先学会读报告,再决定是否要接入真实 provider。
本轮最新运行命令:
pnpm run build:lib:host
pnpm run study:runtime-benchmark -- --iterations 200 --warmup 25运行环境:Node v24.15.0、Windows win32、x64。本轮复跑时间为 2026-08-17(Asia/Shanghai),预热 25 次,正式测量 200 次。实验使用同一个 ToolRuntime 和同一个 24 个工具的注册集合:A 组全部 native 可见;B 组仍注册 24 个工具,但在同一个 agent 作用域通过公开的 restrict({ allow }) 只保留 read_file、search_text、show_status。没有删除注册,也没有执行工具。
| 观测项 | A 组:全部可见 | B 组:限制为 3 个 | 这列能说明什么 |
|---|---|---|---|
| 注册工具数 | 24 | 24 | 两组的注册集合相同 |
| 当前可见工具数 | 24 | 3 | 作用域限制改变了当前可见集合 |
| 可见 schema UTF-8 字节 | 4,524 | 533 | 本地原生 schema 序列化规模不同 |
| prompt assembly 工具数 | 24 | 3 | 组装阶段采用的工具数量不同 |
toolWireUtf8Bytes | 4,549 | 537 | 本地工具 wire 字段的序列化规模不同 |
在 200 次测量(预热 25 次)中,三类本地准备操作的平均耗时如下。这里的单位是纳秒;它是本机相对基线,不是 provider 延迟。
| 操作 | A 组每次 | B 组每次 | 本次 B 相对 A 的观察 |
|---|---|---|---|
debugSnapshot() | 309,234 ns | 160,564 ns | B 较低 |
schemas() | 338,379.5 ns | 96,022 ns | B 较低 |
SystemPrompt.assemble() | 158,517.5 ns | 89,516.5 ns | B 较低;仍应按本机相对基线解读 |
图中每一根条都来自上表同一个数字;比例尺以 schemas() 的 A 组为满刻度。它是同一台机器、同一工作树里的相对观察,不是 provider 延迟,也不能跨机器比较。
这次报告同时记录了 providerCalls: 0、modelCalls: 0、dshProcessStarted: false,并且 comparison.valid: true。因此本次运行支持的结论是:在这台机器、这个工作树、这个固定夹具和这个公开作用域 API 下,注册集合可以保持不变,而可见 schema、工具 wire 字段和本地准备阶段出现可观测差异;本轮三项准备操作的 B 组计时都低于 A 组。这是 2026-08-17 本机复跑的一次相对观察,不是跨机器或 provider 的性能承诺。
本次运行没有证明以下任何一项:provider input tokens、cached tokens、首 token 延迟、网络延迟、真实 Profile 默认工具数量、模型回答质量、工具执行耗时。它同样没有证明“工具越少模型一定更聪明”,也没有证明“在所有机器上一定更快”。要研究这些问题,必须接入固定的 provider、模型、任务和评分表,并把失败、成本和质量一起记录。由于 debugSnapshot() 是本学习仓库当前工作树新增的观测接口,这条记录也不能改写成“固定上游 DSH 已经承诺该公共 API”。
此前一次 1,000 次复跑记录
在同一工作树、Node v24.15.0、Windows win32、x64 上,本轮又以预热 100 次、正式测量 1,000 次复跑。A 仍是 24 个 native 工具全部可见,B 仍注册 24 个但只在 agent 作用域保留 read_file、search_text、show_status;comparison.valid: true,providerCalls: 0、modelCalls: 0、dshProcessStarted: false。
| 操作 | A 组每次 | B 组每次 | 本次 B 相对 A 的观察 |
|---|---|---|---|
debugSnapshot() | 165,596.1 ns | 63,184.2 ns | B 较低 |
schemas() | 140,185.3 ns | 32,164.6 ns | B 较低 |
SystemPrompt.assemble() | 74,318.4 ns | 45,690.9 ns | B 较低 |
这次复跑与前面的 200 次记录方向一致,但绝对纳秒值不同。因此它加强的是“在这个固定本地夹具中,缩小可见集合会改变准备阶段”的机制证据,不是跨机器性能承诺。它仍没有测 provider token、缓存、首 token、网络、任务质量或真实插件 Profile。
此前两次 1,000 次复跑记录
下面保留此前两次使用 1,000 次测量、预热 100 次的记录,用来展示同一条件下的抖动;它们不是上面最新 200 次运行的替代品。注册数量、可见集合、schema 字节数、providerCalls、modelCalls 和 dshProcessStarted 没有改变;准备阶段的纳秒数字发生了变化:
| 操作 | 第一次 A / B | 第二次 A / B | 应该怎样读 |
|---|---|---|---|
debugSnapshot() | 125,716.5 / 56,189.1 ns | 152,205.6 / 61,810.4 ns | 两次都是 B 较低,但绝对值随运行状态波动 |
schemas() | 124,129.3 / 26,966.0 ns | 119,988.5 / 27,507.7 ns | 集合规模差异仍可观察,数值不是跨机器承诺 |
SystemPrompt.assemble() | 66,603.9 / 38,914.6 ns | 68,488.1 / 36,253.9 ns | 只能作为本机同条件的相对观察 |
这几次复跑证明了计时会受 JIT、CPU、垃圾回收和机器负载影响,而且单个操作可能反向波动。以后如果要把工具集合与 provider token、首 token、总延迟或任务质量关联起来,应固定模型、任务、并发、预热、随机化顺序和失败处理,并至少交错运行多轮;这里的本地准备阶段计时不能替代那项实验。
normal、development、audit 不是官方固定 Profile
为了让初学者容易操作,本教材使用下面三档称呼。这是研究方法的命名,不是上游已经承诺存在的三个命令或三个内置 Profile。
| 模式 | 建议暴露方式 | 适合谁 | 主要风险 |
|---|---|---|---|
| normal | 只加载常用 Bundle,并让当前任务需要的少量工具可见 | 日常对话和稳定产品 | 误以为“未显示”就等于“没有权限” |
| development | 额外记录注册变化、schema 组装和结果事件 | 插件作者、宿主开发者 | 为了调试而改私有 registry |
| audit | 工具可以全部注册,但按实验逐组改变模型呈现集合 | 性能和安全审计 | 同时改变模型、prompt、schema 和权限,导致实验无法比较 |
推荐的默认顺序是:先减少不需要的 Bundle,再按 agent 作用域限制解析集合,再检查呈现方式和 schema,最后才考虑是否需要源码级修改。把所有工具注册着不一定有问题;让所有工具在所有 agent 的每一轮都进入模型呈现,才是需要用数据验证的设计选择。
A/B 实验:20 个全部 native 呈现,还是 20 个注册、3 个 native 呈现
最小实验可以采用下面两组:
- A 组:注册 20 个工具,在 native 呈现且最终组装不再替换的条件下,20 个都向模型提供名称、描述和 schema。
- B 组:仍然注册 20 个工具,在相同 native 呈现条件下当前 agent 只提供 3 个工具的 schema;其余工具不从注册表删除。
两组都完成同一个任务,例如“找到一个文件中的配置项并说明它的用途”。为了让结果能比较,至少固定这些变量:
| 必须固定 | 为什么 |
|---|---|
| model 和 provider | 不同模型或服务商的 tokenizer、缓存和工具调用策略不同 |
| 用户 prompt 与上下文 | 问题难度和历史消息会直接改变输入量与质量 |
| 20 个工具的名称、description、schema 和顺序 | 否则你测到的是文案变化,不是可见数量变化 |
| temperature、其他生成参数和平台 | 随机性、网络和机器状态会影响延迟与回答 |
| Profile、权限、沙箱、工具实现和时间窗口 | 不能让 B 组顺便获得更严格或更快的执行路径 |
建议先做少量预热,再让 A、B 交错运行;避免先把 A 组全部跑完、隔很久再跑 B。每次运行都写入同一个实验表;失败、超时和错误工具调用不能静默丢掉。
每次至少记录什么
| 指标 | 记录方式 | 解释边界 |
|---|---|---|
| input tokens | 优先记录 provider 返回的数值 | 不要用字符数替代 provider token |
| cached input tokens | 如果 provider 提供就单独记录 | 没有字段时写“未提供”,不要猜命中 |
| 首字节或首 token 延迟 | 记录请求开始到第一个有效响应的时间 | 网络和排队时间也会进入这个数字 |
| 总延迟 | 记录请求开始到完成的时间 | 工具执行耗时要单独拆开 |
| 工具调用错误 | 记录未知工具、参数错误、拒绝、超时和重复调用 | “最终回答成功”不能抹掉中间错误 |
| 任务质量 | 用固定评分表或人工盲评 | 不要只凭一次回答下结论 |
| 成本 | 记录输入、输出和工具相关费用字段 | 没有 provider 价格或 token 就写未测 |
UTF-8 字节数可以帮助发现 schema 是否明显膨胀。bytes / 4 只能作为非常粗略的启发式估计,因为不同 tokenizer 对中文、英文、标点、JSON 结构和特殊 token 的切分都不同。它不能代替真实的 provider token 统计,更不能直接推出延迟或质量。
结果表模板
复制下面的表格到学习工作簿与首个实验,每一行代表一次请求。没有 API key 或模型服务时,可以先填写快照大小,其他栏写“未测”。
| 编号 | 组别 | 可见工具数 | schema UTF-8 字节 | provider input tokens | cached tokens | 首 token ms | 总 ms | 错误工具调用 | 质量分 | 备注 |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | A | 20 | 待填 | 未测 | 未测 | 未测 | 未测 | 0 | 待填 | 预热/正式 |
| 2 | B | 3 | 待填 | 未测 | 未测 | 未测 | 未测 | 0 | 待填 | 预热/正式 |
实验结论也要分层写:
源码事实:工具注册、作用域筛选和 schema 组装分别存在。
快照事实:这次导出的注册集合有 20 个,native 模型呈现集合有 3 个。
模型事实:provider 报告的 input tokens 和延迟是多少。
质量事实:固定评分表下 A、B 的任务结果如何。
未验证项:哪些模型、provider、平台或插件组合还没有测。如果只有第一层或第二层,就只能说“架构允许按集合治理”或“快照显示集合不同”;不能写成“B 组一定更快”或“模型一定更聪明”。
谁可以做什么
普通插件作者可以:
- 通过公开工具、服务、事件和作用域 API 注册自己的能力。
- 在宿主提供公开观测接口时记录自己的注册、注销和执行结果。
- 提供脱敏快照或测试夹具,让宿主维护者可以复核解析集合和模型呈现集合。
普通插件作者不应为了观察模型集合而直接改私有 registry、重建 Loader、替换模块缓存、修改构建产物或写入 Windows 注册表。若这些动作不可避免,维护者的身份已经变成宿主、发行版、patched fork 或非官方注入器维护者,必须单独公开基线、差异、权限、版本矩阵和回滚方式。
这也是“侵入式工作不能默认交给插件作者”的准确说法:不是说插件作者永远不能维护 fork,而是不能把宿主级修改藏在普通插件安装步骤里,让用户误以为它和公开 Bundle 具有同一信任等级。
初学者的 9 步练习
- 打开工具可见性与非侵入扩展,用自己的话写出“已注册、agent 可解析、实际模型呈现、执行允许”。
- 复制示例快照文件,只改工具名和数量,不填真实参数。
- 运行离线检查器,查看“注册但不可见”和 schema 字节数。
- 运行上面的 A/B 结构预检器,确认
registered数量不变、native 模式下的visible数量减少、共同 schema 没有变化。 - 运行离线性能基准,记录本地快照处理成本,并把它和真实 provider 指标分开。
- 如果本地宿主库已构建,再运行
pnpm run study:runtime-benchmark -- --iterations 20 --warmup 5,比较debugSnapshot、schemas和SystemPrompt.assemble的 A/B 准备阶段。 - 记录一项不能从快照或宿主准备阶段推出的事实,例如“没有真实 provider token”。
- 如果以后拿到模型服务,再按 A/B 表固定变量、交错运行并记录失败。
- 把结果写回工作簿,注明模型、provider、平台、时间和清理动作。
完成这 9 步,你学到的是怎样把一个架构判断变成可复核的实验问题。
实验前可以再用工具预算与插件责任决策卡的审计卡检查:本次快照由谁导出、是否改动了宿主、哪些权限和运行证据仍然缺失。