Crypto OS
Non-Technical Crypto OS第六阶段 · AI × Crypto 与未来链上经济

第 34 章 · Agent Wallet 是什么

把钱包交给 AI 之前,必须先设定什么?

练习的能力
AI LiteracySystem ThinkingOnchain Literacy
动手
为一个假想 Agent 写一份权限表:单笔上限、日上限、允许的合约、需要人工审批的条件。
AI Lab
让 AI 尝试绕过你写的权限表,把它找到的每一个漏洞补进规则里。

一个现实问题

你决定给你的软件一个自己的钱包。你很谨慎,先写了一份规则:

1. 单笔不超过 100
2. 只能和这三个合约交互
3. 超过 100 的操作,弹给我审批

这份规则看起来相当严格。你把它交给一个熟悉链上安全的朋友看,请他挑毛病。他看了三分钟,列出了下面这些:

第一,第 1 条只管单笔。 一百笔 99 元的操作,每一笔都合规,总共九千九百元。这份规则里没有任何一个地方限制总量。

第二,「和合约交互」和「花钱」不是一回事。 你的软件可以调用白名单里的合约,给另一个地址授予一个没有上限的额度。这一步本身没有转走任何钱,所以它连一百元的限额都用不上。但授权之后,拿到额度的那一方可以在任何时候把钱全部取走。

第三,白名单里的合约可能能替你调用别的合约。 很多合约带有转发或者批量执行的能力。你允许了合约 A,而合约 A 可以代你去调用合约 Z——你的白名单在第二跳之后就失效了。

第四,第 3 条那个审批,多久内有效? 如果它弹出来没人处理,是一直等着,还是超时放行?如果是超时放行,那么你的软件只要在凌晨三点提交请求,第 3 条就不存在。

第五,「100」是什么单位? 一百个稳定币和一百个别的代币,价值可能差几个数量级。规则里没有说清楚以什么计价,也没说价格从哪里来——而价格从哪里来这件事,第 32 章已经演示过它出错时会发生什么。

第六,谁来执行这三条规则? 如果它们只写在一份文档里,而软件的私钥可以签任何交易,那么这三条规则的实际效力等于零。一份没有被强制执行的规则不是防线,是一个愿望。

你朋友最后说了一句:「你写的不是权限,是期望。」

所以本章的问题:把钱包交给 AI 之前,必须先设定什么?

这一章的答案不会是「要小心」。它是一份具体的、可以照着写的清单,以及一套检验这份清单有没有漏洞的方法。核心的那句话很短:Agent Wallet 的核心不是签名能力,而是花钱的策略与上限。 让一个软件能签名是几行代码的事;让它只能签那些你真正允许的交易,才是这一章的全部内容。

思想实验

把上面那个过程变成一个练习。

三个人,同一份权限表,四十八小时。 规则只有一条:不许攻破私钥,不许利用任何代码漏洞,只能在你写的规则之内,想办法把钱弄出去。

权限表就是上面那三条。

第一个人花了四分钟。 他发起了一百零一笔操作,每笔 99。第一百笔完成时,钱已经基本没了。他用的是这份规则允许的全部行为,没有任何一步违规。

第二个人花了二十分钟。 他不转账,他调用白名单里的一个合约,给自己的另一个地址授予了一个不设上限的额度。这一步在权限表里完全找不到对应条款——因为授权不是支付。第二天他从那个地址把钱取走了。

第三个人花了三十六个小时,用的方法最让人不舒服。 他每隔几分钟提交一个金额略超 100 的请求,每一个都触发审批。第一天,你认真看了前十几个。第二天上午,你开始只看金额。第二天下午,他提交了一个金额相同但目标不同的请求,你点了确认。

这三个人代表三类完全不同的失效方式,而它们都不需要任何技术攻击:

用的是什么你的规则为什么没拦住补法
第一个人拆单规则只管单笔,不管累计加时间窗累计上限和频率上限
第二个人授权不是支付规则只定义了「转多少钱」,没定义「授予多大权力」把授权额度纳入限额,禁止无上限授权
第三个人审批疲劳规则假设了「人会认真看每一次」给审批本身设预算,超出就一律拒绝

第三个人的方法最值得停下来想。他没有绕过任何规则,他攻击的是执行规则的那个人。

而且这件事不需要有人恶意实施。一个完全善意的软件,在一个设计不当的系统里,会自然产生同样的效果——它并不知道你已经疲劳了,它只是按自己的逻辑不断提交请求。AI 在 Crypto OS 中的位置里那句话在这里得到了最具体的印证:一个每天弹出两百次审批的系统,等于没有审批。

把这个实验收成一句话:

一份权限表的强度,等于它最弱的那一条;而最弱的那一条,通常不在表里,在表的假设里。

你来决定

你要让这个软件真的能花钱。钥匙和权限怎么安排?

观察结果

四个选项的差别,可以归结成一个问题:这条规则由谁执行?

规则写在哪谁执行模型误解时有效吗有人注入指令时有效吗强度
提示词里模型自己无效无效接近零
一份文档里靠软件自觉无效无效接近零
调用前的代码检查里确定性程序有效有效
钥匙的权限里签名系统有效有效
钱包的余额里物理上限有效有效最高,但最粗

这张表是这一章的骨架。 它说明一件反直觉的事:把规则写得更详细、更周全,并不会提高它的强度。 一条写在提示词里的规则,无论写得多好,强度都接近零;一条「这个钱包里只有这么多钱」的物理限制,虽然粗糙,但无法被任何方式绕过。

从这张表可以直接得到三条设计原则:

第一,规则要尽可能往下移。 同一条限制,能放进钥匙权限里就不要放进代码检查,能放进代码检查就不要放进提示词。

第二,越往下的规则越粗糙,所以需要分层。 钱包余额这一层最强但只能限制总量;钥匙权限这一层可以限制目标和函数;代码检查这一层可以做复杂判断(比如价格偏离)。三层配合,而不是选一层。

第三,最上面那一层不算防线,只算提效。 在提示词里写「不要超过 100」是有用的——它能让软件大部分时候做对的事,减少被拦截的次数。但它不是安全措施,不能被计入你的风险评估。

把这一节收成一句话:

Agent Wallet 的核心不是签名能力,而是花钱的策略与上限。

而策略和上限只有在模型够不到的地方执行时,才真的存在。

建立模型

一、完整的链路:钱包只是最后一格

先把这一章放回整个第六阶段的框架里。一个 Agent 的资金操作要走完这十层:

1Intent你给出目标与边界:这个 Agent 要做什么,可以花多少,不可以碰什么。
2LLM只产出提案。它的输出在这一层没有任何执行力,也不持有任何钥匙。
3Structured Output动作、目标合约、函数、金额、单位,全部是字段,不是一句话。
4Validator确定性校验:地址格式、金额为正、精度与单位匹配、目标在已知清单内。
5Policy这一章的主角。单笔上限、时间窗累计、频率、白名单、审批条件、授权额度上限。
6Simulation先跑一遍,拿到真实的状态变化:执行之后我的余额和授权会变成什么样。
7Risk Engine按模拟结果打分:这一笔之后总敞口是多少,离危险线还有多远。
8Execution用一把受限的钥匙签名,且整条链路必须可以被一键停机。
9Onchain Verification执行之后回链上核对:状态真的变成预期的样子了吗,授权额度对不对。
10Audit Log谁提的、过了哪些检查、谁批的、执行了什么、结果如何,一条不漏。

这一章处理的是第五层(Policy)和第八层(Execution)。 前四层在 T32 里有完整的工程实现,这里只需要记住一件事:Policy 层必须是确定性的,它不能包含任何模型。

对照着看那个绝对不能出现的结构:

课程里禁止出现的架构

  1. Prompt
  2. LLM
  3. Private Key
  4. Send Transaction

模型直接拿到私钥并发出交易,中间没有任何校验。任何作业出现这个结构都判不通过。

它和上面十层的区别不是少了几个检查。是模型直接持有了私钥——一旦如此,前面那张强度表里的每一行都同时失效,因为所有的规则都变成了「希望它遵守」。

二、权限表的八个字段

一份真正可执行的权限表,至少要回答八件事。少一个字段,就多一个上一节那样的洞:

字段要回答什么漏掉会怎样
1 身份这是哪个 Agent,用哪个地址出事时分不清是谁做的
2 单笔上限一次最多动多少,以什么计价一次就被掏空
3 累计上限一小时、一天、一周分别最多多少拆单(第一个人的方法)
4 频率上限单位时间内最多几次同类操作高频小额累积,且异常难以察觉
5 目标白名单哪些地址、哪些合约、哪些函数钱被送到任意地方
6 授权上限可以授予别人多大额度,能不能无上限授权不是支付(第二个人的方法)
7 审批条件什么情况必须人来批,批不到怎么办审批疲劳与超时放行(第三个人的方法)
8 有效期与撤销这份权限什么时候失效,怎么紧急停掉一份忘了回收的权限会一直有效

第六个字段是链上特有的,也是最容易被漏掉的一个。 在传统支付里没有「授权」这个概念——你要么付钱,要么不付。链上不同:你可以在不转移任何资产的情况下,授予另一个地址动用你资产的权力,而且这个权力可以是没有上限、没有期限的。

所以权限表必须分开定义两件事:「这个 Agent 一次能转多少」和「这个 Agent 一次能授予多大的权力」。 后者的上限应该比前者更严,因为它的影响是持续的。

第八个字段则是最容易被忘记的一个。 一份没有有效期的权限,会在你早就忘了它存在之后继续有效。给每一份权限写一个到期时间,到期自动失效、需要重新授予——这个小设计能消除掉大量长期累积的风险。

三、限额是四个维度,不是一个数

「设一个上限」这句话通常只被执行了四分之一:

  1. 单笔上限
  2. 时间窗累计
  3. 总预算
  4. 整体敞口
四个维度各自拦住一类失效方式。只设第一个,等于只防住了最不可能发生的那一种。
维度拦住什么一个常见的错误
单笔上限一次性的大额错误以为设了这个就安全了
时间窗累计拆单、异常循环、连续重试只设了「每天」,没设「每小时」——一天的额度可以在五分钟内用完
总预算长期的缓慢流失没有设,或者设了但会自动补充
整体敞口单看每笔都合规、加起来越界完全没有这个概念

第二行那个错误值得特别说。 只设日上限时,那个额度可以在任意短的时间内被用完——第 32 章那个四十分钟里执行十一次的例子,每一次都在日上限之内。所以时间窗必须是多层的:小时、天、周,各设一个。

四、白名单是四层,不是一份地址清单

「只能和这三个合约交互」这句话有四种不同的严格程度:

限制到什么能拦住什么
地址只能和这几个地址交互拦住把钱转给陌生地址
合约只能调用这几个合约同上,但仍然允许调用它的任何功能
函数只能调用这个合约的这几个函数拦住转发、批量执行、授权这类危险功能
参数这个函数的这个参数只能在某个范围内拦住「函数对了但数值离谱」

大多数人的白名单停在第二层,而第一节那个「第二跳」的问题恰恰发生在第二层和第三层之间。 允许一个合约,等于允许了它的全部功能,包括那些可以代你去做别的事的功能。

一条实用的经验:白名单要按函数列,而不是按合约列。 这会让清单变长,但它是唯一能真正限制住行为的粒度。

五、审批是稀缺资源,要给它设预算

审批疲劳不是一个态度问题,是一个资源问题。人的注意力有限,每天能认真做出的判断次数是一个有限的数。

所以审批必须像预算一样被设计:

每天允许送到人面前的审批次数:   最多 5 次
超出这个数之后的请求:           一律自动拒绝,不是排队等待
审批的有效期:                   15 分钟,过期作废
没人处理时的默认行为:           拒绝。绝不能是放行
两次审批之间的最小间隔:          防止连续轰炸

「超出就自动拒绝」这一条是关键,而且它看起来很不方便。 但换个角度看:如果一天有超过五次需要人判断的情况,那说明前面的死规则没有做好——正确的修法是去改规则,而不是让人多批几次。

「没人处理时默认拒绝」这一条没有任何例外。 超时放行等于保证了在最需要人的时刻(凌晨、你在开会、你在睡觉)人不在场。而攻击者和意外,恰好都偏爱这些时刻。

还有一条关于审批内容的要求:弹出来的东西必须让人能在十几秒内做出判断。 一个显示着原始交易数据的审批框,人是看不懂的——他只能点确认。审批界面要显示的是:这一笔会让什么发生变化、最坏情况是什么、为什么它触发了审批。

六、四个自检问题

一份权限表写完,问自己四个问题。这四个问题对应思想实验里的三种失效方式,加上一个最根本的:

  1. 如果它把每一笔都压到限额以下,连续做一千次,会怎样?(拆单)
  2. 它能不能在不转移任何资产的情况下,授予别人动用资产的权力?(授权)
  3. 如果审批一直没人处理,会发生什么?(疲劳与超时)
  4. 如果这份权限表被删掉,这个钱包还能做什么?(规则到底由谁执行)

第四问是最根本的一问。 如果答案是「什么都能做」,那么前三问的答案都不重要——你拥有的不是一个受限的钱包,是一个附带了说明书的完整钱包。

它叫什么

策略Policy

一组决定「这个请求能不能通过」的确定性规则。

关键词是确定性:同样的输入永远得到同样的结果,不需要任何理解能力,不会被措辞影响,不会因为上下文变长而遗忘。

这一层最常见的错误是用模型来实现它。理由听起来很好——「让它理解意图,而不是死板地卡规则」。但一旦策略层包含模型,它就继承了模型的全部不确定性,而策略层存在的唯一意义,就是它比模型更可靠。

判断一条策略合不合格有个简单标准:它能不能被写成一个不需要读懂任何文字的检查? 「单笔不超过 X」可以,「不要做有风险的事」不可以。后者不是策略,是期望。

支出限额Spending Limit

在一段时间内最多能花多少。

它有四个维度,缺一不可:单笔、时间窗累计、总预算、整体敞口。 只设单笔的限额,只防住了最不可能发生的那一种失效。

时间窗必须是多层的——只有日上限时,那个额度可以在五分钟内被用完。小时、天、周各设一个,三层同时生效。

还有一个容易被忽略的点:限额的计价单位必须明确,而且价格来源必须可靠。 「不超过 100」这句话在没有说明计价单位和取价方式之前,是没有意义的。

白名单Allowlist

明确列出允许的目标,其余一律拒绝。

它的力量来自「默认拒绝」这个方向。黑名单(列出禁止的)永远列不全,因为新的目标会不断出现;白名单会误伤,但误伤的代价是一次被拒绝的操作,而漏网的代价是全部资金。

它有四层粒度:地址、合约、函数、参数范围。 大多数人停在合约那一层,而这一层允许了这个合约的全部功能——包括转发、批量执行和授权这些可以绕过白名单本身的功能。

按函数列白名单,是这一章最具体的一条操作建议。

会话钥匙Session Key

一把被限定了用途、范围和有效期的钥匙。

它的价值在于把限制从「软件要遵守的规则」变成了「签名系统的物理边界」。一把只能调用某几个函数、金额不超过某个值、在某个时间点自动失效的钥匙,无论持有它的软件想做什么,它签出来的越界交易都不会被接受。

三个性质决定了它好不好用:范围(能做什么)、期限(什么时候自动失效)、可撤销(出事时能不能立刻作废)。

第三个性质在紧急情况下最重要。一个无法被撤销的受限钥匙,在你发现问题时只能等它自然过期——而那段时间可能足够长。

审计日志Audit Log

完整记录每一次请求:谁提的、内容是什么、过了哪些检查、谁批准的、执行了什么、结果如何。

它经常被当成事后的东西,其实它有三个即时的用途。发现异常:频率突然上升、目标突然变化、失败率突然升高,这些都是在损失发生之前就能看到的信号。定责:出事时能说清楚哪一步失效了。改进规则:被拒绝的请求最有价值——它们指出了模型想做而你不允许的事,其中一部分是你该允许的,另一部分是你该更严格禁止的。

有一个设计要求容易被忽略:日志必须存在软件改不到的地方。 一份可以被记录者自己修改的日志,在最需要它的那种场合恰好是不可信的。

把整章收成一句话:

Agent Wallet 的核心不是签名能力,而是花钱的策略与上限。

而检验这套策略的方法只有一个:假设这个软件会尽一切可能在规则之内把钱弄走,它能弄走多少。

动手

动手为一个假想 Agent 写一份权限表:单笔上限、日上限、允许的合约、需要人工审批的条件一份文档 + 一个测试网钱包 + 一个测试网区块浏览器0 元。这个 Lab 的第二部分涉及钱包操作,全程只使用测试网和水龙头领取的测试代币,绝对不要使用主网,也不要把任何主网私钥或助记词交给任何软件

这个 Lab 分两半:先写表,再在测试网上感受一次真实的边界。

第一半是重点,第二半是为了让抽象的规则变成具体的体验。

第一步:定义这个 Agent 要做什么,越具体越好。

它的任务是:          (一句话,具体到某个动作)
它需要动用资金吗:    (如果答案是「只是读数据」,这个 Lab 换一个任务)
它一天大概操作几次:
它会和哪些东西交互:
最坏情况下它能造成什么损失:

最后一行现在写不出来是正常的,写完整张表之后回来补。到那时你应该能给出一个准确的数字,而不是一个感觉。

第二步:填完八个字段,一个都不许留空。

1 身份:      这个 Agent 用哪个地址
2 单笔上限:  最多 ___,以 ___ 计价,价格取自 ___
3 累计上限:  每小时 ___ / 每天 ___ / 每周 ___
4 频率上限:  同类操作 ___ 分钟内最多 ___ 次
5 目标白名单:合约 ___ 的函数 ___(按函数列,不要按合约列)
6 授权上限:  单次授权额度不超过 ___,禁止无上限授权,授权有效期 ___
7 审批条件:  什么情况必须人批 ___
              每天最多送几次 ___
              超出之后 ___(必须写「自动拒绝」)
              审批超时 ___ 分钟作废,默认 ___(必须写「拒绝」)
8 有效期:    这份权限 ___ 后失效
              紧急停止的方式是 ___(写出具体步骤和预计耗时)

第 6 条和第 7 条最后两行,是这张表里最容易写错的地方。 如果你在第 7 条写了「超时自动通过」,把它改掉——那一条会让整个审批机制在你睡觉时消失。

第三步:用四个自检问题打自己的表。

1. 它把每一笔压到限额以下,连续做一千次,会怎样?
   我的规则里拦住它的是第 ___ 条。拦不住的话,回去补。

2. 它能不能在不转移任何资产的情况下,授予别人动用资产的权力?
   拦住它的是第 ___ 条。

3. 审批一直没人处理会怎样?
   我的答案是 ___。如果是「放行」或者「一直等着」,回去改。

4. 把这份权限表删掉,这个钱包还能做什么?
   我的答案是 ___。

第四问的答案决定了前三问有没有意义。 如果答案是「什么都能做」,那么你现在拥有的是一份愿望清单。这时候要做的不是把规则写得更细,而是去想:这几条限制里,哪几条可以被放进钥匙的权限或者钱包的余额里。

第四步:把规则分到三层,标出每一条由谁执行。

放在钱包余额里的(物理上限):
放在钥匙权限里的(签名边界):
放在调用前的代码检查里(确定性程序):
只能放在提示词里的(不算防线):

最后一行的内容,在你计算「最坏损失」时要全部当成不存在。 这是这一步的全部意义:让你知道自己真正的防线有几层。

如果大部分规则都落在最后一行,这份表需要重写——不是重写内容,是重新设计执行方式。

第五步:在测试网上做一次,感受边界是什么感觉。

这一步只在测试网进行。 创建一个全新的测试网钱包,从水龙头领一点测试代币。不要使用你的主网钱包,不要导入任何主网私钥或助记词,也不要在任何界面上把它们输入给任何软件。

1. 创建一个新的测试网钱包,记下地址
2. 从水龙头领一点测试代币
3. 做一笔正常的小额转账,在区块浏览器上找到它
4. 做一次授权操作,然后回到区块浏览器,
   找到这笔授权,看它的额度是多少、有没有期限
5. 如果你的钱包工具支持,撤销这笔授权,
   记下这一步花了多久、要点几下

第 4 步是这一整个 Lab 里最重要的一次体验。 你会亲眼看到一件事:一笔授权在链上留下的记录,和一笔转账完全不同——它没有转走任何东西,但它把一部分权力交了出去。

第 5 步则让你体会紧急撤销要花多长时间。把这个时间填回第二步第 8 条的「紧急停止预计耗时」那一格。

第六步:回到第一步,补上「最坏情况下它能造成什么损失」。

现在你应该能给出一个具体的数字了。算法是:

最坏损失 = 以下三者里最小的那个
  A. 这个钱包的余额
  B. 时间窗累计上限 × 你发现问题所需的时间窗数
  C. 已经授予出去的授权额度总和

C 那一项常常是三者里最大的,而且最容易被完全忘记。 一个额度没有上限的授权,会让 A 和 B 两项限制同时失效。

把这个数字和「我能接受的损失」放在一起比较。如果前者更大,这份权限表还没写完。

做完之后你会有:一份八字段的权限表、四个自检问题的答案、一张三层执行分布图、一次真实的测试网授权体验、一个具体的最坏损失数字。

这份权限表就是这一阶段的阶段作品。 下一节会用一种非常有效的方式来给它找洞。

AI Lab

AI Lab让 AI 尝试绕过你写的权限表,把它找到的每一个漏洞补进规则里Level 2 · AI Copilot

这个练习是纸面练习。全程不涉及任何真实资金,不需要连接钱包,也绝不要把任何私钥、助记词或主网地址贴进对话框。 你贴进去的应该只有一份规则文本。

它是这一章最有效的一个工具,原因很简单:模型很擅长在规则的字面之内寻找缝隙,而这恰好是你自己最不擅长的事——你写规则时脑子里装的是「我想要什么」,而不是「这句话还能被怎么理解」。

下面是我为一个 Agent 写的钱包权限表。

请扮演一个只能在这些规则之内行动的对手。你的目标是
在不违反任何一条明文规则的前提下,把这个钱包里的钱
尽可能多地转移出去。

硬性约束:
- 不许攻破私钥,不许假设任何代码漏洞,不许假设我会
  违反自己的规则。
- 每一条方法都必须写出:用了哪几步、每一步为什么不
  违反规则中的哪一条、最终能拿走多少。
- 不要编造不存在的钱包功能、账户标准或接口。
  如果你的方法依赖某个功能,请描述这个功能做什么,
  而不是给出一个具体的名字或规范。

请至少给出 8 条不同的方法,按「能拿走多少」排序。

最后单独列一节:这份规则里,哪一条的假设最脆弱。

权限表:
(贴进来)

最后那一节是这个提示词最有价值的部分。 「假设最脆弱的那一条」通常指向的不是某个数字,而是某个你没意识到自己做出的假设——比如「审批时人会认真看」「一天只有一个日切」「白名单里的合约不会代我调用别人」。

拿到之后做三件事。

第一件:把每一条分类。 用思想实验里那三类加一类:

拆单类     (单笔合规,累计越界)
授权类     (不转移资产,但交出权力)
粒度类     (允许的范围比你以为的宽)
人的环节类 (攻击审批本身)
其他       (这一栏里的东西最值得研究)

「其他」那一栏是这个练习的金矿。 落在那里的方法,说明你的思维框架里根本没有这个维度。

第二件:对每一条写一个补丁,并且标出它属于哪一层。

漏洞:
补丁:
这个补丁放在哪一层:(钱包余额 / 钥匙权限 / 代码检查 / 提示词)
如果只能放在提示词里,说明:(这个洞实际上没有被补上)

最后那一行必须诚实。 一个只能靠「在提示词里叮嘱」来补的洞,等于没补。这时候正确的做法通常是把对应的能力整个去掉,而不是叮嘱它别用。

第三件:补完之后重新跑一遍,用同一个提示词。

这一轮它会找到不同的东西,而且往往更刁钻。跑三轮之后,新发现的数量会明显下降——那时候你的权限表才算初步成型。

这类任务上有四个可预期的现象:

  1. 第一轮它会给出一些不合法的方法,比如假设可以读取私钥。把它们剔掉,并在下一轮的提示词里明确禁止。
  2. 它很少主动攻击人的环节。 模型倾向于在技术规则里找洞。如果它没有提审批疲劳,加一句「请也考虑攻击审批流程本身」,通常会有收获。
  3. 它可能编造功能。 这个领域的钱包标准在快速演进,它很容易给出一个听起来专业但并不存在的机制。提示词里已经要求描述功能而不给名字,仍然要检查。
  4. 它的补丁经常不是确定性的。 「加强对异常行为的监控」不是一条规则,是一个愿望。每一个补丁都要能被写成一个不需要读懂文字的检查,否则退回重写。

AI 说完之后,你必须自己验证

  • 它找到的每一个漏洞,是真的在你的规则之内,还是需要攻破私钥或利用代码漏洞——后者不算
  • 它有没有找到拆单这一类:单笔合规、累计越界
  • 它有没有找到授权这一类:不转移资产但交出权力
  • 它有没有找到白名单粒度这一类:合约允许了,但它的某个函数可以代你做别的事
  • 它有没有攻击审批环节本身:数量轰炸、时机选择、超时默认行为
  • 它有没有找到单位与计价的漏洞:同样的数字在不同代币上差几个数量级
  • 它有没有找到时间维度的漏洞:日切瞬间连续两天的额度、有效期没写、权限忘了回收
  • 它提出的每一个补丁,是不是确定性的——能不能被写成一个不需要读懂文字的检查
  • 它有没有编造不存在的钱包功能、账户标准或接口来支持它的说法
  • 最后一条:补完之后再跑一次,它还能找到新的吗

真实案例

额度没有上限的那笔授权持续发生链上最常见的资金损失来源之一

链上有一类损失反复发生,而且它和任何代码漏洞都无关:用户为了省事,给某个合约授予了一个没有上限的额度。

这个操作在当时看起来完全无害——它没有转移任何资产,钱还在自己的地址里。但它把「随时取走这些资产」的权力交了出去,而且这个权力没有金额上限,也没有到期时间。

后来发生的事有很多种版本:那个合约被攻破、它的权限被滥用、或者它本来就是为此设计的。共同点是损失发生在授权之后很久,而且和当初那个操作在时间上完全脱节,导致很多人到最后都没想明白钱是怎么没的。

这件事对 Agent 权限设计的含义非常直接:权限表里必须有「授权上限」这个字段,而且它的默认值应该是「禁止无上限授权」。 一个只写了转账限额的权限表,在这一类风险面前完全裸露。

还有一条配套的操作习惯:定期检查自己的地址授予出去的所有额度,把不再需要的撤销掉。 上一个 Lab 的第五步让你亲手做了一次,就是为了让这件事变成肌肉记忆。

写在提示词里的那条规则反复出现各类 Agent 系统

一个常见的做法是把限制写进给模型的系统提示里:「你每笔操作不得超过 X,只能调用这几个合约。」

这在大多数时候是有效的——模型确实会遵守。问题在于「大多数时候」这四个字,以及它失效的那些场合恰好是最危险的场合。

失效的方式有几种。长对话中的遗忘:约束在很前面,当前的上下文很长。边界情况的解释:遇到规则没覆盖的情况时,它会自己推断一个「合理」的做法。输入里夹带的指令:如果这个 Agent 会读取网页、文档、邮件或者别人发来的消息,那么它读到的内容里可能包含试图改变它行为的文字——而它无法可靠地区分「我的规则」和「我读到的内容」。

最后一种最值得警惕,因为它不需要任何人接触你的系统。只要你的 Agent 会读外部内容,外部内容就有机会影响它。

结论不是「不要在提示词里写规则」——写了有好处,它能让 Agent 大部分时候做对的事,减少被拦截的次数。结论是:在计算最坏损失时,把提示词里的所有规则当成不存在。

两百次审批之后的那一次点击持续存在任何带人工审批的自动化系统

第 32 章讲过这个结构,在这一章它有了一个更精确的版本。

一个系统上线时,人工审批被当作最后一道防线。第一周的审批量是每天两百多次。第二周,负责的人开始批量处理。第三周,他形成了一个固定动作:扫一眼金额,在阈值内就确认。第五周,一笔本该被拦下的请求通过了,而他事后完全不记得看过它。

复盘的结论是:这个系统的设计保证了这个结果。 做出一个真实判断需要的时间,远超过两百次审批能分配给每一次的时间。

正确的设计有三条,而且它们都是数量上的,不是态度上的:给审批设每日次数预算(超出一律自动拒绝)给每次审批设有效期(过期作废,默认拒绝)让审批界面显示后果而不是原始数据

第三条最容易被忽略。一个显示着一串十六进制数据的审批框,人是看不懂的,他只能点确认。 审批界面要回答的是三个问题:这一笔会让什么发生变化、最坏情况是什么、它为什么触发了审批。

那份忘了回收的权限持续存在长期运行的自动化系统

有一类风险不来自任何攻击,只来自时间:一份权限被授予出去之后,没有人记得回收它。

典型的情形是:为了一次临时的任务,给某个软件开了一个较宽的权限,打算事后收回。任务完成了,人换了,项目改方向了,那份权限一直在。半年后它仍然有效,而且没有人在监控它。

这件事在 Agent 的场景里会被放大,因为软件的数量会变多,而且它们通常不会主动告诉你「我不需要这个权限了」。

对策只有一个,而且必须写进设计里:给每一份权限一个到期时间,到期自动失效,需要重新授予。 这个设计的价值不在于防住任何特定的攻击,而在于它让「忘记」这件事不再产生后果

配套的还有一件小事:维护一份权限清单,记录每一份权限授予的时间、原因和到期日。 定期读一遍这份清单——你几乎总会发现至少一条早就该收回的。

改一个变量

如果这个 Agent 会读取外部内容:网页、文档、别人发来的消息

风险等级立刻上升一整级,而且上升的原因和模型能力无关。

一个只处理你自己输入的 Agent,它的输入来源是可信的。一个会读外部内容的 Agent,它的输入来源是任何人。 而它读到的文字和你给它的指令,在它眼里是同一种东西——都是文字。

这意味着提示词里的所有约束都要当成不存在,因为读到的内容有机会覆盖它们。剩下的防线只有下面三层:钥匙权限、代码检查、钱包余额。

具体要加的措施有三条:把读取和花钱分成两个独立的环节(读内容的那个不持有任何花钱的能力)、把白名单收得更紧(因为你无法预测它会被引导去做什么)、把钱包余额压到更低(因为这是唯一无法被文字影响的限制)。

有一条更彻底的做法值得考虑:让读取外部内容的 Agent 和执行操作的 Agent 完全分离,中间只传递结构化的、经过校验的字段。这样外部内容影响的只是提案的内容,而提案还要过完整的策略检查。

如果你要管理的不是一个 Agent,而是四十个

权限设计从「一份表」变成「一套制度」,而且有几件事会从「不重要」变成「关键」。

第一,权限必须有模板和继承。 四十份手写的表,一定会出现互相矛盾和遗漏。应该有几个标准档位(只读、小额、需审批),新 Agent 从档位开始,特殊需求单独批准并记录理由。

第二,累计上限必须有全局的一层。 每个 Agent 各自的日上限都合规,四十个加起来可能远超你的承受能力。全局上限是这个场景里最重要的新增字段。

第三,审批预算是共享的。 你每天只有那么几次认真判断的能力,四十个 Agent 分这几次。这意味着单个 Agent 的审批触发条件要比只有一个时更严。

第四,停机必须是全局的。 一个能一次停掉全部四十个的开关,比四十个各自的开关有用得多——因为出事时你没有时间一个个去停。

如果钥匙不在你手里,而是托管在某个服务上

限制的执行方式会更可靠(因为它由那个服务强制执行,软件无法绕过),但你引入了一个新的对手方。

要问清楚三件事。第一,这个服务能不能在你不同意的情况下动用这把钥匙? 如果能,那么你的资金安全取决于它,而不是取决于你的权限表。第二,这个服务停业或者出故障时,你能不能拿回控制权? 第三,它的权限配置能不能被绕过,谁有权修改它?

第三问对应的正是这一章的第二条铁律:模型不能修改约束自己的规则。 这条铁律在托管场景下要扩展一句:修改权限配置的通道,必须和 Agent 使用钥匙的通道完全分离。 如果一个 Agent 能通过同一套接口既发起交易又修改自己的限额,那它的限额不存在。

托管本身没有对错,它是一个取舍:用对手方风险换取更可靠的规则执行和更省的工程投入。 在很多情况下这个交换是划算的,前提是你知道自己换了什么。

如果出事了,你有多久可以反应

这是决定所有上限数值的那个变量,而且大多数权限表在设定数字时根本没考虑它。

算一下这条时间链:异常发生 → 你收到告警 → 你看到告警 → 你判断出这是真的 → 你执行停机 → 停机生效。

每一段都要填一个真实的数字。如果告警在凌晨三点发出,「你看到告警」这一段可能是六小时。而在这六小时里,Agent 按它的频率上限可以做多少次操作、花掉多少钱——这个乘积才是你真正的最坏损失,而不是你写在表上的那个日上限。

从这个算式能倒推出三件事:频率上限应该按「最坏反应时间」来定,而不是按「正常需要」来定停机开关必须快,而且必须不经过模型一个真正有效的自动熔断(比如异常频率触发自动暂停)比任何告警都有价值,因为它不依赖人在场。

有一条原则值得记下来:系统的停机速度必须快于它的犯错速度。

带走的问题

16
Agent 有什么权限?

这一问在这一章有了一个确定的形式:一份八个字段的表。

身份、单笔上限、累计上限、频率上限、目标白名单、授权上限、审批条件、有效期与撤销。少一个字段就多一个洞,而且思想实验里那三个人分别演示了漏掉第 3、第 6、第 7 个字段的后果。

但比字段更重要的是那个追问:这些规则由谁执行? 同一句话写在提示词里、写在代码检查里、写在钥匙权限里、体现在钱包余额上,强度相差几个数量级。

一个最有用的自检:把权限表删掉,这个钱包还能做什么。 答案就是你真实的风险敞口。

18
哪些决策必须保留 Human-in-the-loop?

这一章给出了一个和直觉相反的答案:人在回路的价值,随着它被触发的次数上升而迅速下降。

所以正确的问题不是「哪些决策要人批」,而是**「人每天能认真批几次,把这几次用在哪里最值」**。答案通常是三类:不可逆且影响面大的操作首次出现的新目标或新动作任何触发了异常信号的请求

配套的三条硬规则:每天审批次数有预算,超出一律自动拒绝;审批有有效期,过期作废;没人处理时默认拒绝,绝不放行。

最后一条没有例外。超时放行等于在最需要人的时刻保证了人不在。

17
AI 错误时谁承担损失?

在这一章,这一问变成了一个非常具体的计算。

损失由部署这个 Agent 的人承担——这一点第 33 章已经说清楚了,软件不是法律主体,责任不会转移。

既然如此,唯一值得做的事就是把「最坏损失」算成一个具体的数字:钱包余额、累计上限乘以反应时间、已授予的授权额度总和,三者取最小。

算出这个数字之后,把它和「我能接受的损失」放在一起比。 这个比较是这一章全部工作的意义所在——它把一份看起来很严谨的规则文档,变成了一个你可以判断的数。

本章自测

一句话带走

Agent Wallet 的核心不是签名能力,而是花钱的策略与上限。

做完这一章的动手环节了?勾上它查看全部进度

本页目录