资讯详情

资讯详情

你的 AI agent 需要一个不在场证明:Elastic 中 Agent Builder 的可观测性和审计追踪

作者来自 Elastic Jeffrey RengifoElastic 9.5 会将每次 Agent Builder 运行记录为你自己的集群中的 OpenTelemetry spans因此工具调用和 token 数量都可以通过 ES|QL 进行查询。只需一个工作流步骤即可添加审批记录并将其写入一个管道无法重写的数据流中。向一个 Elastic Agent Builder agent 提出一个问题产生了 24 个 spans涉及两个模型的 10 次模型调用以及大约 160,000 个输入 token。Elastic 9.5 无需 collector 或 scraper 即可记录 AI agent 可观测性数据。默认情况下每次运行都会作为 OpenTelemetry traces 写入你自己的集群写入traces-agent_builder.otel-space-id细化到 agent 生成的每个 ES|QL 查询以及它查询的每个索引。这些 traces 展示了 agent 如何得出建议以及产生了多少成本但不会记录是谁批准了它。下面介绍如何读取这些 traces、确定一次运行涉及的三个身份以及如何将审批决定追加到一个管道无法重写的数据流中。前提条件Elastic Stack 9.5 或 Serverless具有管理 Kibana 高级设置的权限这是安装 traces 仪表板所必需的。Elastic Observability 在哪里记录 AI agent 操作的各个部分每次审查 agent 化运营管道时都会出现四个问题而每个问题都由不同的记录来回答。问题答案所在位置创建者agent 是如何得出建议的traces-agent_builder.otel-*spansAgent Builder自动生成它调用了哪些工具以及这些工具是否失败同一数据流中的execute_toolspansAgent Builder自动生成此次运行使用了谁的权限工作流执行记录和 Elasticsearch 安全审计日志Kibana部分记录人类做出了什么决定以及操作是否执行由你自己写入的索引你前两个功能在 9.5 中是新增的只需启用一个开关无需额外费用。最后一个没有自动记录来源因此也是大多数管道所缺失的部分。场景结账流程中的过期定价缓存三个checkout-serviceworker 为生产流量提供服务。其中一个即checkout-worker-1已经升级到版本2026.07.26.1现在每次获取报价都会返回 HTTP 500因为它的定价缓存停止刷新。其他两个仍运行2026.07.25.3版本并正常提供服务。这一设置背后的 SRE 控制平面模式将遥测数据、基于这些数据进行推理的 Agent Builder agent以及执行已知操作的 Elastic Workflows 连接起来并在第一个会修改生产环境的步骤之前设置人工审批闸门。遥测数据通过文档中介绍的 OpenTelemetry 路径传入因此 agent 可以读取标准 OTel 字段。Elasticsearch 9.5 提供原生 OTLP 端点使 OTel SDK 可以直接将数据写入集群中间无需 collectorfrom opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter from opentelemetry.sdk._logs import LoggerProvider from opentelemetry.sdk._logs.export import BatchLogRecordProcessor from opentelemetry.sdk.resources import Resource provider LoggerProvider( resourceResource.create({ service.name: checkout-service, deployment.environment: production, }) ) provider.add_log_record_processor( BatchLogRecordProcessor( OTLPLogExporter( endpointf{ES_URL}/_otlp/v1/logs, headers{Authorization: fApiKey {API_KEY}}, ) ) )该端点通过 protobuf 使用 OTLP并且会对application/json返回 HTTP 406因此应该通过 SDK 或 collector 发送而不是手动构建 JSON。这会向logs-generic.otel-default写入 450 条记录三个 worker 中共有 360 条正常事件以及来自故障 worker 的 90 条PricingCacheStaleError事件。agent 不会获得这些上下文中的任何信息而必须通过查询自行找到这些信息。在 Elastic 中读取 AI agent 可观测性 tracesAgent Builder 记录的与一次运行有关的所有信息都存储在两个数据流中并且全部可以通过 ES|QL 进行查询。如何在 GenAI 设置中启用 AI agent tracing打开Stack Management然后打开GenAI Settings找到Agent Builder Traces部分。在 9.5 中Collect conversation traces默认处于启用状态。该面板中有两个细节比开关本身更重要。traces 会写入traces-agent_builder.otel-space-id每个 Kibana space 对应一个数据流同时还有一个配套的logs-agent_builder.otel-space-id用于记录 agent 侧的事件。这些都是使用标准 OTel 索引模板的普通数据流而不是隐藏的系统索引因此 Discover、Lens 和 ES|QL 都可以直接查询它们。提示信息明确说明了访问模型任何能够读取该索引的人都可以读取其中的所有 trace。Trace 访问权限不会按用户进行限制因此在向包含敏感对话的 space 授予访问权限之前应通过角色限制索引模式。读取一次 agent 运行的 LLM trace 瀑布图通过 converse API 提出一个问题让内置的 Elastic AI Agent 调查logs-generic.otel-default找出哪些 pod 和版本返回 HTTP 500并提出一个范围受限的操作。它正确地给出了答案指出checkout-worker-1的版本为2026.07.26.1错误率为 43%而仍运行2026.07.25.3的另外两个 worker 没有错误。在任意 agent 响应下方选择 trace 图标即可打开瀑布图。通过 converse API 提出的一个问题产生了 24 个 spans耗时 43.7 秒。其结构是一个invoke_agent根 span、一个generate_title分支然后交替出现chat和execute_toolspansagent 在查询、读取结果以及选择下一次查询的过程中依次产生这些 spans。三个 span 系列包含了你需要进行聚合的所有信息。Span 名称前缀表示内容关键属性invoke_agent一轮对话CHAIN或一次 agent 执行AGENTelastic.inference.span.kind、gen_ai.agent.idchat一次模型调用gen_ai.request.model、gen_ai.provider.name、gen_ai.usage.input_tokens、gen_ai.usage.output_tokensexecute_tool一次工具调用gen_ai.tool.name、gen_ai.tool.call.id、status.code这次运行的 token 分解如下模型调用次数输入 token输出 tokenanthropic-claude-4.6-sonnet5113,3152,039anthropic-claude-4.5-haiku547,211651一半的模型调用使用了较小的模型。这就是快速模型路由它会将低工作量的步骤发送到成本更低的模型而这种模型分配情况只有在 trace 中才能看到。这次单独的 agent 调查总共消耗了大约 160,000 个输入 token。每一轮都会重新处理累积的上下文因此成本会随着对话长度增长而不是随着问题本身的长度增长。如何使用 ES|QL 查询 agent 的工具调用工具调用是最值得关注的 agent 行为部分因为 agent 正是在这里接触你的数据。每次调用都会产生一个execute_toolspan而文档中的查询可以直接对这些调用进行聚合FROM traces-agent_builder.otel-* | WHERE span.name LIKE execute_tool * | STATS calls COUNT(*), errors COUNT(*) WHERE status.code Error, avg_ms ROUND(AVG(duration) / 1000000.0, 1) BY tool attributes.gen_ai.tool.name | SORT calls DESC在这次运行中agent 主要使用了platform.core.execute_esql而其背后的platform.core.generate_esql和load_skill各调用了两次。文档根部的duration单位是纳秒这也是查询需要除以一百万来转换为毫秒的原因。同时也要检查配套的 logs 数据流。在同一会话的另一次运行中agent 尝试调用一个不在其可用工具集合中的工具这次尝试被记录为logs-agent_builder.otel-default中的一个异常事件并通过trace_id与该 trace 关联{ trace_id: 3f8b9722dbd371ac4b7ad75e4bed13b6, event_name: exception, attributes: { exception.type: toolNotFoundError, exception.message: Tool \platform.streams.query_documents\ called but was not available } }一次被阻止的工具调用尝试与审计相关并且不会出现在 trace 瀑布图中。只查询 traces 数据流会遗漏这类事件。对于聚合视图有一个托管仪表板可以从同一个设置面板中按每个 space 进行安装。在覆盖这些运行的 15 分钟时间窗口内它报告了 903,914 个输入 token、11,734 个输出 token 和 44 次 LLM 请求其中有 35 个工具 spans成功率为 100%平均耗时为 0.42 秒。该仪表板由系统管理且为只读因此如果要修改某个面板需要复制一份这样 Elastic 仍然可以继续改进原始仪表板。OpenTelemetry LLM traces 默认不会捕获哪些内容默认情况下trace 记录的是结构和成本而不是内容。Advanced privacy settings下有六个开关用于控制提示词、响应、工具调用详情、系统提示词、真实的工具和 agent 名称以及真实的对话和工作流 ID这六个开关默认全部关闭。默认情况下trace 记录的是结构和成本而不是内容。在瀑布图中选择任意 span详情面板会直接显示“此 span 没有可用的输入/输出数据。”标识符会经过哈希处理而不是直接丢弃。包含被阻止工具调用的那次运行通过 API 返回了 conversationbe30fb53-d351-4fa1-b5e1-a569816f85d9但其 spans 携带的是gen_ai.conversation.id: b1141340d0851a46。这样你可以将属于同一个 conversation 的所有 spans 分组并在不同 conversation 之间进行比较同时不会暴露能够追溯到用户会话的标识符。因此除非启用真实 ID否则你无法通过 conversation ID 将 traces 与 conversations 进行关联而通常也没有这个必要。converse API 会直接提供关联键{ conversation_id: be30fb53-d351-4fa1-b5e1-a569816f85d9, trace_id: 3f8b9722dbd371ac4b7ad75e4bed13b6, model_usage: { llm_calls: 22, input_tokens: 518251, output_tokens: 6423, model: anthropic-claude-4.6-sonnet } }将这个trace_id存储在你自己的决策记录中这样无需削弱默认的隐私保护设置即可完成关联。只有在确实需要将具体响应精确归因到决策时才启用真实 ID并在进行相同更改时限制 trace 索引的访问权限。在 trace 之外审计 AI agent 操作traces 只记录 agent 做了什么因此显示谁授权了该操作的记录必须来自其他地方。AI agent 操作使用谁的权限运行agent 化管道涉及三种身份每种身份都有自己的边界。身份运行时使用的权限由什么决定如何限制范围Agent Builder 工具使用当前聊天用户的权限当前用户因此两个人针对同一个问题可能获得不同的数据通过 Agent Builder 权限中所述的角色进行限制工作流步骤所有elasticsearch.*和kibana.*步骤共享一个存储的 API key触发方式手动运行使用启动运行的人员的身份计划运行使用上次保存工作流的人员的身份工作流授权Trace 读取者索引级访问权限要么全部允许要么全部拒绝对traces-agent_builder.otel-*的角色授权通过 trace 索引模式设置角色边界在任何审查中都需要考虑存储的 key 所带来的一个影响。停用用户或更改其角色不会刷新这个 key工作流会继续使用它获取的权限运行直到有人再次保存该工作流或者将Enabled关闭后再重新打开。撤销某位工程师的访问权限本身并不会停止仍以该工程师身份运行的工作流。将调查角色的权限范围限制为只读POST /_security/role/agent-builder-observability-investigator { cluster: [monitor_inference], indices: [ { names: [logs-*, metrics-*, traces-*], privileges: [read, view_index_metadata] } ] }读取 agent 自身的 traces 是单独的授权需要对traces-agent_builder.otel-*具有read和view_index_metadata权限。将这两个角色分开因为负责调查故障事件的人员和负责审计 agent 的人员并不总是同一批人。在 Elasticsearch 中记录谁批准了 agent 操作运行工作流它会在审批闸门处停止此时审查人员看到的是渲染到请求中的 agent 结构化输出而不是一个简单的确认提示。执行记录非常详细。它会记录resumedAt、resumedBy、完整的resumeInput负载、每个步骤的 token 使用情况以及指向自身的深层链接。该执行历史是一个运营视图而不是审计存储。底层的.workflows-events数据流专用于系统操作并且会直接拒绝用户查询因此你无法使用 ES|QL 跨越一个季度的决策进行查询而且执行历史受保留策略控制而不是受你的合规策略控制。将决策写入一个由你控制的索引- name: review type: waitForInput with: message: | ## Approve the proposed checkout remediation? The evidence query matched {{ steps.collect_evidence.output.hits.total.value }} error events in the last hour. Agent classification: {{ steps.investigate.output.structured_output.incident_class }} Affected pod: {{ steps.investigate.output.structured_output.affected_pod }} Proposed action: {{ steps.investigate.output.structured_output.recommended_action }} schema: type: object properties: decision: type: string enum: [approve, decline] reason: type: string enum: [supported-by-evidence, insufficient-evidence, wrong-target, unsafe-action] notes: type: string required: [decision, reason] - name: record_decision type: elasticsearch.index with: index: agent-action-audit document: timestamp: {{ now | date: %Y-%m-%dT%H:%M:%S.%LZ }} event.action: agent_recommendation_reviewed incident.id: {{ consts.incident_id }} agent.conversation_id: {{ steps.investigate.output.conversation_id }} agent.incident_class: {{ steps.investigate.output.structured_output.incident_class }} agent.affected_pod: {{ steps.investigate.output.structured_output.affected_pod }} agent.recommended_action: {{ steps.investigate.output.structured_output.recommended_action }} agent.evidence_count: {{ steps.collect_evidence.output.hits.total.value }} review.decision: {{ steps.review.output.response.decision }} review.reason: {{ steps.review.output.response.reason }} review.notes: {{ steps.review.output.response.notes }} review.responded_by: {{ steps.review.output.respondedBy }} workflow.execution_id: {{ execution.id }} workflow.executed_by: {{ execution.executedBy }} workflow.execution_url: {{ execution.url }}上面的工作流代码片段中有两个细节与参考页面不同。审查人员负载多嵌套了一层。文档描述的是steps.name.output.field但正在运行的构建版本会将提交的值放在response下同时还有一个respondedBy字段{ response: { decision: approve, reason: supported-by-evidence }, respondedBy: 1506416774 }execution.executedBy记录谁启动了运行而respondedBy记录谁批准了操作。在人工参与的管道中这两者通常是不同的人。第二个细节是时间戳。{{ now }}会渲染为类似Sun Jul 26 2026 07:37:11 GMT0000 (Coordinated Universal Time)的 JavaScript 日期字符串而 Elasticsearch 会拒绝这种格式并返回failed to parse date fieldexecution.startedAt也存在同样的问题。Liquid 的date筛选器可以解决这个问题。工作流编辑器还会在首次运行之前将steps.review.output.*标记为无效变量因为只有在有人作出响应后审查人员负载的结构才会确定。该警告会在步骤获得实际输出后消失并且模板会在运行时正确解析。创建仅允许追加的数据流如果审计追踪可以被 agent 自己的管道重写那么它就不能算是真正的审计追踪。Elasticsearch 提供了两个相互独立的控制机制并且可以组合使用。首先将数据写入数据流而不是索引因为数据流只接受追加操作不接受其他操作PUT _index_template/agent-action-audit { index_patterns: [agent-action-audit], data_stream: {}, priority: 500, template: { mappings: { properties: { timestamp: { type: date }, event.action: { type: keyword }, incident.id: { type: keyword }, agent.conversation_id: { type: keyword }, agent.evidence_count: { type: long }, agent.recommended_action: { type: keyword }, review.decision: { type: keyword }, review.reason: { type: keyword }, review.responded_by: { type: keyword }, workflow.execution_id: { type: keyword } } } } }其次只授予写入者create_doc权限不授予其他任何权限这样它可以添加记录但无法使用按查询操作等绕过限制的方式PUT _security/role/agent-action-audit-writer { indices: [ { names: [agent-action-audit], privileges: [create_doc, auto_configure] } ] }在正在运行的集群上进行测试后这两个控制机制的行为符合审计存储的要求以审计写入者身份执行的操作结果追加一条决策记录201 Created按 ID 覆盖一条记录400数据流中只允许使用op_type: create使用_update_by_query修改一条决策403操作未获授权使用_delete_by_query删除历史记录403操作未获授权使用_search读取审计记录403操作未获授权最后一行的只写行为是有意设计的。写入决策的工作流没有理由读取这些决策因此审计人员使用单独的读取角色而写入者保持只写权限。这两个控制机制的失败方式不同这一点很重要。400来自数据流本身并且适用于所有人包括超级用户。403则来自角色权限而超级用户仍然可以执行这些操作。因此要实现防篡改的保留策略就意味着需要将记录发送到 agent 操作人员无法管理的集群之外。对于集群级别的活动启用 Elasticsearch 和 Kibana 安全审计日志并 将日志转发到监控部署。在 9.5 中xpack.security.audit.enabled成为了动态集群设置因此 Elasticsearch 不再需要重启即可启用它不过在编排部署中仍然需要将日志发送到某个可读取的位置。使用 ES|QL 查询决策追踪工作流运行两次一次批准一次拒绝会产生两行记录你可以将它们与 Elastic 中的其他数据一起进行查询。FROM agent-action-audit | KEEP timestamp, agent.incident_class, agent.affected_pod, agent.recommended_action, agent.evidence_count, review.decision, review.reason, review.responded_by, workflow.execution_id | SORT timestamp DESC两次运行都看到了相同的 90 个错误事件并且都针对checkout-worker-1提议执行restart-checkout-worker。第一次审查以supported-by-evidence为理由批准了该操作第二次则以wrong-target为理由拒绝理由是重启 pod 只是掩盖定价数据源问题而不是解决问题。由于两次决策都是结构化字段因此审查意见之间的分歧也是可以查询的。你可以统计每个故障事件类别的拒绝次数并按照原因进行分组insufficient-evidence会将你引导回调查路径而unsafe-action则会将你引导到工作流及其权限边界。需要针对这些 AI agent 可观测性限制进行设计有四种行为值得在设计时加以考虑而且在编写工作流之前处理这些问题的成本更低。Trace 访问权限是索引级别的而不是按用户划分的。包含敏感对话的 space 需要在traces-agent_builder.otel-*上设置角色边界而不是通过 UI 设置。托管仪表板不会在新 space 中自动安装。将其添加到 space 配置清单中。工作流执行具有自己的 APMtraceId。它与 Agent Builder 的ai.agent步骤生成的 spans 所使用的 trace 并不是同一个 trace因此应该通过 conversation ID 或 agent 返回的trace_id进行关联而不是期望一个 trace 覆盖两者。waitForInput的输出结构与参考页面不同。提交的值会放在response下同时还有respondedBy如上所述。这些问题都不会阻碍这种模式。从哪里开始使用 AI agent 可观测性开启 trace 收集在 agent 运行所在的 space 中安装仪表板然后打开一次真实 conversation 的瀑布图。它会展示工具调用顺序、模型分配以及延迟分布而这些信息无法从回答文本中获得。然后选择一个你已经信任其运行手册的单一故障事件类别并在其审批闸门之后添加一个elasticsearch.index步骤。一个仅允许追加的决策记录只需要一个工作流步骤却可以回答审查所需的三个问题谁批准了这个操作、依据什么证据批准以及之后发生了什么。有关详细信息请参阅收集 Agent Builder traces、traces 概览仪表板、Agent Builder 权限、工作流授权以及 waitForInput 参考文档。常见问题Agent Builder trace 收集默认开启吗是的在 9.5 和 Serverless 中默认开启。它会写入traces-agent_builder.otel-space-id无需配置 collector。Traces 包含提示词和模型响应吗不包含。六个隐私开关分别控制提示词、响应、工具调用详情、系统提示词、真实的工具和 agent 名称以及真实的 conversation 和工作流 ID并且这六个开关默认全部关闭。我可以限制谁能够读取 agent traces 吗只能在索引级别进行限制通过角色控制对traces-agent_builder.otel-*的访问。访问权限不会按用户或 conversation 进行限制。Traces 仪表板会自动安装吗不会。需要从 GenAI Settings 中的 Agent Builder Traces 部分为每个 Kibana space 安装一次。为什么要单独写入决策索引而不是使用工作流执行历史.workflows-events专用于系统操作并且会拒绝用户查询此外执行历史遵循自身的保留策略而不是你的合规策略。原文Your AI agent needs an alibi: Observability audit trails for Agent Builder in Elastic | Elastic Observability Labs
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →