跳到主要内容

你的故障指挥官无法执行的智能体运行手册

· 阅读需 10 分钟
Tian Pan
Software Engineer

报警在当地时间 02:17 响起。值班 SRE 在手机上打开智能体运行手册,阅读第一步:“检查智能体的工具调用追踪,寻找异常的工具使用情况。”他们打开链接,却遇到了一个他不属于的工作区的 SSO 登录提示。第二步说要检查提示词构建日志;同样碰壁。第三步说回滚到上一个提示词版本,但部署权限被限制在了一个他不在的团队中。等他弄清楚该向哪个 Slack 频道上报,并叫醒 AI 团队的产品经理时(因为她是 02:17 唯一能找到的人),九十分钟已经过去了,而客户可见的回归故障仍在持续给出错误答案。

事后分析会将权限鸿沟确定为直接原因。而更深层的不适感在于,这份运行手册在白天读起来很顺畅,但在深夜执行时却被封锁,因为编写手册的人拥有执行者所不具备的权限。

这种故障模式悄无声息地潜伏在几乎每一个在生产环境中存活过第一个季度的智能体产品中。AI 团队构建了智能体、智能体的可观测性以及智能体的部署流水线。他们根据自己用于调试的工作流编写了运行手册。这份手册在技术上是正确的,但在操作上对于实际执行它的人来说是无法交付的。

作者角色并非读者角色

每份运行手册都有两个角色,而大多数智能体运行手册都混淆了它们。作者角色是构建系统的工程师,知道追踪信息存在哪里,拥有每个后端服务的凭据,并能用代码库的术语描述故障模式。读者角色是那个在 02:17 被传呼的人。在大多数组织中,这是两个不同的人;而在拥有专门 AI 平台团队的组织中,他们必定是处于不同值班轮换、拥有不同权限的不同人员。

传统的服务运行手册能够跨越这种鸿沟,是因为服务团队和 SRE 轮换团队已经为此磨合多年。这里存在一个默契的契约:运行手册中的任何内容都必须能从中央值班人员的权限配置文件中执行。仪表盘在 Grafana 中呈现,而不是在团队特定的工具中。日志进入中央日志存储,而不是私有的 S3 存储桶。部署通过共享的部署控制台进行。当一个服务团队忘记了这个契约时,SRE 团队会在第一次演练中察觉,发送严厉的消息,然后运行手册就会被重写。

智能体运行手册打破了这个契约,因为在谈判该契约时,AI 平台团队通常还不存在。他们是为了追求速度而快速组建的,出于效率或成本原因拥有自己的可观测性技术栈,并且拥有自己的部署流水线,因为提示词不是代码,代码审查无法捕捉提示词的回归。这些本身都没有错。错误之处在于,他们交给值班人员的运行手册读起来就像他们自己调试工作流的 Readme,完全没有意识到执行它的人并不拥有他们的工具。

联邦化是你正在回避的词

每个人首先尝试的廉价修复方案是将 SRE 轮换团队添加到 AI 平台的工具中。授予他们进入提示词可观测性仪表盘的 SSO 权限。将他们加入部署组。为他们发放追踪存储的凭据。这对于一次值班轮换有效,但在下一次有人加入或离职时就会失效,并创造一个让安全团队在下次审计中提出刁难问题的访问面。这不是联邦化(Federation),这是增加了额外步骤的访问权限扩张。

正确的做法是将 AI 平台的遥测数据推送到值班人员已经在使用的可观测性界面中。选择一个供应商中立的仪表化标准(OpenTelemetry 是显而易见的选择),并通过它发送智能体追踪、提示词构建日志和工具调用决策。将产生的数据联邦化到中央可观测性技术栈中。事故指挥官打开他们为任何服务都会打开的同一个 Grafana 面板,看到智能体的行为与其他一切并列,且不需要一套单独的凭据就能查看。

这比直接分发登录账号需要更多的工作,而这正是团队默认选择分发账号的原因。这部分工作在第一次有人加入 SRE 轮换而 AI 团队没有收到相关的 JIRA 工单时就得到了回报。在第二次涉及三个服务的事故中,事故指挥官不需要在工具之间切换时,它再次得到了回报。联邦化工作是少数几项在突然需要它之前,回报一直处于隐形成形态的基础设施投资之一。

运行手册编写即权限契约

一旦实现了联邦化,运行手册本身就需要一种大多数团队从未实施过的纪律:每个步骤必须声明它需要什么权限,并且合并前检查(pre-merge check)必须验证值班轮换人员是否确实拥有该权限。

这听起来很官僚,直到你也遇到过类似情况。一个写着“将提示词回滚到上一个版本”的运行手册步骤实际上是一个权限契约:它断言读者持有提示词注册表的“部署回滚”作用域。让这种断言变得显式化。用它所需的作用域标记该步骤。在合并时,针对值班轮换成员身份验证该标签。如果轮换团队不持有该作用域,则运行手册不得合并,直到获得授权、该步骤被改写为使用“破窗”机制,或者指派另一个轮换团队作为责任方。

这种纪律与我们应用于类型化函数签名的纪律是一样的。运行手册步骤是对事故指挥官权限集的一个函数调用,而未声明的作用域就相当于运行手册中的无类型参数。它能编译,在审查中看起来没问题,但在运行时由于输入不匹配而崩溃。

这种检查本身并不罕见。大多数身份提供者通过 API 公开组内成员身份,大多数部署系统发布其作用域目录,而值班轮换团队就是你传呼工具中的一个列表。将这三者连接起来,添加一个 CI 步骤,当轮换团队不具备断言的作用域时使运行手册 PR 失败,这样故障模式就会从凌晨 02:17 堆满屏幕的身份验证提示,转变为周二下午的一个代码审查评论。

AI 团队欠 Oncall 的紧急访问路径

有些步骤无法被包裹在权限契约中,因为对于“Oncall 是否应该拥有此范围权限?”这个问题的回答是否定的。部署新的 Prompt 版本需要理解该 Prompt 的人员进行评审。轮换工具的 API Key 可能需要与下游团队协调。永久授予 Oncall 那些权限是错误的做法。

你欠他们的是一种紧急访问(Break-glass)机制,其范围仅限于 IC 在处理故障时实际需要采取的操作,并在事后进行严格审计。一个“仅限回滚”的部署端点就是典型案例。它只接受一个输入(前一个版本的标识符),并生成一个产物:一个回滚后的 Prompt。它不能部署新 Prompt,不能编辑现有 Prompt,也不能更改工具连接。IC 无需成为部署团队成员即可调用它,每次调用都会在事后通知部署团队进行审查,并且由于该端点只能执行一项操作,其访问面保持在极小范围。

紧急访问模式在云操作中已广为人知,对于 AI Agent 的回滚也是如此;失败的模式在于团队将其视为稍后构建的企业级功能。它是一个在第一次故障发生前就该构建的故障生存功能。Agent 的回滚单元不仅仅是一个模型版本:它是一个由 Prompt 包、工具契约、策略层、记忆平面和运行时权限组成的整体。紧急访问端点应该恢复这些内容的已知良好组合,而不仅仅是切换模型指针。仅恢复一半的内容会让 Agent 处于一个从未经过测试的配置状态。

当读者不是作者时,演练是必选项

即使有了联邦化、声明范围和紧急访问端点,Runbook 依然会失效。权限会变,工具会重命名,Prompt 注册表会增加步骤。保持 Runbook 可执行的唯一方法是让 IC 定期针对模拟故障完整地执行它。

这正是 AI 团队的直觉再次误导他们的地方。他们会提议由自己来“测试” Runbook。那不是对 Runbook 的演练,而是对 AI 团队的演练。真正重要的演练是:让那位可能在凌晨 02:17 被呼叫的 SRE 在毫无准备的情况下打开 Runbook 并走一遍流程。每一个返回身份验证提示的步骤、每一个指向无法读取的仪表盘的链接、每一个自 Runbook 编写以来已更改的工具名称、作者对系统熟悉程度的每一个假设,都会在演练中暴露出来。在周二下午暴露这些问题,而不是在收入流失的周六晚上。

成熟的服务团队已经这样做了;AI 平台团队在文化上的转变在于接受他们的系统现在是一个多团队运维责任,并相应地配置演练频率。一个合理的初始频率是每季度一次。每季度演练可以捕捉大多数陈旧失效而不会成为负担。一旦实际故障暴露了 Runbook 的漏洞,该 Runbook 就要转为每月演练一次,直到连续两次运行无误。

这一切背后的架构现实

组织必须内化的认知对 AI 平台团队来说是不舒服的,但对任何运行过 SRE 职能的人来说都是显而易见的。生产环境中的 Agent 是多团队的运维责任。构建它的团队负责设计,运营它的团队负责 Runbook,被呼叫处理故障的团队负责执行。这三个团队是不同的团队,而 Agent 平台存在的时间还不够长,不足以让他们协商好接口。

在他们协商好之前,AI 团队编写的每份 Runbook 都只是一份看起来正确但执行受阻的文件。联邦化弥补了可观测性差距。声明范围弥补了权限差距。紧急访问端点弥补了部署差距。演练弥补了陈旧失效。这些都不是艰深的基础架构工作。所有这些都需要承认 Runbook 的作者和读者是不同的人,拥有不同的权限,在不同的轮值表上,在不同的时间醒来,并且只有当读者能够实际运行该文档时,它才算编写完成。

对于任何在生产环境中运行 Agent 的团队,建议如下:今晚打开你的 Runbook,把它交给下一位轮值的 SRE,让他们从头到尾阅读,期间不要问你任何问题。任何他们无法操作的地方,就是你的路线图。

References:Let's stay in touch and Follow me for more thoughts and updates