首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从推荐到修复的四个阶段:使用 Elastic Workflows 实现人机协同自动化

从推荐到修复的四个阶段:使用 Elastic Workflows 实现人机协同自动化

原创
作者头像
点火三周
发布2026-08-31 16:01:56
发布2026-08-31 16:01:56
630
举报

一个没有证据支撑的批准按钮并不是一种控制机制。人机协同自动化将五个要素绑定到一个可审计的记录中:你观察到的证据、你提议的操作、做出决策的人、他们拥有的截止时间,以及实际执行的内容。

在本文中,你将使用 Elastic Workflows 构建这个关卡,并复用配套文章使用 Agent Builder 和 Workflows 构建 SRE 控制平面中的控制平面。这一次,事件的范围足够精确,可以采取行动:一个单一工作节点上的过时定价缓存,并在推荐与修复之间设置一个结构化的审批步骤。这里不会接触生产环境,因此你可以同时运行批准分支和拒绝分支,并对比两者在执行记录中留下的内容。这份记录正是事件响应自动化逐步赢得自主权的方式——一次一个事件类别。

前置条件

  • Elastic Stack 9.4+

在添加审批之前,SRE 控制平面需要什么

本文建立在使用 Agent Builder 和 Workflows 构建 SRE 控制平面的基础上,该文定义了本文使用的控制平面模式:遥测、调查上下文、策略以及一组已知操作,它们被串联在一起。Agent Builder 负责对日志、链路追踪、指标、告警、运行手册和过往案例进行推理。Elastic Workflows 则使用明确的输入和权限执行定义好的序列。人机协同(HITL)正是在证据转化为行动的那个关键点上,将这两项职责连接起来。

Agent Builder 对日志、链路追踪和指标进行推理,同时 Elastic Workflow 执行收集证据、运行分析、创建案例、在 waitForInput 处暂停等待审查者,并分支到批准或拒绝路径
Agent Builder 对日志、链路追踪和指标进行推理,同时 Elastic Workflow 执行收集证据、运行分析、创建案例、在 waitForInput 处暂停等待审查者,并分支到批准或拒绝路径

推荐和修复有着截然不同的失败模式。一个弱的推荐会浪费工程师的时间。一个弱的修复则会改变生产环境。这就是为什么审批关卡应该属于执行模型内部。

使审批关卡成为可靠性控制机制的五个绑定

一个有用的关卡需要保留五个属性。缺少任何一个,关卡都会变弱。

  • 证据绑定:审查者能够看到产生该提议的日志、告警详情、丰富信息或 Agent 推理过程。一个没有证据的“批准”按钮,只是要求一个人接受自动化的置信度。
  • 操作绑定:请求必须指明确切的有界操作、目标、参数和预期效果。一个没有明确目标的请求,可能会授权超出审查者意图的范围。
  • 身份绑定:记录显示谁批准或拒绝了该请求,以及何时做出的决定。没有这一点,你只有结果,却没有问责制。
  • 时间绑定:决策有一个截止时间,过期的请求会失败关闭,而不是在失去上下文后仍然运行。一个没有超时的审批,可能会比支持它的证据本身存活得更久。
  • 结果绑定:执行记录显示运行了什么,跳过了什么,以及操作后验证是否通过。

形式仍然重要,但形式只是更大控制机制中面向人类的部分。审批设计就是可靠性工程。

从 AI 推荐到自动修复的四个阶段

将自主性视为一系列操作状态,而不是一个产品开关。

自主性阶段

系统行为

人类职责

推进证据

0, 观察

搜索日志并汇总上下文。

手动调查并操作。

查询能够找到正确的事件证据。

1, 推荐

提出一个有界的下一个步骤并附带理由。

在工作流外部做出决策并执行。

推荐的准确度足够高,可以快速审查。

2, 审批

在操作前暂停,仅在有结构化输入时恢复。

批准或拒绝确切的提议。

审批质量、执行成功率和回滚行为被度量。

3, 窄范围自动化

针对已证实的事件类别,自动执行相同操作。

审查异常并审计样本。

范围、权限、超时、验证和回滚仍被强制执行。

重要的过渡是从阶段 1 到阶段 2。这是系统不再是顾问,而是获得执行路径的时刻。即使 AI Agent 参与了调查,该路径也应该是确定性的:Agent 总结证据并推荐一个操作,而工作流则负责暂停、结构化决策、分支以及执行记录。

在 Elastic Workflows 中构建人机协同自动化关卡

Elastic Workflows 为此提供了 waitForInput 步骤。当执行到达该步骤时,工作流会进入 WAITING_FOR_INPUT 状态并等待人员操作。审查者在 Kibana 执行视图(或通过恢复 API)中填写一个小表单,他们提交的任何内容都会在后续步骤中通过 steps.<step_name>.output 可用。

工作流会拉取最近 30 分钟的 checkout-api 失败日志,将其交给 Agent Builder 进行根因分析,并将该分析写入一个可观测性案例中。然后停止并询问一个问题:是否应该清除 checkout-worker-07 上的定价缓存?如果批准,它会记录模拟操作,运行一个验证查询,并将结果追加到案例中。如果拒绝,它会记录决策,不执行任何操作。无论哪种方式,生产环境都不会被触及。

从触发器到证据收集,再到提议的有界操作,在 WAITING_FOR_INPUT 中暂停,然后分支到记录决策的拒绝路径,以及执行、验证并将结果记录到案例中的批准路径
从触发器到证据收集,再到提议的有界操作,在 WAITING_FOR_INPUT 中暂停,然后分支到记录决策的拒绝路径,以及执行、验证并将结果记录到案例中的批准路径
代码语言:yaml
复制
name: obs-labs-checkout-control-plane-hitl
description: 基于 OpenTelemetry 的 checkout 控制平面的人机审批关卡。
enabled: false
tags:
  - sre-control-plane
  - agent-builder
  - human-in-the-loop
  - workflows
  - opentelemetry
settings:
  timeout: "30m"
triggers:
  - type: manual
consts:
  incident_id: "obs-labs-checkout-hitl-20260719"
steps:
  - name: collect_evidence
    type: elasticsearch.search
    with:
      index: "logs-*"
      size: 10
      query:
        bool:
          filter:
            - range:
                "@timestamp":
                  gte: "now-30m"
            - term:
                "service.name": "checkout-api"
            - term:
                "attributes.incident.id": "{{ consts.incident_id }}"
            - match_phrase:
                "body.text":
                  query: "checkout failed: stale pricing cache"
  - name: rca_analysis
    type: ai.agent
    agent-id: elastic-ai-agent
    create-conversation: true
    with:
      message: |
        调查由 {{ consts.incident_id }} 标识的 checkout-api 事件。
        工作流证据查询在最近 30 分钟内找到了 {{ steps.collect_evidence.output.hits.total.value }} 个匹配的 OpenTelemetry 日志事件。
        搜索 service.name 为 checkout-api 且 incident.id 为 {{ consts.incident_id }} 的日志、链路追踪和指标。
        确定受影响的 Worker、部署版本、错误类型、HTTP 状态码和延迟证据。
        返回可能的原因、支持证据、置信度,以及以下有界模拟操作是否与证据一致。
        提议的模拟操作:模拟清除 checkout-worker-07 上的定价缓存。
        此工作流不得更改生产环境。
  - name: case_title
    type: ai.agent
    agent-id: elastic-ai-agent
    with:
      conversation_id: "{{ steps.rca_analysis.output.conversation_id }}"
      message: "为这个 checkout 事件生成一个简短的案例标题。只输出标题。"
  - name: case_description
    type: ai.agent
    agent-id: elastic-ai-agent
    with:
      conversation_id: "{{ steps.rca_analysis.output.conversation_id }}"
      message: "生成一个基于 OpenTelemetry 证据的简洁案例描述。包含事件 ID,并说明修复需要人工审批。只输出描述。"
  - name: create_case
    type: cases.createCase
    with:
      title: "{{ steps.case_title.output.message }}"
      description: "{{ steps.case_description.output.message }}"
      owner: "observability"
      severity: "medium"
      tags:
        - sre-control-plane
        - agent-builder
        - human-in-the-loop
        - opentelemetry
  - name: add_agent_analysis
    type: cases.addComment
    with:
      case_id: "{{ steps.create_case.output.case.id }}"
      comment: |
        ## Agent Builder RCA 及提议操作
        证据查询匹配数:{{ steps.collect_evidence.output.hits.total.value }}
        {{ steps.rca_analysis.output.message }}
        提议的模拟操作:模拟清除 checkout-worker-07 上的定价缓存。
        尚未执行任何操作。
        Agent 对话:{{ kibanaUrl }}/app/agent_builder/conversations/{{ steps.rca_analysis.output.conversation_id }}
  - name: review
    type: waitForInput
    with:
      message: |
        批准有界的 checkout 响应?
        事件:{{ consts.incident_id }}
        证据:{{ steps.collect_evidence.output.hits.total.value }} 条匹配的 checkout 失败日志(最近 30 分钟内)。
        目标:checkout-worker-07
        操作:仅在此 Worker 上模拟清除定价缓存。
        预期效果:后续 checkout 请求不再使用过时缓存。
        影响范围:一个 Worker。此模拟步骤不会更改生产环境。
        在决策前,请审查案例 {{ steps.create_case.output.case.id }} 中的 Agent Builder 分析。
      schema:
        type: object
        properties:
          approved:
            type: boolean
            title: "批准模拟缓存清除"
          notes:
            type: string
            title: "审查者备注"
        required:
          - approved
  - name: approved_action
    type: console
    if: "steps.review.output.approved : true"
    with:
      message: "已批准。已为 checkout-worker-07 记录模拟缓存清除。审查者备注:{{ steps.review.output.notes }}"
  - name: verify_after_approval
    type: elasticsearch.search
    if: "steps.review.output.approved : true"
    with:
      index: "logs-*"
      size: 0
      query:
        bool:
          filter:
            - range:
                "@timestamp":
                  gte: "now-5m"
            - term:
                "service.name": "checkout-api"
            - term:
                "attributes.incident.id": "{{ consts.incident_id }}"
            - match_phrase:
                "body.text":
                  query: "checkout failed: stale pricing cache"
  - name: record_approved
    type: cases.addComment
    if: "steps.review.output.approved : true"
    with:
      case_id: "{{ steps.create_case.output.case.id }}"
      comment: |
        ## 人工决策:已批准
        审查者备注:{{ steps.review.output.notes }}
        模拟操作目标:checkout-worker-07
        最近 5 分钟内的验证查询匹配数:{{ steps.verify_after_approval.output.hits.total.value }}
        此演练未更改生产环境。
  - name: record_declined
    type: cases.addComment
    if: "steps.review.output.approved : false"
    with:
      case_id: "{{ steps.create_case.output.case.id }}"
      comment: |
        ## 人工决策:已拒绝
        审查者备注:{{ steps.review.output.notes }}
        未执行任何操作。
  - name: declined_console
    type: console
    if: "steps.review.output.approved : false"
    with:
      message: "已拒绝。未执行任何操作。审查者备注:{{ steps.review.output.notes }}"

collect_evidencerca_analysis 步骤保持了与第一篇文章相同的“证据-推理”顺序,工作流在到达 waitForInput 边界之前就将分析写入案例。当人类被要求做出决策时,推理过程已经是持久且可链接的。

审批表单要求一个布尔值,并接受可选的备注。

只有批准分支会记录模拟缓存清除,运行一个有界的验证查询,并将结果追加到案例中。拒绝分支记录决策,不执行任何操作。

审批请求将结果计数带入决策,而链接的案例则保留完整的 Agent Builder 分析。将计数视为审查者的证据,而非根因声明或性能度量。

将模拟操作替换为真实的自动修复

演练中将批准分支保留为 console 步骤,以便你可以安全地运行两个分支。在生产环境中,你只需将该步骤替换为范围狭窄的外部操作,并保持案例、超时、验证和拒绝路径完全不变。

根据目标系统的访问方式,你有两种选择。

使用 HTTP 连接器调用内部修复 API

在 Kibana 中配置一个 HTTP 连接器,包含基础 URL、认证和任何加密的标头,然后通过 connector-id 引用它。密钥保留在连接器中,永远不会出现在工作流 YAML 中。

代码语言:yaml
复制
  - name: clear_pricing_cache
    type: http
    connector-id: "checkout-remediation-api"
    if: "steps.review.output.approved : true"
    with:
      path: "/v1/cache/pricing/purge"
      method: "POST"
      body:
        worker: "checkout-worker-07"
        incident_id: "{{ consts.incident_id }}"

移交到 Jira、Slack 或 PagerDuty

Kibana 连接器可作为工作流步骤使用,因此批准分支可以为变更管理操作打开一个 jira 工单,向值班渠道发布 slack 消息,或通过 PagerDuty 寻呼——所有这些都使用你团队已集中管理的凭据。

代码语言:yaml
复制
  - name: notify_oncall
    type: slack
    connector-id: "sre-oncall-channel"
    if: "steps.review.output.approved : true"
    with:
      message: "由 {{ steps.review.output.notes }} 批准:已为 {{ consts.incident_id }} 清除 checkout-worker-07 上的定价缓存。"

无论你选择哪种方式,都要保持操作的有界性。

如何设计一个人机协同自动化关卡

上面的工作流展示了具体机制。正确设计关卡是一个设计问题:暂停放在哪里,请求告诉审查者什么,无人应答时会发生什么,以及执行记录需要保留什么。每一点都映射到五个绑定之一。

在事件响应工作流中,审批步骤应该放在哪里?

waitForInput 的最佳位置是紧接在第一个会增加影响的步骤之前。不要在收集证据前暂停,因为工作流通常可以在不接触受影响服务的情况下搜索、丰富、分类和打开草稿案例。也不要在修复后暂停,因为那只是要求一个人批准已经发生的事情。

在任何人启用工作流之前,审查者可以检查证据查询、表单架构、超时、分支条件和操作本身。

一个好的审批请求应该告诉审查者什么

值班工程师不应从五个其他屏幕中重建调查。一上来就给出决策,并仅包含做出决策所需的证据。一个强有力的审批请求按以下顺序回答这些问题:

  1. 我到底在决定什么?
  2. 哪些遥测数据支持这个提议?
  3. 操作将使用什么目标和参数?
  4. 预期效果和影响范围是什么?
  5. 如果我拒绝或什么都不做,会发生什么?

一个必须的决策加上可选的备注通常就足够了。如果审查者需要输入服务名称、主机标识符、环境、操作参数,那么提议在暂停之前就不够具体。

提供操作对话框,显示审批请求,包括事件、证据计数、目标 Worker、预期效果和影响范围,上方是一个 JSON 表单,用于提交批准的决策
提供操作对话框,显示审批请求,包括事件、证据计数、目标 Worker、预期效果和影响范围,上方是一个 JSON 表单,用于提交批准的决策

暂停的执行在历史记录中仍然是可发现的,并且可以由任何授权审查者恢复,这引出了一个队列需求。一旦一个团队拥有超过几个暂停的执行,审查者就需要一个收件箱或等效的筛选视图,显示待处理的决策、年龄、所有者、严重性和目标。否则,一个安全的暂停就会悄然变成一个不可见的积压。

如果没有人及时批准,会发生什么?

waitForInput 没有默认超时;执行会无限期等待。settings.timeout 字段限制了整个执行的时间,包括等待输入的时间,在此工作流中,30分钟的值限制了提议在收集证据后的可操作时间。

根据事件和操作选择该值:在活跃故障期间,流量切换可能需要几分钟内做出决策。维护审批可能有效数小时。确认你操作的确切 Elastic 版本上的超时行为,并如果你观察到的情况不满足你的“失败关闭”要求,则添加一个外部升级或取消路径。

无论如何,都不要将沉默转换为批准。

审计记录必须捕获什么

执行历史记录应能回答四个问题,而无需任何人翻阅聊天记录:

  • 工作流收集了什么证据?
  • 审查者提交了什么确切的输入?
  • 哪个分支运行了?
  • 操作和验证步骤返回了什么?
工作流执行处于等待状态,证据和案例步骤已完成,审查步骤标记为需要操作
工作流执行处于等待状态,证据和案例步骤已完成,审查步骤标记为需要操作
已完成的工作流执行,显示审查者的批准输入已记录在案,操作、验证和案例步骤均已解决
已完成的工作流执行,显示审查者的批准输入已记录在案,操作、验证和案例步骤均已解决

一个暂停的执行显示证据步骤和仍在等待的决策。一个批准的执行会在同一视图中添加操作分支和验证输出。一个拒绝的执行保留相同的证据和相同的决策,同时跳过所有操作步骤。保持演练操作模拟,可以让你在检查两个分支的同时不更改生产环境。

对于更长生命周期的事件上下文,将其推送到案例中。将证据摘要、审查者备注、操作结果和验证结果作为评论添加,案例就成为比执行本身更持久的记录。

如何知道一个工作流已准备好无需审批运行

不要因为少数几次运行成功就移除审批关卡。审查足够多的执行,以同时理解正常和异常路径,并至少度量以下结果:

度量项

它回答的问题

提议接受率

工作流是否识别了正确的事件类别?

审查者编辑或拒绝

哪些证据或操作参数仍然不正确?

审批年龄

团队能否在证据变得过时之前做出响应?

操作成功率

有界操作是否可靠地执行?

验证成功率

操作后服务是否有所改善?

回滚率

响应多久会带来一个新问题?

仅当事件类别、目标选择、操作、验证、权限、超时和回滚路径都狭窄且可重复时,自主执行才是合理的。即便如此,也保持相同的工作流结构。自动化应该绕过已证明路径上的人类等待,而不是绕过证据收集、授权、验证或审计记录。将任何不确定的东西路由回人工审查。

结论

审批关卡只是一小段 YAML,但它改变了自动化的本质。waitForInput 将决策转化为一个结构化输入,分支逻辑依赖于它,因此操作、验证和案例评论之所以存在,是因为一个具名的人在特定时间回答了一个特定问题。将暂停放在紧接在第一个会增加影响的步骤之前,并用 settings.timeout 进行限制,这就是它成为可靠性控制机制而非确认对话框的原因。

将其投入生产环境的变化比看起来要小:模拟的 console 步骤变成 httpslackjira 连接器步骤,其他一切保持不变。从那里开始,你一次一个事件类别地赢得自主权,让接受率、审批年龄、操作成功率、验证成功率和回滚率告诉你,什么时候一个路径已足够证明,可以无需等待运行。

从何处开始人机协同自动化

从一个重复出现的操作信号和一个可逆的响应开始。首先构建证据查询,然后添加一个指明目标和预期效果的推荐,接着在紧接操作之前插入 waitForInput,并在实验室或仅案例模式下运行工作流。与 SRE、开发人员、支持人员、安全团队以及受影响服务的产品负责人一起审查执行历史。

审批关卡不是终点。它是让团队能够向窄范围自主性迈进,同时不放弃证据、问责制或控制的机制。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 前置条件
  • 在添加审批之前,SRE 控制平面需要什么
  • 使审批关卡成为可靠性控制机制的五个绑定
  • 从 AI 推荐到自动修复的四个阶段
  • 在 Elastic Workflows 中构建人机协同自动化关卡
    • 将模拟操作替换为真实的自动修复
    • 使用 HTTP 连接器调用内部修复 API
    • 移交到 Jira、Slack 或 PagerDuty
  • 如何设计一个人机协同自动化关卡
    • 在事件响应工作流中,审批步骤应该放在哪里?
    • 一个好的审批请求应该告诉审查者什么
    • 如果没有人及时批准,会发生什么?
    • 审计记录必须捕获什么
  • 如何知道一个工作流已准备好无需审批运行
  • 结论
  • 从何处开始人机协同自动化
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档