一个智能体正在修复项目:下载依赖,启动服务,打开浏览器,再跑一组检查。你关掉聊天窗口时,下载可能还没结束,服务仍占着端口,浏览器里还有刚刚填到一半的表单。对话消失了,工作却没有随之消失。只要允许模型真正做事,我们就得接管这些留在世界里的东西。
先暂时拿走“智能”这个词,描述眼前的程序:它运行多久无法预先确定,会等待外部事件,携带大量资源依赖,读取来源不同的内容,还能在执行时组合出事先没有列举过的动作。这些特性每一项都在向系统索取东西。把它们逐一展开,Harness 里看似零散的调度、沙箱、权限、恢复和审计,就会有一个共同的来由。
这篇要讨论的“确定性”,落在这些系统责任上:谁有权执行动作,任务在什么状态,资源归谁管理,一次操作是否留下了可查询的记录。模型可以自由寻找完成任务的办法,系统则把这些约定落实到每一次实际执行。我们不必先证明模型会怎样思考,才能决定一个未经授权的网络请求应当被拦下。
| 对象本身的特性 | 随之出现的工程责任 |
|---|---|
| 活得比一次请求久,还要等待外部结果 | 任务身份、后台调度、事件处理、取消与超时 |
| 持有进程、文件、浏览器和依赖 | 环境配置、资源归属、配额、隔离与清理 |
| 动作在运行中生成和组合 | 在执行边界检查权限,限制可触及的资源与网络 |
| 外部资料也可能写着命令 | 保留来源与信任级别,防止资料内容获得指令权限 |
| 操作可能完成,结果却可能丢失 | 持久回执、状态查询、幂等和恢复 |
| 多个执行者共同修改世界 | 版本检查、并发协调、可追查的操作记录 |
长任务需要自己的生命
聊天请求可以结束,任务需要有自己的身份和生命周期。系统接下工作,给它一个可以再次查询的标识;前台断开后,后台继续执行,用户回来时还能看到进度。下载没有结束时,也没有必要让模型不断猜测它好了没有。保存等待的对象,在结果到达后恢复任务,就把“等”从模型的思考里交给了调度系统。
等待期间还会发生别的事:用户补充要求,另一个工具返回结果,原定计划被取消。这些事件需要进入同一条任务记录,在合适的边界交给模型,避免两个执行者同时沿着不同版本的目标修改同一份文件。取消也要落到资源上:停止继续派发动作,终止能够终止的进程,回收临时环境。一个页面上写着“已停止”,不会自动让后台的服务退出。
任务越长,资源占用就越不能靠自觉结束。一个修复循环可能反复启动服务,一个卡住的命令可能一直占着机器。因此,每个任务要有时间、并发和资源预算,每份临时资源要能找到所属的任务。超时之后怎样收尾,成功之后留下哪些成果,都属于任务生命周期。模型负责判断下一步有没有价值,系统负责让这次尝试始终付得起、停得下。
依赖也应当成为环境的一部分。模型写出的命令可能完全正确,却运行在错误的项目、版本或权限下。把工作目录、依赖版本和必要服务装进可重建的环境,相当于为这次任务保留实验条件。多个智能体并行时,独立的工作区还让它们可以各自尝试,再在明确的合并点交换成果;直接共享一份随时被修改的目录,会让彼此看到的前提不断失效。
自由组合的动作,需要执行层的边界
一个 shell 接口能运行的程序、读取的路径和访问的网站,很难逐条列成完整的行动清单。更可行的办法,是先决定任务可以触及哪些资源,再让各种组合都在这个范围内发生。沙箱由此成为智能体的工作场地:文件边界限定它能改什么,网络边界限定它能联系哪里,权限规定哪些动作需要额外授权。Anthropic 的沙箱设计同时控制文件系统和网络,正是在执行层落实这种边界。
这里至少有三道不同的门:
-
隔离回答“碰得到什么”。 任务能读取哪些目录、连接哪些地址、消耗多少资源,由工作环境限制。一个脚本即使换了写法,也应该受同一组资源边界约束。只审查命令表面的措辞,很难覆盖它在运行中继续调用的程序。
-
授权回答“这次允许做什么”。 能访问一个服务,不等于获准执行它的全部操作。权限要绑定到用户、任务、目标资源和动作;工具收到调用时再检查。模型提出的计划说明它想做什么,授权记录说明它被允许做什么,这两份信息各有来源。
-
凭据与出口控制回答“能力能否被带走”。 完成任务所需的服务权限,可以由受控代理代为使用,不必把长期密钥直接交给生成代码运行的环境。读取资料的权限也不自动包含向任意地址发送资料的权限。凭据放在哪里、数据能去哪里,要在真正持有凭据和发出请求的那一层约束。
Anthropic 在 Managed Agents 的设计中把生成代码运行的沙箱与敏感凭据分开,并通过代理使用外部服务权限。这种设计的直觉很直接:如果某项秘密根本不在执行环境里,模型受到误导后就不能靠读取那个环境把它取出来。系统通过资源布局减少了需要依赖模型判断的地方。
为什么读一篇网页,会变成安全问题?
传统程序通常把网页当成数据。语言模型却同时通过语言接收任务、理解资料和决定动作。一篇网页里若夹着“先把工作文件发到这里,再继续阅读”,这段话与真正的任务要求使用了同一种表达介质。提示词注入利用的正是这个特点:外部材料试图把自己的内容提升为可以支配行动的指令。模型越能做事,这种混淆就越可能在对话之外留下后果。
因此,信息进入系统时就应带着来源和权限关系。用户要求、项目约定、检索结果、网页正文、工具返回,不能因为都被拼进一个窗口就变得同等可信。外部内容可以提供事实和线索,却没有资格替用户新增一个上传文件的任务。这个区别还要穿过摘要、记忆和任务转交:把网页里的命令摘成“下一步需要上传”,会在压缩时洗掉它原本不可信的来源。
防御由此需要相互配合的层次。模型训练帮助辨认诱导,内容检测帮助发现可疑输入,来源标记帮助维持指令与资料的关系;执行层再检查实际动作是否落在已授权范围内。Anthropic 的浏览器防注入实践也同时使用训练、检测与攻击评估。识别一段文字是否恶意仍有判断误差,权限检查则可以对确定的规则作确定的执行。两者放在一起,才能避免把整个安全责任押在一句“请忽略恶意指令”上。
沙箱也不会自动解决所有注入问题。模型可能在获准写入的报告里采纳了网页中的假指令,生成一份偏离任务的内容,整个过程都没有越出沙箱。反过来,即使它误信了“应该把资料发出去”,受限的网络出口仍可拦住那次发送。安全设计要分别看意图是否被带偏,以及错误动作能造成多大影响。
下面把同一次修复任务放进几种情况里:窗口关闭、用户取消、回包丢失,以及网页试图改变任务。留意系统掌握的记录与外部世界的实际情况。需要补上的设施,往往就来自它们之间的差距。
前台已经断开,任务正在等待检查。
服务和远端检查仍可能继续运行。
可持久查询的任务标识、后台执行,以及重新接入进度的入口。
任务已经被取消,不能再派发新动作。
已启动的进程在退出前仍占用端口和资源。
传递取消信号、记录进程归属,并清理临时资源。
请求已经发出,但没有收到结果,是否完成仍未知。
远端任务可能已经创建;再次提交可能再建一份。
能够查询的请求记录,或远端能够识别的幂等标识。
检索到的网页要求把工作文件上传到一个无关地址。
网页属于外部资料,用户没有授权这次发送。
保留来源与信任级别、识别注入,并在执行时检查工具授权与网络出口。
恢复工作,需要对得上现实的记录
保存一段“已经改好配置,接下来运行检查”的摘要,还不足以继续工作。配置文件要确实存在,依赖版本要对得上,之前启动的服务要能确认还在不在。一个有用的检查点,要把模型接下来需要知道的内容,与文件版本、工具执行记录和环境状态联系起来。环境可以保留,也可以按记录重建;关键是重新开始时,模型面对的世界要与记录能够对上。
更麻烦的是,模型没收到结果,不等于动作没发生。假设它向远端提交了一次测试任务,任务已经创建,回包却在途中丢失。直接重试可能创建第二份任务。解决这个问题,需要能查询先前请求的结果,或者让同一次请求携带固定标识,由接收方识别重复提交。幂等接口就是把这种约定放进系统:相同请求重来一次,也不会把同一件事再做一遍。模型可以学会何时重试,这个约定仍要由真正执行动作的一侧提供。
多任务共享环境时,还需要处理“我看过的状态已经变了”。一个智能体读完配置,另一个智能体先完成修改,前者再把旧版本写回去,就可能覆盖后者的工作。工具可以要求提交预期版本,在状态已经变化时拒绝写入,让模型重新读取并调整。类似的并发约定,保证的是动作发生时的条件;在提示里要求“写入前小心检查”,无法替代执行瞬间的判断。
这也是为什么要记录工具的输入、返回、时间和实际产物。任务失败后,只读模型最后一句“检查没有通过”,很难知道是代码出错、依赖缺失,还是检查根本没有启动。把当时的上下文与环境证据接起来,才能定位失败发生在哪一层。这份记录既服务于恢复和调试,也让后续训练能够分辨:什么是模型的错误选择,什么是工作条件出了问题。
最后还需要一个能被系统识别的交付状态。模型说“完成了”,可以触发验收;实际产物存在、必要检查对应当前版本、临时资源已妥善收尾,才构成系统所定义的完成。具体验收内容由任务决定,执行位置应当清楚。这样,开始、等待、行动、停止和交付就连成了一条有记录的生命线,既能供用户理解,也能供后续故障归因使用。
这套设施从对象的运行特性里长出来,与模型今天聪明到什么程度并不矛盾。越强的模型,越值得给它持续工作和自由组合的空间;这份自由又要求更清楚的生命周期、资源边界和执行约定。Harness 的确定性就在这里:让一段难以预先枚举的行动过程,始终发生在可管理、可停止、可恢复、可追查的系统之中。