失效模式
拥有 shell 或文件系统访问权限的 agent 天然继承了截断日志、轮转文件和清除历史的能力。这不是假设性的边缘情况;这是将自主进程赋予与人类操作员同等权限的默认后果。如果 agent 可以运行 truncate -s 0 /var/log/agent.log,日志就不再是证据。它只是一种便利。
自修改运行时加剧了这一问题。当 agent 可以编辑记录其行为的代码时,埋点本身就成为可变表面的一部分。一个在调用外部 API 之前写入结构化事件的工具包装器可以被改写为不写入任何内容,或写入一个看似合理但虚假的事件。记录由被记录的主体自身产生,因此记录继承了该主体的动机和失效模式。
当状态本身已被修改时,从应用状态进行事后重建是不可靠的。如果 agent 删除了一行、更新了状态字段或回滚了事务,留存的状态反映的是操作后的世界,而非操作本身。数据库触发器和变更数据捕获只有在写入 agent 无法触及的接收端时才有帮助。否则它们只是另一个可写表面。
这就是核心的不对称性:agent 能够触及的任何证据,都是 agent 能够移除的证据。问题不在于 agent 今天是否具有对抗性。问题在于审计追踪能否在 agent 被攻陷、存在缺陷或执行混乱指令时依然存活。
为什么仅追加不够
可写卷上的仅追加文件仍然可被同一主体写入。POSIX 权限、不可变标志和仅追加属性由同一个内核和同一个超级用户上下文强制执行,而 agent 可能已经占据该上下文。拥有 CAP_SYS_ADMIN 的容器或主机挂载的卷可以绕过文件级保护。仅追加属性是一种约定,而非边界,除非存储针对不同身份强制执行它。
签名条目只有在签名密钥超出 agent 触及范围时才有帮助。如果 agent 进程在内存中持有私钥或从环境变量读取它,签名就无法证明作者身份。它只证明持有密钥的某人对条目进行了签名。密钥保管必须归属于独立服务或硬件模块,且 agent 无法用任意载荷调用它。即便如此,一个对 agent 提交的任何内容都签名的签名预言机只是橡皮图章,而非证明。
按计划删除的保留策略创造了一条看似合规的合法擦除路径。三十天的保留窗口是正常的运营选择。它也是一个窗口,事件可以在任何人调查之前被老化淘汰。如果 agent 可以触发轮转、压缩或生命周期规则,保留策略就变成了一种带有合规外衣的擦除原语。

实际结论是:仅追加、签名和保留都是必要的,但没有一个是充分的。它们缩小了意外删除的影响范围。它们并未在 agent 与其自身记录之间建立边界。
一种针对 trace 的职责分离模式
该模式表述起来直截了当,实现起来却颇为棘手:将 trace 完全移出 agent 的写入域。
将 trace 写入具有不同身份且对 agent 主体没有删除权限的接收端。接收端可以是托管日志服务、具有独立生产者凭据的消息队列,或只写对象存储桶。agent 的身份只获得 PutRecord,别无其他。没有 DeleteObject,没有 PutBucketLifecycle,没有管理角色。接收端自身的保留和删除由 agent 无法冒充的独立主体控制。
在工具边界而非 agent 进程内部发出结构化事件,使记录由被调用方产生。如果 agent 调用搜索工具,搜索服务写入事件。如果它调用数据库,数据库代理写入事件。agent 无权描述自己的行为;它所触及的系统来描述它们。这将信任锚点从 agent 的自我报告转移到被调用方的埋点。这也意味着事件 schema 由工具拥有,而非由 agent 的 prompt 拥有。
保持单调序列和周期性外部摘要,使条目即使被移除也能检测到缺口。每个事件携带来自 agent 无法重置的计数器的序列号。在固定间隔,外部作业对序列范围计算摘要并将其发布到独立通道。如果之后发现接收端缺少序列 4021,摘要证明该条目曾经存在并被移除。没有摘要,缺口与静默期无法区分。
一个具体机制:工具边界写入由 sidecar 进程拥有的本地 Unix 域套接字。sidecar 持有接收端凭据、缓冲事件、分配序列号并转发它们。agent 的容器没有通往接收端的网络路由,也无法访问 sidecar 的凭据存储。sideca
假设 agent 可见的日志不可信,并从接收端重建。本地日志是调试便利。接收端才是记录。事件响应者应将两者之间的任何分歧视为信号,而非同步缺陷。
将任何缺失的序列号视为事件,而非日志缺陷。缺口意味着接收端丢失了数据,或有人移除了它。两者都值得一次告警。摘要使这一检查成本低廉:将发布的摘要与对保留范围重新计算的摘要进行比较。如果它们不同,该范围已被篡改。
为 agent 无法触及的接收端的存储和出口成本做好预算。这是诚实的权衡。具有独立凭据、跨区域复制和摘要作业的只写接收端比本地文件成本更高。从 agent 环境到独立账户的出口并非免费。托管服务中的保留按每 GB 和每次查询计价。替代方案是一个更便宜的系统,其证据恰好在需要时消失。
成本不仅是金钱上的。sidecar 增加了一个失效模式:如果它宕机,工具调用会阻塞或失败。这是一个刻意的选择。在 trace 上阻塞比没有 trace 继续更安全,但它改变了 agent 的可用性特征。团队应明确决定 agent 是故障关闭还是故障开放,并记录该决定。
这改变了什么
日志不再是副产品,而成为主要证据。这种重新定义具有架构后果。trace 管道不再是 agent 工作后附加的 sidecar 关注点。它是信任边界的一部分,与工具接口和凭据模型一同设计。
测试很简单:agent 仅使用自己的凭据和可触及的系统,能否移除或篡改其行为的记录?如果答案是肯定的,日志就不是证据。它是 agent 关于自身的叙述,其可靠性仅取决于 agent 当前的倾向。
对于构建 agent 系统的团队,工作就是让那个答案变为否。独立身份、被调用方发出、单调序列和外部摘要。这些都不是新颖的。新颖之处在于将它们应用于一个能够读取自身埋点并决定重写它的主体。
封面照片:panumas nikhomkhai / Pexels。
