Agent 生产环境中,日志无法追溯请求来源、用户意图和真实行为,安全问题被伪装成可观测性缺陷。
把一个 Agent 部署到生产环境,出了问题,然后试着回答一个简单的问题:它到底做了什么?对于很多 Agent 配置来说,你做不到。不是真的做不到。而这个差距是一个伪装成可观测性问题的安全问题。
以下是原因。当你在构建一个 Agent 时,有趣的部分是行为,而日志是你以后才会加上的东西。所以 Agent 会用自己的系统身份认证,通常是一个单一的服务账号或一把共享密钥,然后开始调用。你的下游系统忠实地记录了这些调用。但它们把这些调用记录为来自那一个身份,执行的是通用操作。Read、Write、Query。没有线程能把这些调用追溯到是哪个 Agent 运行导致的,是哪个用户请求触发的,或者模型在实际调用时到底想完成什么。
所以当你去调查时,你得到的是一堆技术上正确的日志行,却几乎什么都告诉不了你。服务账号读取了这些记录。很好。为什么?代表谁?作为哪个任务的一部分?是 Agent 在做它的工作,还是 Agent 被操控去做别的事?日志无法告诉你,因为它们从未被设计成携带那些上下文。
这在自主性方面变得更糟。一个人做可疑的事会留下人形的痕迹,你知道怎么解读。而处于循环中的 Agent 可以在几秒钟内发出数百个调用,如果它们在你的日志中看起来完全相同,事后从那堆相同的调用中找出真正构成问题的少数几个几乎不可能。你有的不是一根针在一堆草垛里,而是一堆相同的针。
有几件事有帮助,值得从一开始就内置进去,而不是事后补救。
给每个 Agent 自己的身份,而不是共享的服务账号。这是所有其他事的基础,因为"某物读取了数据库"和"发票-agent 读取了数据库"之间有本质区别。当你有五十个东西共享一个身份时,你的日志在你还没开始就已经没用了。
在整个调用链中传播追踪或关联 ID。当一个请求进来、Agent 开始进行工具调用时,给每个调用都打上一个 ID,关联到原始请求和具体的 Agent 运行。然后调查时,你可以拉出一个完整的故事,而不是猜测哪些分散的日志行属于一起。
记录 Agent 的决策,而不仅仅是它的动作。系统调用告诉你发生了什么。但你在事件中真正想要的是为什么。记录 Agent 选择的工具、它决定的输入,最好还有推理过程,这样你就能重建它删除了一条记录,而不是仅仅知道它删了记录。"是什么说服了它这样做"往往是提示注入暴露自己的地方。
把 Agent 的操作日志当作安全遥测,而不是调试输出。它应该发送到持久化的地方,被保留,最好还能接入你已有的监控系统。当问题在三天后才出现时,一小时内就滚动的调试日志毫无价值。
对于你部署的任何 Agent,有一个令人不安的测试:如果它现在做了有害的事,你能在不到一小时内精确重建它做了什么、按什么顺序、被什么触发的吗?如果诚实答案是不能,那你拥有的不是一个你迟早会弥补的可观测性差距。你有一个在你的系统中运行的、你根本无法解释的 Agent,无论你是否意识到,这都是安全问题。
按你将来可能在法庭上需要的方式来构建日志。因为到你真正需要它的那一天,你一定会需要它。