AegisOps: аўтаномны SRE-агент з чатырма ўзроўнямі памяці
Як ReAct-агент на LangGraph вырашае інцыдэнты ў Kubernetes: эпізадычная памяць на pgvector, узроўні аўтаноміі пад кантролем палітык, шаснаццаць інструментаў і поўны аўдыт.
Крыніцы: I Built an Autonomous SRE Agent That Resolves Production Incidents While I Sleep
Зараз 3:14 ранку, і PagerDuty актыўна працуе. Prometheus выдала крытычныя паведамленні: парадактныя сітуацыі ў службе платэжаў вырасілі да 34%, кантэйнеры згінуць унаследке працэса OOMKills, а тэрмін на выкананне умов SLA заканчываецца за шасць хвілін. Ёсць два варыянты: або встац з ложка і падключыцца праз SSH да кластэра, або дазволіць агенту разбірацца з проблемай.
AegisOps — гэта автонамны агент SRE, створаны саме для такіх момантав. Ён дыяганастыкуе, прыме заходы і рашае проблемы ў працоўным сераўеры без участку чалавека, а таксама фіксуе кожную сваю рашыццю і прычыну яе. Гэта не чат-бот, які працуе праз kubectl. У яго ёсць рэальная памяць, шаровыя механізмы автонамнага керавання і можлівасць навучання на адпаведных інцыдэнтах. Заявленая мета ніколі не была заменіць інжынера, які працуе у рэжыме нарадчыка, а дастаць яму неканчлівага агента, які ужо знае інструкцыі, памятае пяцьце апошніх інцыдэнтаў і пераканальваецца з правіламі перш чым вплываць у працоўны сераўер.
Чаму ReAct у LangGraph
ReAct (Разумаванне плюс Дзеянне) пасуюць для рэагавання на інцыдэты. Звычайны ланцуг выконвае крокі слепа, тады калі агент ReAct стварае мысль, выбірае дзеянне, спазірае, што адбылося, і продовжае цікл. Гэта праві падход у разы збою, калі важлівыя запытанні — гэта тое, што вядома, што спазіруецца і што прабавіць далей.
LangGraph апранае выконанне графа з станамі. Кожны вузел бачыць цэлы AegisState — TypedDict, які зберагае паведамленні, памяць, даклады інцыдэта, рашэнні па правілах, вызовы інструментаў і рэзультаты пераканання. Паколькі стан пасля кожнага кроку зберагаецца ў PostgreSQL, выконанне можна паставіць на паузу, пераглядзець і запусціць зноў.
У графе ёсць чатыры вузлы, якія намерна залічваны простымі, каб утрымацься ад занадто сложнай архітэктуры:
-
memory_nodeпрацюе першым і завантажае усё, што патрэбна агенту, прычыму пачатку якога-небудзь аналізу.
agent_node– гэта цыкл аналізу ад ЗІШ.tools– гэта стандартныToolNodeз LangGraph, які выкананяе тое, працоўку якое запрашае мадэль.resolution_nodeзавершае інцыдэнт: ён зберагае інформацыю, вырахоўвае MTTR і аправляе паведамленне ў Slack.
Чатыры слоі памяці
Большасць сістэм агентаў ігнаруе архітэктуру памяці або задаваліся двума слоямі. Чалавек-СРЭ пры інцыдэнце выкарыстоўвае чатыры відменнікі памяці, а AegisOps відтварае ўсе іх.
- Эпізодычная памяць (pgvector, косінусная схожасць) зберагае прымусованыя інцыдэнты з працэй каляк у віглядзе эмбедынгаў. Калі з’являецца новы інцыдэнт, выбіраюцца тры найболей схожыя практычныя прыклады з працэй каляк і включаюцца ў запрошэнне да сістэмы разам з ўсімі дапаможнымі дадзеннямі: первынной прычыной, выконанымі дзеяннямі і рэзультатамі.
- Семантычная памяць (RAG на базе дакументаў у pgvector) зберагае часткавыя версіі інструкцый, дакументаў архітэктуры і аналізаў пасля інцыдэнаў. Інструмент
retrieve_runbookшукае ў іх семантычна, тым самым надаючы агенту інстытуцыйныя знанні каманды.
params.yml у Redis на пачатку обработкі дадзенняў і ацэнююцца перад кожным дзеяннем, якое чаго-небудзь зміняе. Можна сказаць, што гэта трэнаваны рэфлекс агента для безпечных операцый.Эпізодычная памяць у практыцы
Працюючы з данымі, memory_node вызывае retrieve_similar_incidents з спісам сімптамаў тэкушчаг інцыдэнта. 768-вымірны кодэр выражэнняў інкорпоруе гэтыя сімптамы, а функцыя косінусовай аддаленасці з pgvector парабягае ўпораўненне іх з таблой IncidentMemory. Інцыдэнты з мінулога, якія пасягаюць за прагу схожасці 0,72, фарматуюцца і размешчаюцца ў запрошэнні да сістэмы, раней за першую думку агента.
Пасля рашэння проблемы resolution_node вызывае save_incident_memory, ў рэзультаце чаго агент запісвае свае сабеўспамінанні. Інкорпорацыя сімптамаў адбываецца за дапамогою гіпотэзы асновнай прычыны, таму пазнейшы інцыдэнты з аднаковымі сімптамамі знайдуць гэты інцыдэнт.
Апштальованая база дадзеных вектараў, такая як Pinecone або Weaviate, была адной з апцыянаў. Зберагчы ўсё ў PostgreSQL, скасавалася адна залежнасць ад інфраструктуры, а таксама была забезпечана транзакцыйная супараднасць між запісамі прынадзей і ўсунутымі з іх данымі. Працюючы у такім масштабе, pgvector цалкам дастатні.
Рэвэліянтнасць агентаў ад L0 да L3
Гэта была самая складная задача пад час праектавання: як даць агенту рэальную владу над працэйным сервісам без рызыку катастрофы? Адказ — гэта модэль рэвэліянтнасці з роўнамі, пры якой кожны крок, які можа змяніць стан, перад выкананнем перакрыты правіламі.
Кожны адміністратыўны інструмент (restart_deployment, scale_deployment, update_deployment_image) пачынаецца з вызову retrieve_policy. Механізм правіл аналізуе дзеянне, службу, ступень сур’ёзнасці і тэкушчы рэвэлюнт самастоятэльнасці ў супрацоўцы з правіламі, зазначанымі ў params.yml. Калі адпаведзь — няма, інструмент негайна вяртае адмову, і агенту трэба знайсці іншы спосаб, зазвычай паўзеўкі.
Поле requires_approval заслуговае на увагу. Нават на рэвэлюнцыі L3 дзеянні, якія можуць заваражыць сістэму, напрыклад адкатванне зображэння ў крытычна важлівай службе платэжаў, все ўсё заставаюцца патрэбнымі явнай падтрымкай чалавека. Агент падае запыт у Slack і чакае. Чыгунне гарантуюць командзе, якая працуе ў рэжыме 24/7, што найбольш рызыкаваныя операцыі контролююцца чалавекам.
Шысцьціна інструментаў
AegisOps прыносіць шысцьціна інструментаў у чатырох катэгорыях. Шасць з іх выдзеляюцца:
- get_logs — гэта апарат для збору доказаў. Ён берае пасляпярэднія 500 рэчэй з файла журналу службы, застаўляе запрашаныя рэгламенты і адфільтруе кожную рэчэ ад IP-адрэс, UUID-аў і звычайных цэфраў. Два адхіленні з разных хостаў таму лічыцца як адна модэль. Клас
Counterу Python атрыбутуе рангі модэлям і вяртае тыя, якія з’являюцца частае. Чытальнікі тэрмінала і цікл аналізу агента отрымаюць адно і тое ж структураванае рэзультат, і не ўчаствуе жадны кластэр Elasticsearch — толькі файл журналу і калькі рэчэй на Python. - get_pod_status запытае Kubernetes CoreV1Api пра пады, якія маюць атрыбут
app={deployment}, і адмаўляе інфармацыю пра перзапускі, гатовнасць і стан контэйнераў. Калі да кластэра немагчыма дасягнуць, ён ввічліва пераходзіць на альтэрнатыўны спосаб і прыказвае агенту выконацьget_logsу замене.
kubectl.kubernetes.io/restartedAt запускае поступовы перзапуск, пасля чаго чакае, пакуль усе рэплікі стануць гатовымі, і адбывае перакананне стану. Апшарговы крок дазволяе утрымаць трафік пахадзеў пад час перзапуску.True толькі тады, калі усе пады гатовыя і колькасць адпаведзей 5xx застаецца ніжэй 5%.Ад адзінага інцыдэту да завершэння
Гэта тое, што агент зрабіў па проблеме OOMKill у службе платэжаў о 3:14 ранку:
[MEMORY] Loading episodic context for payment-service...
[MEMORY] Found 2 similar past incidents (similarity: 0.89, 0.76)
[MEMORY] Loaded 3 procedural policies for payment-service/critical
[THOUGHT] Incident: payment-service OOMKill, 3 pods CrashLooping.
Past incident INC-2801 had identical symptoms — root cause was
a memory leak in the gRPC connection pool after a deploy.
Starting with get_logs to confirm before acting.
[ACTION] Calling tool: get_logs with {'service_name': 'payment-service', 'log_level': 'error'}
→ top_errors: [{"pattern": "out of memory: kill process", "count": 47},
{"pattern": "grpc connection pool exhausted", "count": 23}]
[THOUGHT] OOM confirmed. gRPC pool exhaustion matches INC-2801 pattern.
Retrieve runbook before acting — want the fix procedure.
[ACTION] Calling tool: retrieve_runbook with {'query': 'payment service grpc oom memory leak fix'}
→ [runbooks / payment-service-oom.md] Recommended action: rolling restart
resets connection pool. If recurs within 1h, rollback to previous image.
[THOUGHT] Runbook confirms rolling restart. Checking policy for autonomy L2...
[ACTION] Calling tool: restart_deployment with {'service': 'payment-service',
'deployment': 'payment-worker', 'namespace': 'production',
'severity': 'critical', 'autonomy_level': 'L2'}
→ policy: ALLOWED (L2 ≥ min_level L2 for restart_deployment)
→ draining pods... restarting... polling rollout...
→ health_check: healthy=True, pods_ready=3/3, error_rate=0.008
[THOUGHT] Restart succeeded. Error rate 0.8% — below 5% threshold.
Verifying with check_service_health before closing.
[ACTION] Calling tool: check_service_health with {'service': 'payment-service',
'deployment': 'payment-worker', 'namespace': 'production'}
→ healthy=True, pods_total=3, pods_ready=3, error_rate=0.007
[THOUGHT] Service fully recovered. Writing audit log and resolving.
[ACTION] Calling tool: write_audit_log ...
→ audit_log written: restart_deployment for incident INC-2847
RESOLVED: payment-service recovered after rolling restart. Root cause: gRPC
connection pool OOM — matched pattern from INC-2801. All 3 pods healthy,
error rate 0.7%. MTTR: 187 seconds.
[MEMORY] Saving incident INC-2847 to episodic memory...
[NOTIFY] Sending resolution to Slack channel: #all-aegisops ✅
Усё гэта зайняло 187 секунд — ад часу паведамлення да рашынення працэй пройшло трохі больш чым тры хвіліны, пры чым ніхто не быў прыгожаны. Гэты показнік цяпер стаў стандартным для інцыдэтаў, падобных да пакананых. Агент спачатку аналізаваў тое, што працавало ў пакананы раз, як і рабіць бы гэта вышэйшы інжынер, тое ўсё ўскладнюецца эпізодычным запамятованнем.
Гэтыя даны былі пераканструйаваны для большай яснасці. Рэальны запуск на простай локальной сістэме, з аднім кластэрам Kind без Prometheus, выглядае інакш. Інцыдэт быў спрычынены простым вызовам webhook у PowerShell:
Invoke-RestMethod -Uri "http://localhost:8000/webhook/incident" `
-Method Post `
-ContentType "application/json" `
-Body '{
"source": "webhook",
"severity": "critical",
"service": "payment-service",
"symptoms": ["High 500 errors", "DB connection timeouts"],
"autonomy_level": "L2"
}'
Агент запрацавіў усё гэта ад початку да канца. Ён знайшоў падобныя інцыдэнты і сформулаў гіпотэзу, што сплеск трафіку перэтвараецца ў перавантажэння ўместа паддоў, што падабнае да падобнага кейса з працэсу памяці. Ён вызваў get_pod_status і побачыў, што 2 з 5 паддоў готавыя, пасля чаго расшырыў розмішчэння да 4 рэплік, паўтарна пераканаўся за дапамогою check_service_health і закрыў інцыдэнт з статусам RESOLVED. У чат-канале #all-aegisops з’явілася паведамленне, а інцыдэнт быў запісаны знову ў памяць інцыдэнтав.
Гэта спакойней, чым збой гRPC з-за нехваткі памяці о 3 гадзіны ночы, але цыкл застаецца тым самым: той самы цыкл Мысль, Дзеянне, Абазораванне, тая самая перакананне ў правілыях першыя расшырэння і той самы запіс у памяці напрыканце. Толькі атмасфера ў меньшай меры напружаная. Агент не можа розразліці кластэр з ноутбукамі і флот з 50 вузламі. Змяніце kubeconfig, націяйце Prometheus на рэальныя показнікі, і той самы код будзе працаваць у рэальных умовах.
Slack як канал выходных дадзенняў
Значныя дзеянні адправляюць паведамленне ў Slack. Калі інцыдэнт завершаецца, вузол з рашэнням запішае інфармацыю ў #all-aegisops з колерам ступеня сур’ёзнасці, часам на выкарыстоўванне рашэння і повным апісам рашэння, тады інжынер, які знаходзіцца у рэжыме чату, бачыць зелёную галочку, а не спавяшчы сігнал.
Тэхнічная структура
Усё гэта працюе на простай тэхнічной структуры. PostgreSQL з pgvector адпавядае за зберагчыце эпізодычнай інформацыі і чэкпоінты LangGraph. Redis храніць правілы і будзе выкарыстоўваны для будучых обмежэнняў частоты запытоў. Prometheus надае рэальныя паказнікі колькасці бядаў у функцыю check_service_health, а Grafana стварае панелі керування.
version: "3.9"
services:
postgres:
image: ankane/pgvector:latest
ports:
- "5445:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: admin123
POSTGRES_DB: aegisops
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:alpine
ports:
- "6380:6379"
app:
build: .
ports:
- "8000:8000"
env_file: .env
depends_on:
- postgres
- redis
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./infra/prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
postgres_data:
Эты ўтварэнне — FastAPI пад uvicorn. Інцыдэнты прыходзяць на канцэнтр пэўбэк, які стварае IncidentEvent і вызывае run_agent(). Выкананне ўявляе сабою асінхронную працу, таму калькі інцыдэнтов можна обрабатваць паралельна без блакання. Кліент для Kubernetes — kubernetes_asyncio, які дбае пра тое, каб вызовы кластэру былі асінхроннымі.
Ёсць адна проблема: get_pod_status і check_service_health завантажаюць настройкі Kubernetes калі імпортуецца модуль, а не ўнутрь асінхроннай функцыі. Калі кластэр не ўступае ў контакт пад час запуску, яны працуюць без адзінаго паведамлення пра аберанне і вяртаюць паведамленні пра апазоры, таму неабходна пераканацца, што KUBECONFIG або акаунт службы ў кластэры налаштаваны ўжо да запуску ўтварэння.
Хроніка аўдыту
Кожны выклік інструмента фіксуецца ў ToolInvocation TypedDict: што было запусцана, з якімі параметрамі, што вернулася, чы было досягнута мета, скількі часу гэта зайняло, калі і якая правільна рашынка цэго дазволіла. Этыя запісы накапліваюцца ў state["tool_invocations"] пад час працы і зберагаюцца ў перыодычной памяці пасля завершэння. Аддзельны інструмент write_audit_log выдае структураваны JSON-радок для кожнай значныя дзеяння.
Рэзультатам яе ўжыццёвае ў тым, што будзь-які інцыдэнт можна праз тым перэглядзець: последовасць крокаў, дзейнаўчыя правы, якія дзейнавалі, і прычыны кожнага з іх. Команды з адпаведальнасці за салідарнасць просільга самэ такія запісы.
Адзін выбор дыяграматыкі вплывае на всю сістэму. Кожны крок змены фіксуе рашэнне правіл адночасна з рэзультатамі перагляду стану, таму агент ведае тры рэчы заодно: чы робіцца вызов, чы ён быў дазволены і чы сэрвіс зараз у стабільным стане. Усе тры фактары вплываюць на яго наступныы рашэнні.
Што яшчэ не ўсталяна
Усё вышэспісаванае працюе ад початку да канца. Далейшая развіцце была обмежана тым, што локальны камп’ютар мусіў выкананы Ollama падчас працы цэлай сістэмы. З большымі рэсурсамі спачатку выявляюцца тры прынтанты.
Працэс затверджэння — гэта найбольшыя проблемы. У стацыянцы ужо існуе approval_status, а requires_approval ужо пераканалізаваны, пры тым нічога на самай працы не зупіняецца. План — адправіць кнопку ў Slack, зупініць граф і пракрацаваць толькі пасля таго, як хтось нажме на яе, перш чым будзе выконана якая-небудзь дзеянне рэвэню L3. LangGraph можа зупініць граф пад час ўжывання за дапамогою своіх точак контролю, таму застаецца толькі налагоджэнне, а не перадзялёвка.
Порэшанне па показніках «до» і «пасля» — гэта другая проблема. check_service_health — гэта кадровы знімак стану пасля выправлення. Агенту патрэбны показнікі Prometheus у віглядзе дэльты: канцэнтрацыя памылак за пяць хвілін да і пяць хвілін пасля, ўпэўніцца, што ўсё справды было выправлена, а не проста спадобалася збіг часу.
Самастворэнне інструкцыйяў ў якосты рулоніка ёсць давялегацельны праграма. На дзесяньні два істочнікі знанняя — перадышлыя інцыдэнты і інструкцыйі — ніколі не супрацоўнаюць адзін з аднім. Пасля нестандартнага рашэння працавнік павінен напісаць новы фрагмент інструкцыйі і дадаць яго ў базу знанняя, каб retrieve_runbook могаў яго вернуць наступны раз. Гэта з’яеднае баць два слоі памяці.
Што навучыў праект
Адказная проблема з автонамнымі агентамі інфраструктуры, як выявілася, не ў логіцы модэлю, а ў структуры безпекі, якая яго абрамляе. Слоі памяці, механізм прыняцця рашэнняя, лёгкі для адстэплення журнал і процедуры затверджэнняя — гэта тое, што прыводзіць каманду да гатовасці заставіць інструмент працаваць сам ад 3 гадзін ранку.
AegisOps выступае за структураваныя машыны станоўлення з чыстымі межамі праваў, якія пераважаюць над агентамі, якія дзейнуюць свабодна і імпровізуюць. Гэта падход зьявіўся эфектываў: ёсьць болей развіты лог інцыдэтаў, а агент павышае свою эфектыўнасьць пасля кожнага новага кейсу. Функцыя контрольных пунктав у LangGraph, чыстая разліка між дыягнастычнымі і дзейнароднымі інструментамі, а таксама вікорыстанне TypedDict для стану сістэмы дапамагаюць лёгка адзірваць, дыбагаваць і аўдытаваць сістэму, калі ўтвараюцца проблемы, і трэба з’ясавіць, чаму агент выбраў такі спосаб дзеяння.
Калі вы ствараеце ўсё гэта, рана інвестуйце ў архітэктуру памяці. Агент з хорашаю памяцю ценіцца у дзесяць разоў больш, чым той, у якога толькі трохі лепшыі запрос. Для Transformers была неабходна ўвага, а агентам у рэальным свеце — кантэкст.
Спаднія матэрыялы
- Знімкі памяці агента, навыкі, занепад якосты дадзеных і скарыстаўанне памяці па галузях — Чатыры дадатковыя функцыі для вбудованага шара памяці у вектарнай БД для агентаў, якія выконваюць код: перэносныя знімкі памяці з можлівасцю з’еднання, актывацыя навыкаў, занепад якосты дадзеных з перакрычанням конфліктав, а таксама скарыстаўанне памяці па галузях.
- Скарыстаўанне інструментаў у працэсе вырабоцтва для агентаў: праўяжнасць дадзеных, прабавы вызова і можлівасць абзірнае аналізу — Агент банку часта вызываў платную API і выдумваў номеры тэлефонаў. У статыцы рассказваецца пра мінімальныя наборы інструментаў, праўяжнасць параметраў, трывалыя прабавы вызова і показнікі для кожнага інструмента.