:多智能體協(xié)同的自動告警處置系統(tǒng)搭建)
做運維的人應該都有過這種沖動半夜告警響了爬起來看一眼發(fā)現(xiàn)只是某個服務抖動了一下自己恢復了或者收到一堆日志排查半天定位到一個早就該有人處理的配置項。那時候就在想這些事能不能讓機器自己干了說實話傳統(tǒng)的腳本和自動化能做不少事但遇到“需要判斷、需要協(xié)同、需要臨時改策略”的場景腳本就僵住了。最近我在折騰 AI 運維 Agent試了一套多智能體協(xié)同的方案讓幾個 Agent 自己分工、自己干活、自己匯報效果比預期好不少。這篇就聊聊這個系統(tǒng)是怎么搭的、里面的 Agent 怎么協(xié)作、以及實測下來的真實表現(xiàn)踩過的坑也一并寫出來。這適合已經在用自動化腳本、但想往智能化走一步的運維同學也適合對 Agent 概念感興趣、想看看它在運維場景里到底能干啥的人。不需要你有大模型訓練基礎但得對 Linux、API、工作流編排有點概念。1. AI 運維 Agent 的“自主做事”靠的不是大模型本身先說一個容易誤會的點AI 運維 Agent 不是把大模型接進來就完事了。大模型本身只能理解語言、生成文本它不會執(zhí)行命令、拉取指標、改配置。真正讓它“自己做事”的是一套把它跟運維系統(tǒng)連起來的執(zhí)行鏈路。1.1 從“聊天”到“干活”隔著一個完整的工具鏈我見過不少人說“接入大模型之后能讓它幫我查日志嗎”。實際上大模型返回的只是一段文本甚至可能是一段“我建議你執(zhí)行 xxx 命令”的文字。要讓它真的去查日志、去重啟服務需要做三件事第一給大模型提供工具。每個運維動作都得封裝成一個可調用的函數或接口比如“查 CPU 使用率”“拉取最近 1 小時錯誤日志”“重啟某個 Pod”“回滾某個版本”。這一步很像把所有常用運維操作做成 REST APIAgent 通過調用函數來執(zhí)行動作。第二給大模型觀察結果的能力。一次調用可能不夠Agent 得能連續(xù)多輪“觀察-思考-行動”。比如先查指標指標異常再查日志日志里看到某個錯誤碼再決定下一步動作。這個循環(huán)是 Agent 能做決策的基礎。第三設置邊界和審批機制。自主不等于不受控尤其是生產環(huán)境。初期部署時每臺機器都配了白名單命令和操作風控超過閾值的操作會轉人工確認。所以“自己做事”的本質是大模型負責推理、規(guī)劃和拆解任務工具層負責執(zhí)行編排層負責控制節(jié)奏和風險。三者缺一不可。1.2 我的第一個最小閉環(huán) Demo我最開始跑通的版本很簡單一臺測試服務器部署了一個大模型接口通過 Python 寫了一個執(zhí)行器腳本封裝了三個函數get_cpu()、get_disk()、restart_service()。然后給模型一個目標“檢查 CPU 持續(xù) 5 分鐘高于 80% 時重啟應用服務”。這次跑通過程讓我理解了關鍵的機制Agent 不是一次性生成答案而是進入了循環(huán)模式。第一輪調用模型模型返回“先執(zhí)行 get_cpu()”執(zhí)行器去查系統(tǒng)指標把結果塞回對話上下文模型看到 CPU 確實高繼續(xù)執(zhí)行restart_service()然后再檢查一次 CPU 是否回落。整個過程沒有人工參與。心跳定時器驅動了這個循環(huán)。每檢查一次算一個 step通常任務要 3~6 個 step 才能完成。為了不把上下文撐爆我給對話歷史做了截斷只保留最近的 10 輪往返。這也是后面很多問題的根源后面會細說。2. 多智能體協(xié)同不是“一堆模型開會”而是“流水線 分工”單 Agent 能做的事很有限。真正想覆蓋“監(jiān)控發(fā)現(xiàn)、根因定位、止損恢復、通知響應”這條完整鏈路得讓不同 Agent 各管一段互相配合。2.1 每個 Agent 的角色畫像和能力邊界我最終部署的這套環(huán)境里定義了四個 Agent每個都有自己的職責和工具集Monitor Agent 專職盯告警和指標。它定時輪詢監(jiān)控系統(tǒng)一旦觸發(fā)閾值就生成一條結構化事件。它不負責修復只負責“發(fā)現(xiàn)問題并發(fā)出信息”。Diagnose Agent 專職分析。它拿到 Monitor 的事件后去拉日志、查依賴關系、看最近變更記錄輸出一份帶置信度的根因判斷。它不直接操作只給結論。Executor Agent 專職執(zhí)行動作。它接收 Diagnose 的判斷結果匹配預案庫里的操作步驟執(zhí)行重啟、回滾、擴縮容等操作。它需要最嚴格的風控。Notify Agent 專職通報。所有階段性結論、執(zhí)行結果、人工確認請求都由它發(fā)出發(fā)到企業(yè)微信或釘釘機器人。它不做決策只是保持信息透明。四者協(xié)作按照標準的三個階段推進——發(fā)現(xiàn)、診斷、處置——構成完整閉環(huán)。2.2 關鍵在于Agent 之間如何交換信息多 Agent 架構里最常見的坑是各說各話。每個 Agent 都接了大模型如果不做結構化管理它們之間傳的就是一堆自然語言段落結果后面的 Agent 根本沒法穩(wěn)定地把關鍵信息提取出來。我用的辦法是所有 Agent 之間只通過 JSON 結構傳消息。Monitor 輸出的事件格式固定{ event_id: evt_001, type: cpu_high, severity: P2, target: order-service, metrics: { cpu_usage: 92.5, load1: 18.3 }, timestamp: 2025-01-10T14:23:00Z }Diagnose 拿到這個消息后解析target和type決定拉哪些數據源輸出根因判斷也走固定格式{ event_id: evt_001, root_cause: jvm_old_gc, confidence: 0.87, evidence: [gc log count12, heap usage95%], suggested_actions: [restart_service, increase_heap] }這樣做的好處是每個 Agent 都不需要理解其他 Agent 的“思維過程”只需要消費結構化的輸入、產出結構化的輸出。大模型的不穩(wěn)定性被鎖在了各自的處理流程里Agent 間的通信反而是穩(wěn)定的。這一步我強烈建議不要省略。早期版本試過直接傳自然語言Diagnose 經常把 Monitor 的意思理解偏甚至會自己腦補出不存在的問題。2.3 協(xié)同編排一個輕量的任務狀態(tài)機四個 Agent 不是并行隨便跑的它們得按一個流程走同時允許異常分支。我用了很輕量的狀態(tài)機來做編排沒有引入重型工作流框架就維護一張任務狀態(tài)表狀態(tài)負責 Agent流轉條件detectedMonitor指標越限diagnosingDiagnose收到事件root_causedDiagnose輸出根因置信度 0.6executingExecutor收到建議動作recoveredExecutor恢復命令返回成功notifiedNotify消息發(fā)送成功wait_approvalExecutor置信度低或超閾值操作每個 Agent 異步處理處理完就更新狀態(tài)。狀態(tài)一旦更新會觸發(fā)現(xiàn)有定義的下一跳。這套模型足夠簡單但也踩了不少坑。后面遇到的最多問題都是狀態(tài)沒流轉到、事件卡死這類細節(jié)讓我意識到編排層和 Agent 一樣重要。3. 部署實踐從零搭一個能自主處置告警的 Agent 系統(tǒng)如果你也想搭一套類似的系統(tǒng)我這里把可復制的步驟整理一遍假設環(huán)境是一臺 Linux 服務器、Docker、Python 3.9、已經有大模型 API 的訪問權限。監(jiān)控數據源我們先拿 Prometheus 的 API 來測。3.1 環(huán)境準備和必要的組件清單系統(tǒng)拆四個模塊部署用 Docker Compose 管理。四個模塊分別是事件總線用輕量消息隊列、Agent 執(zhí)行器Python 進程、編排引擎帶狀態(tài)表的小服務用 FastAPI 寫的、管理面板只用來查日志和狀態(tài)。實際部署過程中有幾件事要提醒第一大模型 API 一定要走內網或代理地址不然每次 Agent 調用都走公網延遲不可控。后面排查問題的時候就遇到過一次因為外網不穩(wěn)定導致 Diagnose 響應超時整體任務狀態(tài)卡了十幾分鐘。第二所有 Agent 需要共享一套時鐘。最開始排查一個“事件順序錯亂”的問題發(fā)現(xiàn)是不同容器的系統(tǒng)時間偏差了十幾秒診斷 agent 讀到的日志時序是反的。第三日志必須全部帶結構化字段。最好不要只靠打印字符串。后面調試多 Agent 協(xié)作時一篇混亂的日志根本沒法快速定位是哪個環(huán)節(jié)出了問題。Docker Compose 的 service 定義大致長這樣單機玩法夠用了version: 3.8 services: queue: image: valkey/valkey:7.2 ports: [6379:6379] executor: build: ./executor environment: - MODEL_ENDPOINThttp://llm-gateway:8080/v1 - TOOL_WHITELISTrestart_service,get_cpu,get_mem volumes: - /var/run/docker.sock:/var/run/docker.sock orchestrator: build: ./orchestrator ports: [8081:8080] depends_on: - queue第一版跑起來之后建議不要一次啟用四個 Agent。我是先用假的告警數據流把事件總線拆通再逐個開啟 Agent 驗證。3.2 編寫 Executor Agent 的工具封裝一個關鍵動作是封裝給大模型調用的工具函數。這里最容易踩的坑是模型“亂發(fā)明工具”。第一次跑我讓大模型輸出工具名模型自己編了個restart_nginx_if_cpu_high()的函數名執(zhí)行器當然找不到。解決辦法是工具調用不用自然語言輸出而是用 function calling。大模型結構化返回調用的工具名和參數。執(zhí)行器里注冊所有合法工具模型只能從白名單里選。以查 CPU 為例def get_cpu_usage(host: str) - float: # 調用 Prometheus API 獲取瞬時 CPU 使用率 resp requests.get( fhttp://prometheus:9090/api/v1/query, params{query: favg(rate(node_cpu_seconds_total{{mode!idle,instance{host}}}[5m])) * 100} ) return float(resp.json()[data][result][0][value][1])封裝完這一個函數后需要在 OpenAI 兼容格式的 tools 列表里描述它{ type: function, function: { name: get_cpu_usage, description: 獲取指定主機的 CPU 使用率百分比, parameters: { type: object, properties: { host: {type: string} }, required: [host] } } }tools 描述就像是給大模型的“說明書”。說明書寫得好不好直接影響后面的診斷準確率。3.3 配置定時巡檢與擬人化反饋機制Monitor Agent 不需要大模型純規(guī)則就行。它的巡檢頻率我設為 30 秒一次查詢最近 5 分鐘的平均負載。觸發(fā)條件設置了兩級超過 70% 寫一條 warning 日志超過 85% 進入診斷流程。巡檢本身是死邏輯但反饋要擬人化。我特意給每個 Agent 設置了不同的“人設”描述和措辭模板。比如 Notify Agent 發(fā)消息時會寫“CPU 持續(xù)高位已排查 XX 服務的 GC 日志判斷為堆內存不足已進行重啟操作”而不是只發(fā)一個“CPU 高”。這個細節(jié)的效果非常好——因為最終看消息的還是人措辭越接近人話響應效率越高。而且如果通知周末凌晨發(fā)過來一眼能看清發(fā)生了什么值班的人也不需要再重新拉一堆日志核實可以直接決定要不要介入。3.4 配置權限控制和人工確認環(huán)節(jié)自動化程度越高越要想清楚控制邊界。對外面常見的做法是“全自動或者全手動”其實中間應該有一層灰度策略。我按操作風險分級操作類型風險等級執(zhí)行方式查詢指標、拉日志低自動執(zhí)行重啟服務、清理緩存中自動執(zhí)行寫審計日志回滾版本、變更配置高自動準備命令人工確認后執(zhí)行這個表格是按實際經驗總結的。初期誰都不想讓機器直接改生產配置但全手動又失去了 Agent 的意義。折中下來把“查詢和常規(guī)重啟”交給 Agent 自動做把“回滾、擴容等有長期影響的動作”設為待確認狀態(tài)。通知 Agent 會把預執(zhí)行的命令和變更原因發(fā)出來人工點確認之后Executor 才真正執(zhí)行。有一點很值得說人工確認不能只在流程末尾加那樣 Agent 可能會在決策過程中做出錯誤行為。正確做法是把人工確認作為獨立的狀態(tài)節(jié)點嵌入流程中間。例如高風險的變更在 Executor 生成命令后必須等待確認不允許先執(zhí)行后補審批。權限上還要區(qū)分不同 Agent 能訪問的主機范圍Monitor 和 Diagnose 可以看所有機器Executor 默認只能操作測試環(huán)境的機器生產環(huán)境機器要額外授權。整套權限體系跑通了之后我才敢讓它處理一部分低風險告警。4. 實戰(zhàn)場景實測從“告警產生”到“自動恢復”的完整鏈路整個系統(tǒng)搭建完成后我用三個典型故障場景做了壓測模擬了真實環(huán)境中容易遇到的告警類型。這幾個場景能比較全面地暴露問題。4.1 場景一CPU 持續(xù)飆高Executor 自動重啟服務我模擬了某訂單業(yè)務服務 CPU 打滿的情況。用stress-ng在容器里持續(xù)占 CPU讓其超過 85% 閾值并保持。Monitor 首次檢測到該指標生成告警事件寫入隊列。Diagnose 收到事件后先去拉該服務的 CPU 監(jiān)控曲線確認不是瞬時尖峰是持續(xù)攀升。然后拉日志翻到大量線程阻塞信息結合最近變更記錄判斷根因疑似“連接池配置過小導致請求堆積”最終輸入根因結論和建議動作restart_service和increase_pool_size。由于restart_service屬于中風險操作Executor 執(zhí)行腳本完成重啟。重啟過程中Notice Agent 每步更新進度避免中間狀態(tài)無人知曉。最終查到 CPU 負載回落。Notify Agent 發(fā)出完整報告包含觸發(fā)時間、根因、處置動作、當前狀態(tài)、后續(xù)建議字段。這套聯(lián)動從告警發(fā)生到恢復用了大約 4 分 40 秒。其中大部分耗時在大模型多次推理上。如果繼續(xù)優(yōu)化可以把 Diagnose 的日志分析改成先做關鍵詞預篩再讓大模型判斷總耗時能壓縮到 3 分鐘以內。4.2 場景二誤判差點釀錯人工確認攔住了第二個場景專門測人工確認機制。我模擬的是磁盤使用率報警。Monitor 發(fā)現(xiàn)某臺主機的磁盤超過 90%觸發(fā)診斷。Diagnose 分析后發(fā)現(xiàn)目錄/data/logs占用最多判斷為“日志文件膨脹”建議動作是“清理 7 天前的日志文件”。這個動作本身沒問題但磁盤上其實還跑著一個數據分析任務正準備讀取/data/logs/archive下的舊文件直接清理會破壞這個任務。因為清理動作被列入高風險操作Executor 生成了命令但沒有執(zhí)行而是通過 Notify 發(fā)給我確認。我看到命令涉及刪除文件手動檢查了一下目錄內容發(fā)現(xiàn)舊文件還有用否掉了這個操作改成讓 Diagnose 重新給方案最終換成了“按文件大小和最后訪問時間只清 tmp 目錄”。這個案例很有價值。證明“慢一點確認一下”不是拖后腿反而可能是真正的保護。也正因如此我強烈建議人工確認的閾值設置得偏保守寧多不少。4.3 場景三長任務執(zhí)行中上下文丟失的驚人后果第三個場景是暴露問題最狠的。我模擬了一個復雜故障一個業(yè)務依賴了三個組件狀態(tài)全部異常一個組件磁盤滿一個組件 OOM一個組件網絡延遲高。Diagnose 在同一輪上下文里要分析三個組件的日志。但對話歷史經過截斷較早的組件 A 信息被擠出上下文Diagnose 分析到最后只報告了組件 B 和 C 的問題組件 A 的問題被漏掉。結果 Executor 只處理了 B 和 CA 的故障未被處置。最終告警主鏈路沒有恢復。這個案例敲響的警鐘遠超預期讓我意識到單 Agent 大模型上下文的局限多組件、多關聯(lián)任務的情景個人的記憶窗口就是瓶頸。后續(xù)優(yōu)化方案是拆分解耦。讓 Diagnose 做兩級分析先由一個粗篩 Agent 把所有組件異常匯總成一張清單再拆成獨立子任務分別診斷。每個子任務都是獨立上下文互不污染。現(xiàn)在這個新架構上線后再次模擬同樣的場景三個組件異常都能被正確識別和處置沒有出現(xiàn)“高并發(fā)的多問題互相擠掉”的現(xiàn)象。上下文丟失的問題算是解決了。5. 多智能體協(xié)同系統(tǒng)跑起來之后的優(yōu)化經驗與避坑指南整個系統(tǒng)從能跑到能用中間經歷了大量調整。下面寫幾個我認為最有價值的優(yōu)化點和最容易踩的坑。5.1 大模型返回不穩(wěn)定怎么辦大模型不是每次都聽話的。偶爾會給出越界建議偶爾會漏掉函數調用偶爾會生成亂碼。我的處理思路是給所有 Agent 加一個輸出校驗層。校驗層做兩件事一是格式校驗解析大模型輸出的 JSON、工具調用是否合法二是邏輯校驗——比如 Executor 要執(zhí)行重啟但當前 CPU 負載只有 10%明顯不合理就拒絕執(zhí)行并要求重新診斷。這個校驗層也幫我攔下了一次比較危險的操作某個模型在分析了一句錯誤日志時建議“重裝操作系統(tǒng)”被校驗層直接攔截并標記為異常輸出。所以不要把所有判斷權都交給大模型工具層該有的理智還是要用代碼寫死。5.2 消息隊列選型和事件冪等設計多 Agent 系統(tǒng)里的消息隊列一開始選型很隨意直接用最簡單的 Redis 列表。結果在并發(fā)告警多的時候多個 Executor 同時消費同一個任務重復執(zhí)行了操作。原因是消息沒有做冪等。后來換成了 Stream 類型每條事件帶event_id消費端維護一個已處理集合。遇到相同的event_id直接跳過。這個改動雖然小但效果非常明顯大量因為消息重復觸發(fā)的誤操作消失了。另外Agent 的執(zhí)行入口必須是冪等的。例如restart_service被調兩次第二次要判斷服務狀態(tài)已經是 running就跳過。這也是一種保護。5.3 記憶持久化與上下文管理是保證長任務穩(wěn)定性的基石前文提到的上下文丟失問題除了拆分解耦還需要在架構層面做記憶持久化。我引入了一個向量庫用于存歷史故障處置案例。當 Diagnose 遇到某個事件時會先檢索相似歷史案例把檢索結果拼進 prompt 里供大模型參考。這個機制的效果出乎意料地好——第二次遇到同類故障時Diagnose 的根因置信度明顯提高建議的動作也更貼合之前驗證過的方案。這有點像給團隊加了一份“歷史經驗存檔”每次處置完故障之后整個鏈路都會自動歸檔摘要?,F(xiàn)在每次工單結束我都盡可能地保證歸檔動作是自動完成的并且會把最終的根因、處置動作、驗證結果都寫成結構化摘要。長期跑下來這套系統(tǒng)會越來越懂這個環(huán)境越用越精準。6. 這套模式在落地時實際運維團隊應該如何適配很多朋友看完上面可能會問我這邊沒有大模型開發(fā)和編排能力怎么落地這套東西我覺得核心不是非得自研而是把現(xiàn)有的工具鏈和團隊分工重新理順。6.1 大模型基座用成熟平臺比什么都重要我嘗試過本地部署開源模型也試過各種微調。最后穩(wěn)定下來的方案反而最簡單——用成熟的大模型 API 服務作為底座。主要原因有三個穩(wěn)定性、工具調用的成熟度、持續(xù)迭代能力。部署一個私有模型要處理顯存、推理速度、上下文長度這些問題很影響體驗。而成熟服務在 function calling 上做得比較完善對 Agent 場景支持好。甚至到現(xiàn)在我的 Agent 系統(tǒng)接入的大模型 API 已經在不同版本間切換了好幾次業(yè)務代碼幾乎沒有改動。建議如果要試不必糾結必須完全私有化部署先用成熟 API 把流程跑通再評估后續(xù)需要調整的部分。6.2 運維人員的角色轉型從“操作員”到“策略制定者”當 Agent 真的開始接管低風險操作后運維人員的工作內容會發(fā)生變化。團隊里最明顯的體會是一線工單少了許多例如重啟、日志清理這些重復操作基本不需要人參與了。但提出問題、制定安全策略、審核 Agent 操作合理性的工作量卻變多了。我現(xiàn)在主要做的一件事就是不斷給工具白名單補充和修正操作邊界以及對 Agent 的決策邏輯給出校驗規(guī)則。比如某些命令只在特定目錄可用某些環(huán)境只允許在維護窗口期執(zhí)行變更全部要靠人提前定義清楚。如果團隊里沒有這樣一個“策略制定者”Agent 系統(tǒng)很容易暴走。這塊需要盡早重視哪怕初期一個人專職盯控也比全自動裸奔強。6.3 灰度發(fā)布和評估機制這套系統(tǒng)從 Demo 走到生產用了一個還算穩(wěn)妥的灰度策略先讓 Monitor 和 Diagnose 全量上線但 Executor 只接入一臺測試機跑了兩周確認沒有邏輯錯亂再逐步擴大到低風險操作每一步都留有人工復核通道。我個人的判斷是評估機制的關鍵不在于“自動化率有多高”而在于“人工介入次數是否逐步下降”。如果今天自動執(zhí)行了 100 次但其中 40 次都需要人工干預糾偏那說明 Agent 的學習和判斷能力還沒到位。反之如果人工介入頻率逐月降低說明系統(tǒng)進入了良性循環(huán)新增的自動恢復能力是值得信任的。7. 一些最后想說的話折騰這套系統(tǒng)大半年我最大的感受是“AI 運維 Agent”并不是一個成品而是一個需要持續(xù)調教的協(xié)作過程。多智能體協(xié)同也不是把多個 Agent 丟在一起就能成事關鍵還是清晰的角色分工、穩(wěn)定的信息流轉以及嚴格的邊界控制。最讓我欣慰的時刻是它在一次真實故障里成功識別出根因并自動處置完畢值班同事第二天早上看了一眼報告發(fā)現(xiàn)處理記錄比人工寫的還要清晰。那種“機器真的在幫忙分擔壓力”的成就感很難用語言表達。它不能替代所有判斷但確實把不少重復的、低價值的勞動接了過去。讓做運維的人可以去做更復雜、更值得思考的事這大概就是這套系統(tǒng)最大的價值。