你的默认值就是你的策略,而一项智能体能写入的设置,不算设置。
智能体的哪些设置才真正要紧?是那些没人去碰的——因为默认值承载了你几乎全部的整体风险与成本;以及那些被存在智能体摸不到的地方的——其余的都只是披着管控外衣的偏好。智能体产品打破了每一块设置界面从普通软件那里继承来的心智模型:被配置的那个东西能读自己的配置、能编辑文件,还会在对话里被要求改掉自己的行为——于是「用户把那个关掉了」有三种不同含义,而只有一种熬得过一个对手。
步骤 1三种旋钮,而其中只有一种算管控。
每个智能体产品最后都会同时拥有这三种,而且通常没人决定要把它们造出来:
- 偏好。运维方可以改它,改它就是目的本身。主题、啰嗦程度、用哪个模型、默认工作目录。没有任何东西依赖它保持不变。
- 硬性要求。运维方不可以改它,因为风险是别人接下来的。禁止对外出网、禁用凭据类工具、只允许这份 MCP 服务器清单里的而没有别的。
- 能力授予。它压根不是一个调节值——它决定什么存在。挂载了哪些工具服务器、哪些目录可达、加载了哪些技能。授予一项不是在配置这个智能体;那是在造一个不同的智能体。
这三种几乎总是被存进同一个文件,而这正是那个 bug。一项躺在「被约束方可以写入」的文件里的硬性要求,不过是一个上面配了一行严厉注释的偏好。OpenAI 的 Codex CLI 在这里值得照抄,恰恰因为它在这件事上很较真:管理员在 requirements.toml 里设置 allow_managed_hooks_only = true,以忽略用户、项目与会话层的钩子配置,同时仍允许来自 requirements 与 managed config 两层的钩子——而文档写明这项设置只在 requirements.toml 里受支持,所以把它放进 config.toml 根本不会启用该模式。同一个键,在一个文件里是管控,在另一个文件里是空操作。这看起来像个古怪之处,而它就是整个机制。
先写测试,再做界面:对每一项设置,先说清它约束的是哪一方,然后检查那一方能不能写它所在的那个文件。如果答案是「能」,那你拿到的是文档,不是管控。而在智能体产品里,被约束的那一方通常包括智能体本身——而它就是靠编辑文件吃饭的。
步骤 2默认值就是策略。拿你自己的变更率把这道算术算一遍。
一块设置界面是在分配结果,而这个分配由「没人选的那个选项」主导。设 r 为曾经动过某项设置的用户占比,那么你全量范围内的行为就是一个加权混合;而对于设置界面实际会产生的那些很小的 r 来说,默认值就是行为:
# what a default actually decides, with your own measured change rate r = change_rate # share of accounts that ever move this setting exposure = (1 - r) * risk_of_default + r * risk_of_chosen # at r = 0.05, 95% of your fleet is running the value you picked in a sprint # planning meeting. Moving the DEFAULT one notch is worth ~19x the effort # spent making the setting easier to find. # the number you need is r, and you already have it: SELECT setting, COUNT(*) FILTER (WHERE value <> default_value) * 1.0 / COUNT(*) FROM account_settings GROUP BY setting ORDER BY 2 ASC; -- lowest r first
在下一次设置界面改版之前,把这道查询跑一遍。排在最上面的那几行并不是「用户不在乎的设置」;它们是你已经替所有人做掉的决定,也正是评审时该拿出来争论的那几项。一个权限默认值、一个自治程度默认值、一个留存默认值、一个模型默认值,各自为你的整个安装基数定下了一个数,而这四个里有三个是风险、不是口味。
有两个容易落地的推论。第一,如果一项设置的安全取值同时也是它的慢取值或贵取值,那么默认值也决定了你的成本曲线——面向用户的那一半见成本与配额 UX。第二,你的默认值有一个并非你选定的依赖:当某个供应商改掉它的默认值时,你产品的行为会在没有任何一次部署的情况下移动——这正是未固定的厂商默认值这一页要抓的那个失效。把要紧的那些固定下来,你就算是决定了它们;放着不管,就是让别人在某个周二替你决定。
步骤 3智能体读得到自己的设置,所以「把那个关掉」有三种含义。
这是让智能体设置面区别于其他一切设置面的那个性质,而它常常被漏掉,因为界面看上去一模一样。当一个用户说「改文件之前别再问我了」,他可能指的是三件事中的任何一件,而你的产品大概实现的是最弱的那一件:
- 对话里的一句话。模型读到它,并作为「服从指令」的一部分照办。系统里什么都没变。之后的某一轮、一次上下文压缩、一个子智能体,或一份足够自信的被检索文档,都能把它撤销掉——而用户无从判断自己处在哪一种状态里。
- 一项智能体看得见也写得了的已存偏好。跨轮次持久、在文件里可见,并且可被它所治理的那个东西编辑——所以它熬得过遗忘,熬不过一个对手。
- 一项在智能体触及范围之外的硬性要求。由智能体无法修改的代码执行,放在它写不了的文件里。三者之中,只有这一个是边界。
设计上的义务,是让「当下在起作用的是哪一种」变得可读,因为用户会把这三件事读成同一个动作。一条合理的规则是:在对话中改掉的设置永远算偏好,而界面必须这么说、并显示它落在了哪里;任何带有安全或开销后果的东西,都要求一次智能体并不参与的带外变更。这不是为了摩擦而摩擦——这是环境权限与一次真正的授予之间的差别;而对话里那句「好的,我不会再那样做了」,是智能体 UX 里最令人信服的错误答案。
既然说到这里:请假定那份设置文件除了智能体之外也会被一个对手读到。一份枚举了你的 MCP 服务器、端点与认证线索的配置是一张地图,而配置即侦察完整论证了它为何属于这台机器上性价比较高的那几个文件。
步骤 4写后果,别写机制。
智能体的设置由工程师撰写、由不共享工程师那套系统模型的人阅读,于是产出一屏屏「句句为真、却没人能据此行动」的文字。「启用 Bash 工具」是一个正确的标签,也是一个无法回答的问题。改写方法很机械:说清什么变得可能,并框定在哪里。
- 不要写「允许 shell 命令」——而要写「在这台电脑上运行程序,包括会改动本项目之外文件的程序」。
- 不要写「自动批准只读工具」——而要写「不经询问即可读取本文件夹内的任何文件。读取就是数据离开的方式,所以这包括这里存着的任何机密。」
- 不要写「启用网络访问」——而要写「从互联网取数据、也向互联网发数据。藏在它所抓取的某个页面里的一条指令,此后就可能被照着执行。」
第三个例子说明了为什么这不只是文案工作。一个把「网络开着」理解成便利开关的用户,不可能被指望自己推出那条外泄通路;把它说出来,是这次同意能有分量的唯一办法。经验法则是:用「一个讲理的人不会预料到的最坏结果」来给设置打标签,而它通常只要一句话,而且通常关于读而不是写。权限授予与撤销 UX讲授予流程本身,而自动批准与命令允许清单讲为什么这几个开关里最和善的那一个背后的允许清单,比看上去难得多。
按爆炸半径分组,别按子系统分组。「这次对话」/「这个项目」/「这台机器与我的账户」是用户本来就持有的层级;「工具 / 模型 / 高级」是你的仓库目录结构。按爆炸半径排序还有一个好处:它会把危险的设置排到相邻位置,而那正是一位评审者会注意到「三个单看都合理的开关,组合起来成了没人签字过的东西」的时刻。
步骤 5每项设置都需要一个作用域和一个寿命,而用户想要的是「就这一次」。
设置存储的默认形状——每个账户一个值、永久有效——对智能体权限来说是错的,因为用户真正想要的,在两个维度上几乎总是更窄。他们想让智能体在这件事上别再问,而不是从此不再问;而他们说「行,你去吧」,心里想的是接下来十分钟。
所以请把这两个字段显式带上,并让界面优先给出那个窄的选项:
- 作用域。一轮、一件任务、一个会话、一个项目、一个账户、一个组织。一项在会话作用域上被授予、而产品却存在账户作用域上的权限模式,是智能体最终拿到比任何人授予的都更多权限的最常见那一种方式——因为用户记得的是关于某一件工作的一个决定。
- 寿命。直到这件任务结束、直到这个会话结束、直到某个日期,或者永不过期。请把「永不过期」做成一次刻意的选择,而不是「没有做选择」的结果;一项没有过期时间的授予,与一项没人复核过的授予无法区分,而那正是权限复核之后不得不靠人工去翻找的东西。
还有两条规则能挣回自己的位置。实质变化时重新询问:如果当初做出授予时所依据的那个范围已经挪动了——换了一个仓库、新挂上了一台工具服务器、这件任务隐含的开销跳了十倍——那么旧的那个「是」并不覆盖新的局面;而任务作用域是「把一次授予钉在引发它的那件工作上」的一般版本。以及,让撤销和当初的授予一样好找:那个打开它的按钮,应该紧挨着那个关掉它的按钮,并配一句朴素的说明讲清当下在生效的是什么。渐进式自治讲的是如何随时间把一个用户往这些横档上送,而它之所以行得通,正是因为每一档都是有作用域的、而不是全局的。
步骤 6把「失败放行」的默认值当作一处侦测缺口,并测四件事。
有一类默认值值得单独点名,因为那是产品悄悄选定风险姿态的地方:当一件被配置的制品校验失败时会发生什么。Cloudflare 的 Agents SDK 0.32.0 于 2026 年 10 月 29 日发布,它会把加载的每一份 SKILL.md 对照 Agent Skills 规范做检查——而一个违反规则的技能仍会被加载、只记录一条警告;只有那种压根无法使用的技能,比如没有 description 的,才会被跳过。对一份仍在变动中的规范来说,这是个站得住脚的默认;而它同时也是一个每一次部署都未经选择就继承下来的决定。如果你的产品会校验技能、钩子、工具 schema 或策略包,那么「失败放行还是失败拦截」这个选择就已经是一项设置了,无论你有没有把它暴露出来;而失败拦截与失败放行论证了为何该把它变成显式的。
然后给这个面装上度量,因为一块设置界面是一个有用户的产品,而几乎没人去测它:
- 每项设置的变更率。就是 STEP 2 里的
r。接近零意味着是你决定了它;那就把下一次改动该默认值当成一次行为变更,施加与代码变更同等的评审,若有开关则放在开关后面——面向智能体的特性开关就是那套机制住的地方。 - 按作用域与寿命统计的授予。存活授予中「账户级且不过期」的占比。这个数字放着不管只会往上走,而它也正是审计方会向你索要的那一个。
- 对话式覆盖。用户试图靠「说一声」来改设置的频率。数值高,同时意味着一处缺失的管控和一块误导人的界面,而它会准确告诉你该把哪一项设置挪出对话。
- 同一会话内的回退。用户在一次使用里把某个东西开了又关,意味着那个标签没有描述清后果——这是 STEP 4 失败时最便宜的信号,而且不需要做任何问卷。
请按这个顺序做。把每一个旋钮归类为偏好、硬性要求或能力授予,并把硬性要求挪进一个「被约束方——包括智能体——写不了」的文件;如果做不到,就别再把它们叫作管控。测出每项设置的变更率,并把低 r 的那些默认值当作它们本来就是的策略决定来评审,并固定住任何可能被供应商在你脚下挪动的项。让「一次变更落在了三种状态中的哪一种」变得可见,并立下规矩:任何带安全或开销后果的东西,都不能在对话里改掉。用「最坏的、未被预料到的后果」重写每一项设置的标签,并框定范围;再按爆炸半径给界面分组,让各种组合变得可见。给每一次授予一个显式的作用域与寿命,优先给出窄的那一个,在实质变化时重新询问,并把撤销摆在授予旁边。在任何你会校验配置制品的地方,刻意选择失败拦截。然后盯住变更率、账户级不过期授予的占比、对话式覆盖的尝试次数,以及同一会话内的回退。如果你只带走一句话:你的默认值就是你的策略,而一项智能体能写入的设置只是偏好——界面管它叫什么都一样。