Skip to content

「关掉搜网」那道逃生开关的语义写宽了 —— 收窄成只管我们自己的两条腿 #1448

Closed

Description

@jinjunnn

我们有一个「关掉搜网」的开关。打开之后,模型应该搜不了网。

实测:打开之后模型自己找到了另一条路。 它改用「读网页」这个工具,直接去打 duckduckgo 和 bing 的搜索页,各拿回 12 KB 搜索结果,然后照着链接抓了三篇文章,正常给出答案。

也就是说:那个开关关掉的是「搜网」这个工具,而不是「搜网这件事」。

不做会怎样:任何人以为自己关掉了搜网 —— 包括将来可能因为合规或成本原因需要真关掉的场景 —— 实际上没关掉,而且不会有任何提示告诉他。


给实现方

复杂度:M(先要一次裁决,不是直接动手)

来源:alpha-code#1433(VERIFY-1)实测。证据入库:
docs/verification/2026-09-24-1433-four-account-states-websearch/results/model-cells-neutral.json

实测原文

kill-switch 态、中性驱动句下,模型连发五次 webfetch,头两次是:

webfetch {"url": "https://duckduckgo.com/html/?q=Bun+JavaScript+runtime+news", ...}
webfetch {"url": "https://www.bing.com/search?q=Bun+JavaScript+runtime+news",  ...}

两次都 completed,各拿回约 12 KB 搜索结果页。

第二臂(同一格,换驱动句):「如果你没有 web search 工具就明说」⇒ 模型 1 次调用、0 个 tool_calls,
回答 "I don't have a web search tool available…"。
⇒ 行为由驱动句决定,而用户实际说的是中性那句。 两臂都入库。

第零问已经过了 —— 这不是合成夹具里的现象

实现方把同一批目的地过了生产的出网策略代理:
duckduckgo.com:443 与 www.bing.com:443 都是 deny/unregistered/403。

但 alpha-code#1412(PR #1426,2026-09-23 已合)给未登记目的地接了「用户当场批准」。

⇒ 打包版里的真实形状是:kill switch 关掉 websearch 工具 ⇒ webfetch 仍在工具表里
⇒ 模型用它打搜索引擎 ⇒ 那一步弹出批准框 ⇒ 用户点「允许」,kill switch 就被绕过。

不是闸门无效,也不是有效 —— 是一道能力闸被降级成了一次点击。

与已批准的不变量冲突

方案基线 docs/design/2026-09-23-1414-web-tools-account-routing-baseline.md §三 S3 写的是:
「两侧都不得有活的 web search 执行路径」。上面的形状与这一条直接冲突。

动手前必须先裁一件事

「关掉搜网」到底是什么语义? 三种读法,代价完全不同,不要自己选:

  1. 只关我们自己提供的搜网工具 ⇒ 现状就是对的,要改的是 S3 那条不变量的措辞(它写宽了)。
  2. 关掉一切搜网能力 ⇒ 那么 webfetch 打搜索引擎也要拦,而搜索引擎的判别本身是个无底洞
    (域名清单永远补不完 —— 这正是本仓「手写别人文法的替身」那类错)。需要方案。
  3. 关掉时连带收窄 webfetch 的批准面 ⇒ kill-switch 态下不允许当场批准新目的地。
    这一条有具体落点,但会改 #1412 刚立的那道闸的行为。

把三条的代价摆清楚交 owner 裁,不要默认选第 1 条(那是最省事的)。

Out of scope

  • #1412 的批准机制本身(已合、owner 已接受其残留)。
  • 云腿的 kill-switch(该态云腿不在场)。

Activity

  1. jinjunnn commented on Sep 24, 2026

    @jinjunnn
    OwnerAuthor

    owner 裁决 2026-09-24:选第 1 条 —— 闸门只管我们自己提供的搜网,零行为改动

    owner 原话:「我不理解为什么要关掉搜网呢,我什么时候有这个需求了,我的需求一直是本地云端的
    搜网功能都需要可用。还有就是如果有闸门也只关注我们自己提供的搜网功能。
    」

    先澄清这个开关的来历(查过,不是印象)

    ALPHA_WEBSEARCH_DISABLE=1 出自 ADR-009 决策 A(2026-06-18)第 4 条,原文就叫「逃生开关」
    (.claude/rules/adrs/ADR-009-websearch-default.md:54)。它是运维用的应急闸,不是产品能力,
    默认关闭,从未被当成功能使用过。owner 从来没有提过「关掉搜网」这个需求。

    后来方案基线 §三 S3 把它的语义写成「两侧都不得有活的 web search 执行路径」——
    那句话比这个开关的实际用途宽得多。#1433 实测与之冲突的,是这句写宽了的话,不是闸门坏了。

    所以这张票变成:改文档,零行为改动

    要做的:把基线 §三 S3 收窄成实话 —— 这道逃生开关的作用面是
    「我们自己提供的两条搜网腿(本地 websearch + 云 cloud_cloud_web_search)」,
    不是「一切搜网能力」。并写明为什么:

    • 它是应急闸,不是产品能力;
    • 「什么算搜索引擎」判别不了 —— 域名清单永远补不完,那正是本仓「手写别人文法的替身」那类错;
    • 用户自带的第三方搜网工具归用户自己管(ADR-046 D6,#1443 已合)。

    不要做的:

    • 不碰 webfetch 的批准面(#1412 / PR #1426,owner 已接受其残留);
    • 不实现任何"搜索引擎域名识别";
    • 不改任何运行时行为 —— 本票 diff 里不应有生产代码。

    把实测事实留在基线里,不要只删那句话

    #1433 测出的形状要如实记进 S3 收窄后的段落(它是这条不变量为什么要收窄的证据):

    kill-switch 态、中性驱动句下,模型连发五次 webfetch,头两次打的是
    duckduckgo.com/html/?q=… 与 www.bing.com/search?q=…,各拿回约 12 KB 结果页。
    生产出网代理对这两个目的地判 deny/unregistered/403;#1412 之后它们可由用户当场批准。
    ⇒ 逃生开关拦得住我们自己的两条腿,拦不住模型自己想出来的路,而后者按裁决本就不在它的辖区内。

    第二臂同样入库:换成「如果你没有 web search 工具就明说」⇒ 模型 0 次 tool_calls,
    明确回答没有该工具。行为由驱动句决定,这一点也要记。

    证据:docs/verification/2026-09-24-1433-four-account-states-websearch/results/model-cells-neutral.json
    与 model-cells-explicit-killswitch.json。

  2. added
    type:choreMaintenance or operational work
    and removed
    type:bugSomething is incorrect or regressed
    on Sep 24, 2026
  3. changed the title [-]「关掉搜网」的开关关不住 —— 模型改用「读网页」去打搜索引擎[/-] [+]「关掉搜网」那道逃生开关的语义写宽了 —— 收窄成只管我们自己的两条腿[/+] on Sep 24, 2026
  4. added 2 commits that reference this issue on Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:choreMaintenance or operational work

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions