阅读需 8 分钟

AI 事件确认应如何保留未关闭的事件

AI 事件确认必须记录责任归属,同时保持事件未关闭。本文讲清安全的状态转换、审批记录、竞态控制和审计设计。

AI 事件确认应如何保留未关闭的事件

代理确认告警,只说明了一件有用的事:某个人或某个系统已经接手调查。代理并没有证明用户已经恢复正常、告警条件已经消失,或下一位响应人员可以停止待命。任何把确认直接变成关闭的集成,都会抹掉这一差别,并在事件记录里写下不实信息。

应该把事件操作设计成相互独立的状态转换,并为每种转换设置单独权限。确认、解决、抑制和路由在告警界面里可能挨在一起,但它们回答的是不同的运维问题。代理应调用范围最窄的操作;当制度有要求时,由人批准影响较大的转换;审计记录则必须同时写明两类参与者。

确认记录责任归属,而不是服务恢复

确认表示响应人员已经接下告警并开始调查。它会改变接下来应由谁行动,也常常会改变升级行为,但它没有说明故障是否仍然存在。

PagerDuty 的 Incidents 文档明确区分了这两件事:已确认事件正在处理中,但尚未解决。确认会认领责任,并在确认超时前停止升级;解决才表示问题已经修复。这个超时机制很重要。如果超时前没有人解决事件,PagerDuty 可以把事件重新改成已触发并继续升级。代理在确认时关闭事件,会悄悄移除这层保护。

Google Cloud Monitoring 使用的术语略有不同,但保留了同样的边界。其文档把 Acknowledged 定义为仍处于打开状态、有人在调查时手动标记的事件。文档还说明,确认不会停止重复通知。休眠或策略变更负责控制通知;而关闭则依赖恢复观测、人工关闭或自动关闭条件。这个行为提醒我们,不能假定告警系统里的所有动词都有相同副作用。

实际契约应该很明确:acknowledge 记录负责人、确认时间以及接下工作的参与者。如果告警系统支持,它可以暂停升级路径。它必须让事件的恢复状态保持打开,保留仍活跃的告警,并且不得修改通知或路由规则,除非调用方通过另一个控制明确请求另一项操作。

这条边界也能保护事件指标。如果确认同时关闭记录,确认时间和恢复时间会落在同一个时间戳上。团队随后会奖励快速点按钮的行为,却失去真正反映用户受影响时长的指标。事后复盘也会继承同样的错误,因为时间线会声称缓解措施生效前服务就已经恢复。

一个代理动词只能对应一次转换

每个代理工具都应公开一个运维动词和一个主要效果。把多个动作捆在一起,在平静的设计评审中看似方便,真正发生故障时却很难推理。

确认回答“谁接下了工作”。它的主要效果是记录责任和确认时间,不能暗示服务已恢复或告警已消除。解决回答“事件是否已经结束”。它在取得恢复证据后关闭记录,不能顺带静默未来的告警或改变负责人。

抑制回答“选定信号是否应创建事件或发送通知”。它在指定范围内阻止部分通知或事件创建,但不会让已经打开的事件恢复。路由回答“谁应该收到或负责这项工作”。它会改变服务、团队、升级路径或负责人,却不能声称目标方已经确认或解决任何问题。

这些定义共同构成授权边界。人们可能愿意让代理确认分配给本团队的任何告警,但要求真人批准解决操作。同一个人也可能只允许在已声明的维护窗口内抑制告警,并且只允许在两个服务之间路由。一个宽泛的 manage_incident 能力无法表达这些选择,除非在内部藏入难以看见的分支。

不要设计带有 ackmuteassignclose 标志的 handle_page 工具。它会让模型根据自然语言选择动作组合,一句被误解的话就可能触发多个修改。分开的工具迫使调用方明确意图,也让网关能分别授权每次转换。

这种分离必须贯穿不同供应商的适配器。如果一家供应商把静默操作称作 snooze,另一家称作 downtime,适配器可以把两者映射到共同的 suppress_notifications 意图。不能因为它们都能让告警器安静,就假装抑制和解决可以互换。

安全的 API 应让非法组合无法表示

一个范围明确的请求模式,比聪明的提示词更能防止事故。下面的请求只能确认一个现有事件,无法偷偷夹带关闭、静默或重新分配操作。

{
  "operation": "incident.acknowledge",
  "incident_id": "inc_01JQ8K4Q6M",
  "expected_version": 17,
  "actor": {
    "type": "agent",
    "session_id": "ses_01JQ8JY2P3"
  },
  "reason": "Accepted investigation after the database latency page"
}

服务器应补充它能够验证的身份事实,而不是让代理提供。模型可以填写原因,但不能信任它声明自己的可执行文件哈希、代码签名身份、用户账号或审批结果。网关应从经过认证的进程和审批通道中取得这些值。

成功响应应说明确切的转换,以及仍然保留的状态:

{
  "operation_id": "op_01JQ8K5D7A",
  "incident_id": "inc_01JQ8K4Q6M",
  "transition": "triggered_to_acknowledged",
  "incident_status": "acknowledged",
  "recovery_status": "open",
  "version": 18,
  "approved_by": "usr_2048",
  "approved_at": "2026-07-24T02:14:31Z"
}

返回 recovery_status: open 看起来可能有些重复,但应该保留。代理常常根据最近一次响应继续推理,明确状态比让模型猜测供应商语义成本更低。这个响应还给编排器提供了一个稳定的测试断言:确认成功,而且恢复状态仍然打开。

不要在确认请求中接受 resolve_if_healthymute_forroute_to 之类相互矛盾的便利字段。这些字段会把单一端点重新变成动作包。如果工作流需要第二个动作,就应发起第二个请求,获得单独决策,并留下单独审计事件。

审批必须绑定到具体转换

审批应授权一个描述清楚的状态变化,而不是笼统地认可某个代理。会话审批可以确认一个已知进程可以运行,但不应自动授权该进程后来发现的每一种事件修改。

每次转换都要记录拟议操作、目标事件、决策前观测到的状态、请求范围、发起请求的代理会话、批准人、决策时间和审批方式。还要保存批准人当时看到的状态版本或供应商事件标识符。没有这种绑定,为事件 A 显示的审批卡可能被用于事件 B;在已触发状态下作出的批准,也可能在别人已经解决事件后才执行。

审批界面应使用运维人员能直接理解的语言。确认数据库延迟事件 inc_01JQ8K4Q6M,并把调查分配给支付值班组 是可以审查的。允许代理操作 则不行。解决操作应展示代理引用的恢复证据,并说明哪些状态仍然活跃。抑制操作应展示确切的信号范围、持续时间和过期时间。路由操作应同时展示当前目标和建议目标。

不要把所有人都压进一个模糊的 actor 字段,要保留四种身份:

  • 请求者是提出变更的代理会话。
  • 批准者是在需要审批时授权操作的人。
  • 执行者是调用供应商的网关或集成身份。
  • 主体是发生变化的事件、告警、服务或路由。

这些身份在审查中回答不同问题。请求者解释自动化为何开始,批准者证明人的授权,执行者把事件与凭证及供应商日志对应起来,主体则防止有效决策漂移到另一个资源。

当存储的密钥要求保护时,Sallyport 可以把 HTTP API 和 SSH 操作置于逐次审批之后,而凭证始终留在加密保险库中,不会交给代理。这个机制很适合事件转换,因为审批可以绑定到具体供应商请求,而不是模型写下的一句自由文本承诺。

竞态会把看似合理的自动化变成虚假时间线

查清是谁确认了告警
Activity 日志记录每次外部调用,Sessions 日志则标明对应的代理运行。

代理推理、等待审批或重试网络调用时,事件状态仍会变化。忽视这种延迟的设计,迟早会确认一个已经解决的事件,把工作从正在处理的响应人员手里路由走,或者在维护结束后应用过期抑制。

应使用乐观并发控制。代理读取版本 17,针对版本 17 提出确认,只有当供应商记录仍符合相关状态时,网关才执行。如果另一位响应人员先改变了事件,就返回说明差异的冲突,不要默默把操作应用到新状态。

{
  "error": "state_conflict",
  "incident_id": "inc_01JQ8K4Q6M",
  "expected_version": 17,
  "actual_version": 19,
  "actual_status": "resolved",
  "retryable": false
}

不要教代理重试每一种冲突。传输超时可能允许使用同一个操作标识符进行幂等重试,状态冲突却要求重新读取,而且通常要重新决策。如果事件已解决,确认就已经过时。如果事件已路由到另一团队,原审批也未必覆盖新的目标。

一种常见故障始于迟迟未处理的审批。代理读取到数据库告警,要求 Alice 批准确认。审批卡等待期间,Bob 缓解问题并解决事件。随后 Alice 批准了过期卡片。粗糙的适配器发送 acknowledge,接收供应商特有的成功响应,甚至把事件强行改回活跃状态,并把 Alice 记录为一项已经结束的工作的负责人。版本绑定会在时间线变得荒谬之前拦住操作。

幂等性解决的是另一个问题。为每个拟议转换分配不可变的操作 ID,并持久保存结果。如果供应商已经应用确认,而网关丢失 HTTP 响应,重试就返回已存结果,而不是添加第二条时间线记录或再次通知。并发保护让意图不被变化后的状态扭曲;幂等性则防止同一意图执行两次。

路由和抑制需要各自的权限

路由改变责任落在谁身上,抑制改变哪些信号会产生噪声。两者都不能证明恢复,也都不应藏在确认操作里。

如果当前服务明显错误,而且还没有人接手,应先路由再确认。确认之后再路由要格外小心,因为响应人员可能已经开始调查。转换应说明责任是否转移、原响应人员是否继续订阅,以及目标方的升级策略是否启动。代理不能从一个团队名称推断这些效果。

抑制必须有明确范围和过期时间。PagerDuty 的 Event Management 文档说明,受到抑制的告警仍可用于取证,但不会创建事件。其 Event Orchestration 文档还说明,不匹配的事件可以路由到某个服务,也可以通过兜底路径受到抑制。这些都是事件进入系统时的决策,不是关闭现有事件的同义词。

Datadog 的 Downtimes 文档还划出另一条有用边界:停机期会静默告警和通知,但不会阻止监控状态转换。如果停机期结束时监控仍处于告警状态,通知可以恢复。这通常才是维护期间真正需要的行为。系统应记住不健康状态,而不是仅仅为了停止通知就把它改写成健康。

因此,抑制请求应包含信号选择器、开始和结束时间、原因、创建者以及到期行为。像整个服务这样的宽范围选择器,应比单个监控组需要更严格的审批。无限期抑制应被拒绝,或走明确的例外流程。代理不能制造一个安静却无人负责的故障。

不要仅仅因为响应人员接下了告警,就在确认后自动抑制。有些系统会在确认时暂停升级,另一些仍会继续重复通知。Google Cloud Monitoring 明确说明确认不会停止重复通知。应保留供应商原有行为,或单独请求抑制,让审查者看得见噪声为何停止。

解决必须依据证据,而不是代理的信心

只有恢复证据符合预先声明的条件时,才能解决事件。一条修复命令成功,只能证明动作执行过,不能证明服务恢复。

这一区别能抓住一种常见自动化故障。代理重启进程,收到退出码零,然后关闭事件。进程启动后未通过就绪检查,三十秒后再次崩溃。命令成功了,服务却从未恢复。根据命令成功关闭事件,会产生两个事件、两次告警和一个虚假的恢复时间,而不是一段连续故障。

应在事件类型附近定义解决证据。可用性事件可能要求告警条件消失并在一个评估窗口内持续正常。队列事件可能要求积压量和最旧消息时长都降到阈值以下。证书告警只有在已部署端点实际呈现预期证书后才能解决,而不是某台主机写入文件后就关闭。

代理可以收集证据并提出解决。网关应在审批中附上观测值、时间戳、来源和任何数据空缺。如果监控仍报告活跃条件,就拒绝关闭。Google Cloud Monitoring 对指标事件正是这样处理:其文档指出,当近期数据仍违反策略时会返回 Unable to close incident with active conditions 错误。

人工解决仍有必要。监控可能延迟,遥测可能失效,响应人员也可能知道受影响服务已按计划退役。覆盖正常流程时要写明原因和批准人,并保留最后一次不健康观测。覆盖是可追责的例外,不能成为削弱常规转换的借口。

重新打开的行为也属于契约。要明确重复信号是重新打开同一事件,还是创建新事件;无论哪种情况都要保留关联标识符。代理不能假设 resolve 会静默下一次事件。PagerDuty 说明,如果还需要处理工作,已解决事件可以重新打开;Datadog 则说明,手动解决监控只会把状态设为 OK,直到下一次评估。下一次不健康评估仍可能再次告警。

审计记录必须保存决策过程

先查看发起请求的进程
会话审批卡会先显示代理进程的代码签名机构,再决定是否允许运行。

供应商活动日志会显示某个 API 凭证调用了一个端点,但通常没有足够上下文解释代理提出了什么、谁批准了什么,以及批准人当时看见了什么状态。应保留独立的决策记录,并把它连接到供应商事件。

完整的转换事件应包含不可变操作 ID、请求负载哈希、标准化动作、目标、变化前后状态、请求者身份、批准者身份、执行者身份、审批方式、决策时间戳、供应商响应标识符和结果。被拒绝和已过期的提案也要记录。一次被拒绝的抑制能解释为何通知继续;过期审批则能解释拟议确认为何没有运行。

要防止记录顺序被悄悄修改。只追加存储、受限写入者、保留控制和密码学链分别对付不同威胁。Sallyport 从同一份加密哈希链审计日志生成 Sessions 和 Activity 两套日志,sp audit verify 可以在没有解密密钥的情况下离线验证密文链。事件集成因而能保留代理运行与每次外部调用的证据,又无需把凭证暴露给代理。

不要只保存代理的自然语言解释。模型可能写出自信但不准确的摘要,所以旁边还要保留结构化事实。已接下延迟告警 这样的原因方便人快速浏览;事件 ID、状态版本、HTTP 请求哈希和审批身份则让调查人员能够验证。

随着集成演进,审计读取者仍需要稳定语义。应为事件模式和标准化动作名称设置版本。如果适配器改变了供应商映射,要记录执行每次调用的适配器版本。否则,新版本改变副作用后,旧的 acknowledge 事件会变得含糊。

有权读取审计记录,不应等于有权读取事件凭证。把验证事件顺序的能力与解密敏感负载字段的能力分开。秘密应在进入记录前就删除,而不是指望每位读取者以后都能安全处理。

把状态转换当作恶劣工作流来测试

顺利路径测试只能证明端点在没有意外时可以工作。事件自动化需要在读取、审批、调用和响应之间的每个位置中断流程并进行测试。

先确立五条不变量:

  1. 确认绝不会把恢复状态从打开改成关闭。
  2. 解决绝不会创建或延长抑制。
  3. 路由绝不表示目标方已经确认事件。
  4. 每个获批的修改都写明请求者、批准者、执行者和主体。
  5. 过期审批不能在不同状态版本或目标上执行。

然后让适配器对接一个可在调用之间改变状态的模拟供应商。在确认等待审批时解决事件;在抑制执行前改变路由;接受请求后返回超时,再用相同操作 ID 发送一次;批准后、执行前撤销代理会话。每种情况都应得到确定结果和一条审计事件。

应测试供应商差异,而不是把差异抹掉。一个告警系统可能在确认时停止升级,另一个可能继续重复通知。标准化响应可以把 escalation_pausednotifications_suppressed 作为独立事实暴露。适配器无法验证的通用副作用就不要承诺。

审查工具描述时,要像审查代码一样保持怀疑。处理这个事件 会邀请模型自行选择结果。记录支付值班组已接手调查,并让恢复状态保持打开 描述的是有边界的转换。工具文本会影响代理尝试发送的请求,因此它也是控制面的一部分。

最后还要测试没有权限的情况。只有确认权限的代理调用解决、路由或抑制时,应收到明确拒绝。拒绝不应自动提供会执行另一种修改的后备方案。安全失败必须让事件保持可见且不变。

后果越大,代理权限越应收紧

分开记录会话与调用
Sallyport 会记录获批进程会话以及每次确认、路由、抑制或解决请求。

权限设计应依据每个动作的影响,而不是依据调用它的工作流是否方便。读取事件、确认已分配工作、转移责任、静默信号以及宣布恢复,在后果不同时就应该得到逐步收紧的授权。

先使用同时写明动词和范围的能力。仅针对支付服务的 incident.acknowledge 比覆盖整个生产环境的 incident.write 更窄。路由授权可以把目标限制在同一小组拥有的服务。抑制授权可以限制选择器和持续时间。解决授权可以要求已批准的证据配置。网关必须根据结构化请求字段评估限制,不能依赖代理的解释。

授权还应包含时间和进程身份。为一项编程任务启动的代理会话,不应在进程退出后继续拥有事件权限。如果审批等待期间有人撤销会话,即便之前的决策当时有效,执行也应失败。审批确认的是一个拟议转换,不能复活已经失去授权的请求者。

权限和审批要分开。权限回答这个请求者能否尝试某类动作,审批回答这一次具体尝试现在能否继续。要求审批无法修补过宽权限,因为审查者最终会产生审批疲劳,尤其当卡片隐藏范围时。同样,如果组织规定影响较大的转换必须由人决定,狭窄权限也不能取代审批。

降低可见性的操作应受到更严格处理。确认增加负责人并让故障保持可见。路由可能把告警移出当前团队的视野。抑制可能让人们听不到持续故障。解决可能把事件从活跃队列移除,并改变绩效报告。这种顺序不是放之四海皆准,但把它写下来能让分歧在代理深夜遇到之前暴露出来。

凭证也应遵守同样边界。如果供应商提供不同角色或令牌,不要仅为确认事件就给执行者一个能够管理排班和服务的账号。如果供应商只提供宽权限凭证,就在网关限制具体操作,并把这个限制明确写入威胁模型。供应商审计显示凭证可以做什么,网关记录必须显示本次请求被允许做什么。

撤销需要可预测的结果。撤销代理会话,应阻止该进程的一切新操作。撤销审批,应在执行尚未开始时阻止所绑定的操作。撤销路由或抑制授权,应阻止后续请求;已有抑制则通过明确取消转换处理。不要悄悄删除旧决策存在过的证据。

团队经常建议在事件开始时只做一次人工审批,让代理处理其余工作。这个想法流行,是因为重复提示会打断响应人员,但它不适合后果混杂的操作。可以为日常访问审批一次代理会话,再把转换审批留给广泛抑制、跨团队路由和解决之类的动作。这样既能让低风险工作继续,也不会让最初仓促的一次点击变成一小时后关闭事件的权力。

部署前,应写一张以动作为行、范围为列的授权矩阵。每个单元格都要决定代理能读取、提出、无需新决策执行,还是只能在审批后执行。加入最大抑制时长、允许的路由目标、可接受的解决证据,以及批准人不操作时的处理方式。空白单元格应拒绝操作,不能从更宽泛的标签继承权限。

要用真实供应商凭证演练这张矩阵。如果网关策略拒绝解决,但另一个已暴露的 HTTP 工具允许代理直接调用供应商端点,这套策略仍然不完整。盘点通往告警系统的每条路径,包括通用请求工具、命令运行器、Webhook 中继和已存脚本。能绕过网关的凭证不应交给代理进程。

审批提示还需要速率控制,但限速必须安全失败。如果代理反复提交相同确认请求,合并相同提案或让多余提案过期。不能用自动批准、自动解决或隐藏事件来应付审批过载。要记录多余请求,以便团队修复制造它们的循环。

告警器安静时,事件仍可以保持打开

告警噪声、响应责任、服务健康和团队路由是相互独立的维度。把它们压缩成一个状态,会让界面看起来简单,却把歧义转移到自动化、指标和事后复盘里。

即使代理完美执行了确认,也要让确认保持狭窄。它可以接下工作、记录谁批准了这次认领,并让事件继续打开。如果工作流还需要新路由、临时抑制,或在验证恢复后解决,就把每一步都变成可见的独立请求和决策。

这种设计会多花几次工具调用,却能换来一条凌晨两点的事件指挥官也能信任的时间线:谁接下了告警,谁允许状态转换,当时系统显示了什么,以及事件最终为何关闭。

常见问题

AI 代理可以自动解决事件吗?

可以,但前提是系统能可靠检查预先声明的恢复条件,而且代理拥有单独的解决权限。命令成功或模型信心十足都不够,监控状态和服务证据必须支持关闭。

代理确认告警时应该发生什么?

系统应记录责任归属、确认时间、请求者身份和任何必要的批准人。事件必须保持打开,抑制或路由只能通过独立操作改变。

确认事件会停止通知吗?

这取决于告警系统。PagerDuty 可以在确认超时前暂停升级,而 Google Cloud Monitoring 说明重复通知仍会继续;应暴露实际观察到的效果,不要假定统一规则。

抑制告警和解决告警有什么区别?

抑制控制选定信号是否创建事件或发送通知。解决表示事件在恢复后已经结束,仅为让告警器安静而使用解决会破坏运维记录。

AI 代理应如何路由事件?

使用专门的路由操作,写明当前目标、建议目标和预期状态版本。该操作应说明责任和升级是否改变,但不能把目标方标记为已经接下工作。

代理操作的审计日志应记录谁?

记录发起请求的代理会话、批准人、执行网关身份和受影响主体。把它们压进一个 actor 字段,就无法判断是谁提出、授权并执行了转换。

怎样阻止过期的事件审批执行?

把审批绑定到事件 ID、请求动作、范围和批准人看到的状态版本。如果任一事实在执行前改变,就返回冲突并重新读取,不能盲目重试。

告警操作为什么需要幂等键?

供应商可能已经应用转换,但网关没有收到响应。使用相同操作 ID 重试,网关就能返回原结果,而不会重复添加时间线事件或通知。

什么证据足以解决事件?

使用与故障模式直接相关的证据,例如告警条件在一个评估窗口内持续消失,或队列指标恢复到阈值以内。修复命令成功只证明命令运行过。

一个代理权限可以覆盖所有事件操作吗?

技术上可以,但不应该这样做。确认、解决、抑制和路由的后果不同,分开的权限和审批可以防止普通认领动作顺带获得隐藏或关闭事件的权力。

Sallyport

Sallyport 替你的 AI 智能体执行 API 调用和 SSH 命令。密钥留在你 Mac 上的本地密钥库里;每次运行由你批准,每个操作都落入一份密封的审计日志。

© 2026 Sallyport · 依据 Apache-2.0 开源 · Oleg Sotnikov