凌晨两点十七分手机在床头柜上震了三下值班群里甩过来一条告警截图就一行红字核心交易链路 P99 延迟突破阈值。我爬起来开电脑先翻监控面板再去日志平台捞关键字接着查最近两小时的发布记录最后在配置中心对比了一下昨天改过的连接池参数——四十分钟过去问题定位到一个下游依赖的超时配置被顺手改小了跟本次发布没有半点关系。这种夜我在过去几年里熬了太多次真正花在想上的时间不到五分钟其余全耗在找上。这篇东西聊的就是怎么把这四十分钟里的三十分钟交给机器。Ongrid 是我最近在折腾的一套运维排障协同工具核心能力是把AI Agent拉进运维排障的链路里告警进来之后Agent 自动去拉指标、翻日志、查变更、比对历史相似事件把证据整理成一条有时间线的推理链最后给出几个待验证的假设。它不替你做决定也不碰生产环境的写操作干的是取证和初步推理这种又累又机械的活。适合谁看如果你手上管着几十上百个服务、经常值夜班、团队里新人和老手的排障效率差着好几倍那这套思路值得花一个下午试一试如果你只是想找个能自动重启服务的脚本那这篇不太对口关掉就行。1. 先想清楚AI Agent 到底该站在排障链路的哪个位置1.1 传统排障真正的成本不在修在找大多数人复盘故障时会说这次故障处理用了 40 分钟但把这个 40 分钟拆开看结构其实非常固定前 5 分钟确认告警是真的、判断影响面中间 25 到 30 分钟在四五个系统之间来回跳把散落的证据拼起来最后 5 到 10 分钟才是真正的判断和处置。也就是说八成以上的时间花在信息搬运上而不是决策上。这件事之所以一直没人解决不是因为技术上做不到而是因为排障需要的上下文天然是散的。指标在时序库日志在检索平台调用链在追踪系统变更记录在发布平台配置在配置中心历史相似故障在工单系统或者某个人的聊天记录里。每一处都有一套房号式的查询语法每一处都要单独登录。老手之所以快是因为他脑子里有一张该去哪儿找的地图新人慢不是笨是这张图还没建起来。Agent 的价值恰好落在这个位置。它不需要比人更懂业务它只需要不知疲倦地把这张地图走一遍而且每次都走全。人最容易被经验带偏——上次就是这个原因然后一头扎进去Agent 没有这种包袱它会按顺序把指标、日志、变更、依赖全部过一遍再下结论。这一点在真实排障里比想象中重要得多。1.2 Ongrid 的定位不替代人替代找证据的体力活我把 Ongrid 理解成一个事件驱动的 Agent 运行时。它的输入是一个告警或者一个人工发起的事件输出是一份结构化的排障报告中间过程是一连串工具调用记录。整个链路大概是这么走的告警从接入层进来先做聚合和去重然后触发一次会话会话启动时自动装配上下文告警详情、关联服务、最近变更、历史相似事件接着 Agent 在工具集里挑合适的工具去取证取证结果进入上下文循环若干轮最后输出结论。它有三个我比较认可的设计取向。第一是只读优先默认给 Agent 的工具全是查询类涉及变更、重启、扩缩容的动作类工具必须显式开启并且走人工确认这个默认值很重要因为很多事故是被自动化放大的。第二是证据可追溯Agent 说连接池耗尽报告里必须附上对应的指标曲线数据点和时间戳说不出来源就不算结论。第三是会话可回放整个排障过程像录像一样存下来事后能一帧一帧看 Agent 当时看到了什么、为什么那么判断这对调优提示词和培养新人都是宝贝。注意如果你所在的团队对AI 下结论这件事天然抵触别一上来就让它给结论。先把工具挂上去让 Agent 只输出证据清单 时间线不带任何判断。人用两周之后发现证据确实齐了再放开推理能力阻力会小很多。1.3 入门阶段的三组取舍我建议这么选第一组取舍自己拿框架搭 vs 用 Ongrid 这类带编排的平台。自己搭的好处是完全可控坏处是你要自己实现事件聚合、上下文装配、工具注册、会话持久化、权限审计这一整套光是工具调用失败了怎么重试就够写两天。入门阶段我建议先用平台把精力放在工具设计和提示词上这两块才是效果差异的真正来源。第二组取舍只读 vs 读写。我的答案很干脆入门阶段只读一条写操作都不要放。原因不是技术不成熟是排障场景下 Agent 的信息是不完整的它看到的永远只是系统的一个切片基于切片做写操作的风险收益比极差。等你在只读模式下跑了几十次对它的判断准确率有了体感再挑一两个低风险动作比如清理临时缓存目录、重置某个非核心连接做白名单试点。第三组取舍单 Agent vs 多 Agent 分工。多 Agent 听起来很美——一个查指标、一个看日志、一个查变更并行跑。实际入门阶段我不建议因为多 Agent 的上下文同步成本很高容易互相污染而且调试起来是灾难。单 Agent 配一套设计良好的工具在 90% 的排障场景里已经够用了。工具设计得好单 Agent 的串行调用也不会慢到哪里去因为真正的耗时在查询接口本身不在模型思考。2. Ongrid 的核心抽象四个概念撑起整个链路2.1 事件、上下文、工具、AgentOngrid 里的概念不多入门只需要记住四个剩下的都是这四者的组合。事件Incident是一次排障的容器。它可以由告警自动创建也可以人工手动发起。事件上挂着几个关键字段影响的服务、严重级别、起始时间、当前状态。事件是所有会话的父节点一个事件下可以有多次会话比如第一轮 Agent 没定位出来人补了几条线索再开一轮。上下文Context是喂给 Agent 的全部材料。它分三层静态层是服务元数据、依赖拓扑、值班信息这部分基本不变动态层是告警详情、当前指标快照、最近变更记录每次会话开始时自动拉取会话层是 Agent 自己通过工具调用获取的证据边跑边攒。理解这三层很重要因为后面调优的时候你会频繁在这三层之间做取舍——上下文塞太多会稀释注意力塞太少又不够判断。工具Tool是 Agent 的手。一个工具就是一个带描述的查询函数Agent 根据描述决定什么时候调它、传什么参数。工具的描述写得好不好直接决定 Agent 会不会用、用得对不对。这块后面单独展开讲。Agent是执行者。它的配置包括用哪个模型、系统提示词、可用工具集、最大轮次、超时时间这几个要素。Ongrid 支持配多个 Agent按服务或者按故障类型路由比如交易类事件走一个 Agent基础设施类事件走另一个各自的工具集和提示词可以做差异化。概念作用入门阶段的常见误区事件排障容器聚合告警与会话把每个告警都建成独立事件导致同一故障开几十个会话上下文喂给 Agent 的材料一次性全量灌入反而淹没了关键信号工具Agent 的取证手段工具粒度过粗一个工具返回上千行模型抓不住重点Agent执行单元只配一个万能 Agent不区分故障类型提示词写成大杂烩2.2 一次排障会话的完整生命周期我把一次会话拆成六个阶段理解这六个阶段后面出问题的时候你就知道该去哪个阶段找原因。阶段一事件聚合。告警进来先做指纹计算同一个服务、同一类指标、五分钟窗口内的告警合并成一个事件避免告警风暴把 Agent 冲垮。这个窗口参数很关键设小了合并不住设大了会把不相关的故障混进来我一般从 5 分钟起步观察一周再调。阶段二上下文装配。会话启动时系统自动去拉服务元数据、当前指标快照、最近两小时的变更记录、历史相似事件 Top 5。这一步是纯工程活不涉及模型但决定了 Agent 的起点高度。装配得好的话Agent 第一轮就能问出很准的问题。阶段三首轮推理。Agent 拿到上下文输出一个初步的排查计划——它打算先看什么、后看什么。这一步我建议在界面上显式展示出来让值班的人一眼看到 Agent 的思路对不对走偏了当场打断别等它跑完十轮才发现方向错了。阶段四工具调用循环。Agent 按计划调工具取证每次拿回结果后判断是否需要调整方向。这里有个轮次上限的设定我一般设 8 到 12 轮。设太少容易半途而废设太多会陷入再查一个的无限循环成本也压不住。阶段五结论生成。输出结构化报告时间线、关键证据、可能原因排序、建议的下一步验证动作。注意是建议验证动作不是建议修复动作这个措辞差异体现的是定位。阶段六人工接管与回写。值班的人看完报告要么直接按建议去验证要么补充线索让 Agent 继续。最终的根因和处置过程回写到事件上成为下一次检索的历史样本。这个回写环节千万别省它是系统越用越准的唯一来源。2.3 为什么我把上下文预算当成一等公民这是我在实际使用中体会最深的一点。刚开始用的时候我的想法很朴素证据越多越好全塞进去让模型自己挑。结果发现效果反而更差——模型被大量无关信息干扰抓着一个不重要的日志报错反复分析真正关键的指标拐点被淹了。后来我改成按预算分配上下文。假设主模型的上下文窗口是 128k token我的分配是这样的系统提示词留 3k工具描述 schema 留 4k输出预留 8k历史会话摘要留 10k剩下的 100k 左右才是证据区。证据区里再按重要性分配当前指标快照给 30k日志片段给 30k变更记录给 20k历史相似事件给 20k。这个分配不是拍脑袋是算出来的。举个例子一条应用日志平均 200 token如果无脑抓 500 条就是 100k直接把预算吃光了。所以我给日志工具的默认参数设成limit120并且强制要求按错误级别过滤把 500 条压到 120 条以内token 消耗降到 24k 左右同时保留了绝大部分有效信息。这种在工具层做预算控制的做法比在提示词里写请只关注重要日志有效一百倍。提示判断上下文是否超预算最直观的信号是 Agent 开始忘记前面已经查过的内容重复调用同一个工具。一旦出现这种循环先去查会话的 token 用量曲线八成是超了。3. 环境准备半天时间搭出一个能跑的最小版本3.1 资源规划和几个关键参数的估算Ongrid 的部署形态比较轻我按最小可用规格列一下。主服务跑一个容器2 核 4G 起步元数据库用 Postgres最小规格即可主要是存事件、会话、工具调用记录如果要做历史相似事件检索还需要一个向量库本地测试用轻量方案就行生产上建议用独立的向量存储服务。另外要预留一个对象存储桶用来存会话回放的原始快照。几个需要提前算的参数我给个经验公式每日会话数估算日均告警条数 ÷ 聚合系数。假设一天 600 条告警聚合系数取 8也就是平均 8 条告警合并成 1 个事件一天大概 75 次会话。这个数字决定了你的模型调用配额和数据库容量。单次会话成本估算轮次 × 单轮 token。按 8 轮、每轮平均输入 25k、输出 1.5k 算一次会话消耗约 200k 输入 token 和 12k 输出 token。再乘上每日会话数你就知道一个月大概什么量级了。这个数不算小所以我一直强调工具层做预算控制——工具返回的数据少一半成本直接砍一半。存储估算单次会话完整记录含工具返回原文大概 500KB 到 2MB按每天 75 次算一个月 1.5GB 到 5GB。这个量很小随便存别为了省这点空间把原始记录裁掉回放的时候你会感谢自己。3.2 安装和初始化安装过程没什么花样容器化部署一条命令拉起来。下面是我本地测试环境的启动配置改改就能用。# ongrid.yaml - 最小可用配置 server: host: 0.0.0.0 port: 8080 # 会话默认超时超过这个时间强制结束防止 Agent 挂死 session_timeout: 600s database: url: postgresql://ongrid:ongridlocalhost:5432/ongrid max_connections: 20 storage: # 会话回放快照的存放位置 snapshot_bucket: file:///data/ongrid/snapshots retention_days: 90 agent: # 默认 Agent 配置 default: model_profile: main max_rounds: 10 # 单次工具调用超时超过就判失败并让 Agent 决定是否重试 tool_timeout: 15s temperature: 0.2 # 按事件类型路由 routing: - match: { service_tag: trade } agent: trade_agent - match: { service_tag: infra } agent: infra_agent tools: # 工具执行器的注册位置后面详细写 registry_dir: ./tools policy: # 只读模式所有标记为 write 的工具一律拒绝 read_only: true # 需要人工确认的工具类型 require_approval: [write, destructive]拉起服务# 初始化目录结构和默认配置 ongrid init --workspace ./my-workspace # 启动服务前台运行方便看日志 ongrid up --config ./my-workspace/ongrid.yaml # 另开一个终端验证 ongrid status # 输出server ok | db ok | tools 0 registered初始状态下工具数是 0这是对的因为它还不知道你的系统长什么样。接下来就是往里填东西。3.3 接入第一个告警源Ongrid 的接入层支持几种常见方式Webhook 直推、从消息队列消费、主动轮询告警接口。入门阶段我强烈建议从Webhook 直推开始链路最短出问题最好排查。配置大概是这样integrations: - name: alert-webhook type: webhook path: /hooks/alert # 字段映射把外部告警的字段映射到 Ongrid 的事件字段 mapping: title: $.alert_name severity: $.level service: $.labels.service started_at: $.startsAt fingerprint: $.labels.alertname : $.labels.instance # 聚合窗口同指纹在此窗口内合并 dedup_window: 5m # 自动触发会话的严重级别 auto_session_levels: [P0, P1]配置完重启服务用 curl 打一条模拟告警进去验证curl -X POST http://localhost:8080/hooks/alert \ -H Content-Type: application/json \ -d { alert_name: HighLatency, level: P1, labels: { service: order-api, instance: order-api-7d9f, alertname: HighLatency }, startsAt: 2024-06-11T02:17:00Z }接口返回 200 并且带上事件 ID说明链路通了。这时候去界面上看事件已经创建但因为工具数是 0会话大概率会直接返回无可用工具无法取证。别慌这是预期行为下一步把工具挂上就好了。4. 工具设计和提示词效果差距的九成在这里4.1 工具粒度的黄金法则一个工具回答一个问题我见过最常见的失败模式是有人写了一个叫query_everything的工具参数是自然语言查询语句返回一大坨 JSON。这种工具看起来万能实际 Agent 根本用不好——它不知道该传什么参数也不知道返回结果里哪些是重点。我的经验法则是一个工具只回答一个具体的、可以用一句话描述的问题。比如过去 30 分钟某个服务的 P99 延迟是多少、某个服务最近两小时有没有发布、某个错误关键字在过去一小时出现了多少次。工具的名字要动词开头、语义明确描述里必须写清楚三件事这个工具能查到什么、参数怎么填、返回结果长什么样。我整理了一份入门阶段够用的工具清单按优先级排优先级工具名回答的问题关键参数必装query_metrics某个指标在时间窗内的走势service, metric, window, step必装search_logs某个关键字在某服务某时段的日志service, keyword, start, end, limit必装list_recent_changes最近有没有发布、配置变更service, hours必装get_dependencies这个服务依赖谁、被谁依赖service, depth强烈建议find_similar_incidents历史上有没有类似故障symptom_text, top_k强烈建议get_instance_health实例维度的健康状态service, instance可选query_traces调用链上哪个环节慢service, window, min_duration可选check_quota资源配额是否触顶service, resource_type工具数量不是越多越好。我测试过 6 个工具和 15 个工具的版本后者反而更差因为 Agent 在选择工具上就开始犹豫经常挑了个不合适的花两轮试错。入门阶段 6 到 8 个工具是比较舒服的区间。4.2 手写一个指标查询工具工具在 Ongrid 里有两种注册方式YAML 声明走 HTTP 调用或者用 Python 写函数直接注册。前者适合复用现有的查询服务后者适合做数据加工。我拿指标查询举例用 Python 写因为需要在返回前做降采样。# tools/query_metrics.py from ongrid.tools import tool import statistics tool( namequery_metrics, description( 查询指定服务在时间窗口内的指标走势。 返回降采样后的数据点序列包含时间戳和值以及最大值/最小值/平均值。 适用于判断是否存在突增、突降或持续漂移。 参数 metric 常见取值latency_p99(毫秒)、error_rate(百分比)、 qps(每秒请求数)、cpu_usage(百分比)、db_pool_used(百分比)。 ), schema{ service: {type: string, required: True, desc: 服务名如 order-api}, metric: {type: string, required: True, desc: 指标名}, window: {type: string, required: False, default: 30m, desc: 时间窗口如 15m / 1h / 6h}, step: {type: string, required: False, default: 1m, desc: 采样步长窗口长时建议放大到 5m} } ) def query_metrics(service: str, metric: str, window: str 30m, step: str 1m): raw _query_backend(service, metric, window, step) # 对接你的时序库 if not raw: return {found: False, hint: f{service} 没有 {metric} 数据检查指标名或服务名} values [p[value] for p in raw] # 关键控制返回体大小最多返回 40 个点 if len(raw) 40: factor len(raw) // 40 1 raw raw[::factor] return { found: True, service: service, metric: metric, window: window, points: [{t: p[ts], v: round(p[value], 2)} for p in raw], summary: { max: round(max(values), 2), min: round(min(values), 2), avg: round(statistics.mean(values), 2), p95: round(sorted(values)[int(len(values) * 0.95)], 2), trend: _calc_trend(values) # rising / falling / flat } }这段代码里有几个细节值得单独说。降采样必须做原始曲线可能几百上千个点直接返回就是烧钱加干扰压到 40 个点以内趋势完全看得出来。summary 字段要有模型看序列不如看极值和趋势来得准。空数据要带 hint否则 Agent 拿到空结果会反复重试同一个工具白烧好几轮。再来看一个日志工具重点在过滤tool( namesearch_logs, description( 在指定服务的日志中检索关键字。只返回错误和警告级别的日志 自动按时间聚合返回每类错误的出现次数和最多 5 条样例。 limit 控制原始返回条数上限默认 120不要设得太大。 ), schema{ service: {type: string, required: True}, keyword: {type: string, required: True, desc: 支持简单通配如 timeout*}, start: {type: string, required: True, desc: 起始时间ISO8601}, end: {type: string, required: True, desc: 结束时间ISO8601}, limit: {type: integer, required: False, default: 120} } ) def search_logs(service, keyword, start, end, limit120): limit min(limit, 200) # 硬上限防止模型自己把 limit 调大 rows _search_backend(service, keyword, start, end, limit) # 按错误模板聚类把 120 条压成 5 到 8 个模板 clusters _cluster_by_template(rows) return { total_hits: len(rows), clusters: [ { template: c[template], count: c[count], first_seen: c[first_seen], samples: c[samples][:3] # 每个模板最多 3 条原文 } for c in clusters[:8] ] }日志聚类这一步是我踩过坑之后加的。最早我直接把原始日志扔给模型120 条里可能 100 条是同一个模板在刷模型能识别出来但会浪费大量 token 在重复内容上。加了模板聚类之后返回体缩小到原来的十分之一而且某个模板在某个时间点突然开始刷这个信号变得非常显眼——这往往就是根因的直接线索。4.3 系统提示词的结构化写法提示词这块我的做法是固定五段式结构不玩花活角色与边界、可用信息、工作流程、输出格式、禁止事项。下面是我现在用的一版可以直接参考。# 角色与边界 你是某运维团队的排障助手负责在故障发生时收集证据、形成假设。 你不执行任何写操作不猜测没有证据支撑的结论。 # 可用信息 你会收到告警详情、服务元数据、依赖拓扑、最近变更记录、历史相似事件摘要。 你可以调用工具获取更多证据。工具返回为空时不要重复调用换个角度。 # 工作流程 1. 先用一句话概括告警现象和影响面。 2. 列出你的排查计划最多 4 步。 3. 按计划调用工具每拿到一个结果就判断是否调整方向。 4. 形成假设时必须指出支持它的证据和反驳它的证据。 5. 给不出确定结论时明确说明当前证据不足以定位并列出还需要什么信息。 # 输出格式 ## 现象概述一句话 ## 时间线按时间排序的关键事件每条注明来源工具 ## 关键证据3-6 条每条附数据点或日志原文片段 ## 可能原因按可能性排序每条标注置信度高/中/低 ## 建议验证动作只读操作最多 3 条 # 禁止事项 - 禁止在没有工具返回数据的情况下断言任何指标数值。 - 禁止把服务重启后恢复当作根因。 - 禁止输出超过 800 字信息密度优先。这份提示词里我认为最关键的是两处。一处是必须指出反驳证据这一条逼着 Agent 做双向验证实践下来明显减少了它一条道走到黑的情况。另一处是给不出结论就说给不出早期版本没写这条Agent 特别爱硬凑一个根因出来看起来很像那么回事实际经不起推敲值班的人信了反而更耽误事。实操心得提示词不要一次写完美先写个能跑的版本然后拿历史故障做回放测试。把过去三个月的真实故障事件导进去让 Agent 跑一遍对比它给的结论和当时的真实根因。跑 20 个案例你会精准地发现提示词该往哪个方向补。这个过程比看十篇教程有用。5. 实战演练一次模拟故障的完整排障过程5.1 场景设定与故障注入光看配置没感觉得跑一次。我搭了个模拟环境一个订单服务 order-api依赖库存服务 stock-api 和支付网关 pay-gateway前置一个网关层。故障注入的方式很土但有效——把 order-api 到 stock-api 的连接超时从 2000ms 改成 200ms然后压一波流量。这个故障的特点是告警会指向 order-api 的延迟升高但根因在它下游的调用配置是典型的表象在上游、根因在下游。这种场景最适合验证 Agent 会不会被表象带偏。注入之后大概 30 秒告警进来了[P1] HighLatency - order-api P99 延迟 1860ms超过阈值 800ms5.2 会话记录逐段复盘第一轮Agent 拿到上下文后输出现象概述order-api P99 延迟从 210ms 升至 1860ms持续约 4 分钟影响下单主链路。 排查计划 1. 确认延迟上升的时间点和幅度是否与 QPS 变化同步 2. 检查 order-api 最近两小时是否有发布或配置变更 3. 查看 order-api 的错误日志是否有超时类报错 4. 检查下游依赖 stock-api 和 pay-gateway 的延迟表现这个计划我挑不出毛病四个方向覆盖得挺全而且第 1 步就考虑了是不是流量涨了这个最常见的误报原因。这就是上下文装配到位的价值——它知道 order-api 有哪些下游依赖。第二轮Agent 调了query_metrics调用query_metrics(serviceorder-api, metricqps, window30m) 结果avg 1420, trend flat 调用query_metrics(serviceorder-api, metriclatency_p99, window30m) 结果points 显示 02:13 之前稳定在 210ms 左右 02:13 起快速爬升02:17 达到 1860ms 并维持。 summary: max 1860, min 205, trend risingAgent 的判断QPS 平稳排除流量突增。延迟在 02:13 出现拐点需要找这个时间点发生了什么。这一步很关键。如果 QPS 是涨的整个排查方向就完全不同了。Agent 先排除了最可能的误报原因这个顺序是对的。第三轮Agent 并行调了变更查询和日志检索调用list_recent_changes(serviceorder-api, hours2) 结果无发布记录。02:08 有一次配置变更变更项 downstream.stock-api.connect_timeout2000ms - 200ms 调用search_logs(serviceorder-api, keywordtimeout*, start02:00, end02:25) 结果total_hits 342聚成 2 个模板 模板 Acall stock-api timeout after 200ms318 次02:14 起 模板 Border create failed, upstream timeout24 次02:15 起到这儿基本上就水落石出了。变更记录的时间点 02:08延迟拐点 02:13日志报错起点 02:14三个时间点串成一条链而且日志里明明白白写着timeout after 200ms跟变更内容完全对得上。第四轮Agent 做了一次反向验证这是我比较惊喜的地方调用query_metrics(servicestock-api, metriclatency_p99, window30m) 结果points 稳定在 45ms 左右trend flat 调用query_metrics(serviceorder-api, metricdb_pool_used, window30m) 结果avg 32%无异常 判断stock-api 自身延迟正常说明问题不在下游服务性能 而在 order-api 对它的调用配置。db 连接池正常排除数据库侧原因。它主动去查了 stock-api 自己的延迟确认对方没问题从而把矛头精准指向调用配置而不是下游服务故障。这一步如果省略结论就会模糊成stock-api 有问题方向偏了。最终输出## 现象概述 order-api P99 延迟 02:13 起从 210ms 升至 1860ms持续至今影响下单链路。 ## 时间线 02:08 配置变更stock-api 连接超时 2000ms - 200ms来源list_recent_changes 02:13 order-api P99 延迟出现拐点来源query_metrics 02:14 日志开始出现 call stock-api timeout after 200ms来源search_logs 02:15 下单失败日志出现来源search_logs ## 关键证据 1. 延迟拐点与配置变更时间相差 5 分钟符合配置生效延迟 2. 日志明确记录超时阈值为 200ms与变更后的值一致出现 318 次 3. stock-api 自身 P99 稳定在 45ms排除下游性能问题 4. QPS 平稳排除流量突增 ## 可能原因 1. 连接超时配置从 2000ms 调整为 200ms低于 stock-api 的 P99 响应时间 波动上限导致大量请求超时。置信度高 ## 建议验证动作 1. 查看 02:08 那次配置变更的操作记录和变更单 2. 对比 stock-api 近 24 小时的 P99 分布确认 200ms 是否覆盖不足从告警进来到这份报告出来全程 47 秒8 次工具调用。人工做同样的事熟练工大概 20 分钟不熟练的可能要 40 分钟以上。而且这份报告的证据链是完整的每一条都能追溯到具体工具和数据点。5.3 结果验收怎么判断 Agent 干得好不好跑完不算完得有验收标准否则你不知道它是真准还是碰巧。我用三个指标定位命中率Agent 给出的 top1 原因和最终确认的根因是否一致。入门阶段能到 50% 到 60% 就算合格别指望一上来就 90%。重点是看那些没命中的案例是工具缺失、上下文不足还是提示词问题。证据完整度报告里的关键证据是否覆盖了时间线、指标、日志、变更四个维度。这个指标比命中率更重要因为即使结论错了只要证据齐人接手也能很快纠正反过来结论蒙对了但证据是空的这种对的答案毫无价值。人工节省时间从告警到人工形成判断的时间差。这个要跟改造前的基线比我的体感是熟手节省 30% 到 40%新手节省 60% 以上。新手收益更大因为 Agent 相当于把老手的排查路径固化下来了。我建议每次演练之后做个简单的记录表攒够 20 条再回头做统计分析。单看一两次结果没有意义样本太小了。6. 常见问题与排查技巧实录6.1 高频问题速查表下面这些是我在实际使用中真碰到的按出现频率排序现象大概率原因处理办法Agent 反复调用同一个工具上下文超预算前面的结果被挤掉了查 token 用量压缩工具返回体减少工具数量结论里出现没有来源的数字提示词缺少禁止无据断言约束补充禁止事项并在输出格式里强制要求标注来源工具调用全部失败工具注册的服务地址不通或鉴权配置错误单独用 curl 打一次工具的底层接口验证Agent 只查一个方向就下结论提示词里的工作流程不够强制把列出排查计划改成必须输出的前置步骤同一个故障开了十几个会话告警指纹设计不合理聚合窗口太小调整 fingerprint 字段组合窗口从 5m 起调报告很长但没信息输出格式没有字数限制加不超过 800 字信息密度优先会话超时被强制结束工具响应慢或者轮次设太多查工具 P99 耗时超 5s 的工具要加缓存新人看不懂报告术语没有解释时间线不完整提示词里要求假设读者不了解该系统6.2 三个我踩过的坑值得单独说第一个坑让 Agent 自己决定查多长时间窗口。早期版本我把时间窗口做成完全开放参数结果 Agent 经常查 24 小时的数据返回几百个点token 炸了不说短时突变的信号还被长时间基线稀释了。后来我改成默认 30 分钟最长不超过 6 小时而且要求在描述里写明故障排查场景优先用短窗口。改完之后效果立竿见影。第二个坑工具描述写得太技术化。我一开始按 API 文档的风格写工具描述参数类型、取值范围写得清清楚楚但没写什么时候该用。结果 Agent 有一半时间在纠结用哪个工具。后来我在每个工具描述开头加一句场景说明比如当怀疑是下游依赖导致上游延迟时使用使用准确率明显提升。工具描述是给模型看的不是给同事看的这句话我建议贴在显示器上。第三个坑没做工具返回的空值处理。有个工具在查不到数据时返回空数组Agent 拿到空数组不知道是确实没有还是查询失败了就会反复重试一轮会话能重试五六次。后来所有工具统一规范查不到数据必须返回{found: false, hint: 可能的原因}明确告诉模型别查了换个思路。这个小改动省下的成本相当可观。注意还有一类坑不在技术上在流程上。如果 Agent 的报告直接推到值班群里很容易造成AI 说是 XX 原因的认知锚定人反而不去独立验证了。我的做法是报告先只对值班本人可见他确认之后再决定要不要转发。这个隔离很重要。6.3 成本、效果和推广节奏成本这块我给个粗略的量级参考。按前面算的每日 75 次会话、单次 200k 输入 token 计一天大概 1500 万输入 token。这个数字听起来吓人但跟一个 P1 故障动辄几十人小时的投入比其实不算什么。真正要控制的是无效会话——那些因为告警抖动触发、Agent 跑完发现啥事没有的会话。我的控制手段有三个只对 P0/P1 自动触发会话P2 以下人工点一下才跑聚合窗口从 5 分钟调到 8 分钟砍掉一批抖动告警给 Agent 加了一个前置判断步骤上下文里如果显示该指标在过去 24 小时有 3 次以上同幅度波动且自行恢复直接输出疑似抖动建议观察就结束不进入完整排查。这三招下去无效会话少了大概六成。推广节奏上我的建议是先在一条非核心链路上跑两周让团队里两三个人用起来收集真实反馈改工具和提示词。等他们主动说这个挺好用的时候再往核心链路推。反过来先推核心链路一旦出一次误判整个事情就很难再推动下去了人的信任是很脆弱的。最后分享一个小技巧。我在每个 Agent 的提示词末尾加了一句话如果你发现当前工具集无法获取某个关键信息请在结论中明确写出缺少 XX 能力。 这句话的本意是让 Agent 老实交代结果意外成了工具迭代的需求来源——跑了三周它列出来的缺失能力清单比我拍脑袋想的工具规划准得多。现在我每周看一次这个清单挑出现频率最高的补上工具集的演进方向基本不用自己操心。