这个案例实际说明了什么
费城的一则新闻报道描述了一个自动化系统——或依赖该系统的操作员——转发了一条最终被证明为虚假的线报,而在任何人来得及核实之前,后果已经落在了一个真实的人和一个真实的机构身上。归因的细节不如失败的形态重要。agent 做了它被要求做的事。伤害来自一个前置条件从未被指定的动作:在线报离开机构之前需要什么证据,有多少独立来源已经佐证了它,接收方在收到之后能否撤销任何东西。
这与我们每周在 tool call 评估中看到的失败属于同一类。每个调用都符合 schema。JSON 能解析,参数匹配声明的类型,传输层返回 200。结果仍然是错的,因为有效性不等于符合策略。一个 tool call 可以在形式上正确,却在上下文中构成取消资格:消息发给了错误的接收方,记录基于单个未经验证的字段被更新,通知推送给了无法当作没看见的第三方。
把它框定为幻觉问题,会引向一个不可能奏效的模型修复。如果模型编造了一个细节,你尚可合理地要求更好的 grounding。但在费城模式中,模型可能只是如实报告了它被给予的内容。缺口在生成的上游:系统中没有任何东西说过此动作在获准之前需要两个独立来源。再多的 prompting 也填补不了一个从未被写成需求的缺口。
具有后果的工具需要前置条件
有用的区分不在于好模型与坏模型之间,而在于留在组织内部的工具与触达第三方的工具之间。对内部索引的 retrieval 调用出错代价很低。而一个向监管机构发邮件、提交报告、发布关于具名个人的声明或派遣现场团队的调用则不然。
对于第二类中的任何工具,wrapper 至少应声明三件事。
- 必需证据。 在调用被允许之前,哪些字段必须存在且非空,以及每个字段必须携带什么 provenance。只有单一非结构化来源的线报,与带有来源、时间戳和佐证记录的线报不是同一个对象。
- 佐证数量。 必须有多少个独立来源一致。独立性是难点;从同一上游 feed 复制的两个字段是一个来源戴了两顶帽子,schema 应编码 provenance 图,使数量是被计算出来的而非被断言的。
- 可逆性类别。 该动作能否被撤销,以及由谁撤销。发送内部草稿是可逆的。向外部合作伙伴发送线报则不可逆,因为接收方已经读过了。

不可逆、影响第三方的动作需要一条单独的审批路径,并指定具名的人类负责人。不是通用队列,不是共享邮箱:而是一个具体的、可问责的角色,由审计日志在审批时刻记录。审批与其他任何前置条件一样,由同一机制评估。
前置条件检查属于 tool wrapper,而不属于 prompt。wrapper 位于模型提议的调用与副作用之间。它接收参数,查阅已声明的前置条件,对照当前状态进行评估,然后要么允许调用,要么返回结构化拒绝。因为它存在于代码中,它能经受模型升级、prompt 重写和新 agent 框架的到来。因为它返回拒绝而非静默改写请求,模型可以被告知为什么,并可以选择另一条路径,而拒绝本身也成为一条记录。
为什么 prompt 承载不了这件事
指令在争夺上下文。一个系统 prompt 若在任务框架、工具描述、格式规则和当前对话之外还承载运营策略,那么策略在其中只是众多声音之一。在长程任务中,这个声音不会变得更响;它会变得更远。到第二十轮时,写在上下文顶部的告诫只是模型可能加权也可能不加权的一个事实,而从外部无法分辨是哪种。
在代码中检查的前置条件会产生带有原因的拒绝。该拒绝是一个离散事件,带有时间戳、输入、规则标识符和结果。它可以被计数、采样和重放。prompt 层面的告诫不会产生任何事后可检查的东西。如果一条线报发出去了,你想知道系统是否考虑过佐证,用 prompt 的答案是我们要求过它。用 wrapper 的答案是一行日志。
这里有一个诚实的权衡,而且不小。代码中的前置条件会增加延迟和摩擦。每个具有后果的调用现在都要等待一次评估,其中一部分会被拒绝并需要人来查看。在最初几周,这个比例令人不适,因为 schema 比它所取代的非正式流程更严格。团队会感觉系统在挡路,放松规则的压力立刻出现。反向压力在于:放松的前置条件在失败之前不可见,而严格的前置条件立即可见。成本在前期支付,且在你能够看见的地方。
第二个权衡:前置条件的质量取决于它所读取的状态。如果佐证数量依赖于上游系统填充不一致的 provenance 字段,检查就会放行本不该放行的东西。这就是为什么评估必须与调用一起记录,并附上它实际看到的输入。当前置条件被证明是错的时,日志会告诉你究竟是规则有问题,还是喂给它的数据有问题。

设计规则:先分类,再附加
实用规则是按影响范围和可逆性对工具分类,然后把前置条件附加到类别上,而非附加到单个 prompt 上。工具的类别是工具自身的属性,声明一次,在工具变更时审查。每个能触达该工具的 agent 自动继承该类别及其前置条件。新 agent 不需要被教导谨慎;它们需要被给予已经自带谨慎的工具。
一个最小声明如下所示:
tool: submit_external_tip
blast_radius: third_party
reversibility: irreversible
preconditions:
- rule: evidence.required_fields
fields: [claim_text, source_id, source_timestamp]
- rule: corroboration.min_independent
count: 2
provenance_field: source_lineage
- rule: approval.named_principal
role: duty_editor
on_fail: refuse_with_reason
wrapper 按顺序评估每条规则,并产生三种结果之一:允许、带原因拒绝,或升级给具名负责人。评估记录与调用写在同一 trace 中,因此数月之后决策仍可重建:哪些规则运行过,它们读取了什么值,哪一条拒绝了,以及如果有人批准,是谁批准的。
这是不 glamorous 的工作。它看起来像 schema 设计和访问控制,而非 AI 工程,这也是它被跳过的部分原因。但费城模式不是靠更好的模型或更谨慎的 prompt 解决的。它靠的是把前置条件变成附加到工具上的一等对象,在代码中评估,并记录在它所治理的动作旁边。Agent 会继续做它们被要求做的事。问题在于它们被要求做的事是否已被约束到组织实际愿意让其发生的范围之内。
首先应该埋点监测什么
从清单开始,而不是从模型变更开始。列出任何 agent 能调用的每个工具。对每个工具,记录它是否触达第三方、能否被撤销,以及必须存在什么证据,组织才能在六个月后的审查中为该动作辩护。最后一个问题没有明确答案的工具,就是需要在下次部署之前——而非下次事故之后——加上前置条件的工具。
然后把评估接入 trace。未被记录的拒绝与从未发出的请求无法区分,未被归因的批准与 agent 独自行动无法区分。上面链接的两篇新闻报道描述的是结果;工程上的回应是让本可阻止它们的前置条件变得明确、被强制执行且清晰可读。
