Агентські AIOps із графом контексту: Neocarta, Neo4j, LangGraph та Gemini
Дизайн реагування на інциденти з закритим циклом: імпортуйте ServiceNow, Dynatrace та GitHub до Neo4j, аналізуйте дані за допомогою LangGraph та Gemini за захисним бар’єром, та фіксуйте кожну дію.
Джерела: Building Agentic AIOps: A Closed-Loop Platform with LangGraph, Gemini, and a Native Graph Database
Під час збою на платформі або у команді SRE ця ситуація повторюється. Один інженер відстежує дані Dynatrace, інший переглядає історію розгортань у GitHub, щоб з’ясувати, що змінилося, а третій редагує заявку у ServiceNow, щоб керівництво припинило запитувати про оновлення. Ніхто не має повної карти ситуації, оскільки вона не знаходиться ніде конкретно — вона розкидана між трьома чи навіть десятьма інструментами.
Саме ця фрагментація, більше ніж сама помилка чи неудачне розгортання, здебільшого спричиняє затримки у відновленні. Затримка виникає через те, що люди знову створюють контекст, який вже існував у системі, просто не в одному місці.
План вирішення цієї проблеми передбачає поєднання трьох обраних технологій у єдину платформу AIOps з агентами. Neocarta автоматизує вставку даних у граф Neo4j та забезпечує доступ до цього графа для інструментів штучного інтелекту через MCP. LangGraph здійснює детерміновану оркестрацію дій агентів, а SDK Google Gen AI з Gemini забезпечує механізми міркувань. Тут немає lakehouse, немає пакетної обробки даних ETL, немає вручну створених механізмів webhook та немає панелей керування застарілими метриками. У результаті залишається живий, доступний для запитів граф операційної реальності, до якого агент може отримати прямий доступ та вживати заходів.
Граф контексту замість панелей керування
Багато інструментів AIOps додають інтелект до аналітичних сховищ даних, призначених для бізнес-аналітики, а не для реального часу, що є неправильною основою. У цьому підході операційний стан розглядається як проблема графа. Кожен сервіс, розгортання, інцидент, команда та заходи з усунення проблем стають вузлами, а взаємозв’язки між ними, такі як DEPLOYED_TO, ALERTS_ON, TRIGGERED_BY та OWNER_OF, є ребрами першого класу.
Як тільки події інфраструктури утворюють з’єднаний граф, а не ізольовані журнали, аналіз первинної причини змінює свою природу. Він перестає бути ручною археологією та стає перетином графа, багатоетапним запитом, над яким ШІ може працювати безпосередньо через Graph RAG.
Чотири шари, які закривають цикл
Кожен з чотирьох шарів виконує певну функцію, і цикл закривається тому, що власні дії агента записуються назад у граф. Таким чином, наступна ситуація, яку він обробляє, знає про те, що вже було спробовано.
- Автоматичне збирання даних за допомогою CLI Neocarta ingestion. Замість створення приймача webhook для кожного інструменту, конектори Neocarta отримують метадані та журнали з ServiceNow, Dynatrace та GitHub та завантажують їх у граф. Не потрібно підтримувати окремий сервіс збору даних для кожного джерела.
Neocarta замінює собою спеціалізовану службу обробки даних та прямі виклики драйверів баз даних. Його CLI автоматизує завантаження даних у Neo4j, а сервер MCP є тим інструментом, з яким фактично взаємодіє агент для отримання контексту графа.
Рівні 1 та 2: обробка даних через Neocarta
Схема є першочерговою, адже саме вона є онтологією, на якій ґрунтується вся платформа. Мітки вузлів та типи зв’язків – це те, що кожен коннектор та кожен запит Cypher у кінцевому підсумку читає та записує. Кожна ентріта є вузлом з типом даних, а кожна залежність, зв’язок власності та сповіщення є напрямленим ребром з типом даних. Саме ця структура перетворює процес дослідження в різних інструментах на процес просування по графі.
Раніше для обробки даних потрібно було запускати отримувач webhook окремо для кожного джерела та вручну писати код Cypher для кожної форми даних. Neocarta скорочує цей процес до простої налаштування. Достатньо спрямувати його CLI на ServiceNow, Dynatrace та GitHub, щоб він самостійно здійснював виявлення схеми, інкрементальне завантаження даних та їх відповідне мапування на типи вузлів та зв’язків у графі.
# Register each source once — Neocarta handles auth, schema inference, and scheduling
neocarta connect servicenow --instance your-org.service-now.com --scope incident
neocarta connect dynatrace --tenant your-tenant-id --scope metrics,problems
neocarta connect github --org your-org --scope deployments,repos
# Point the loader at your graph and let it run
neocarta load --target neo4j://your-instance:7687 --database aiops-graph
У основі використовуються ті самі шаблони MERGE та CREATE, які можна було б написати вручну. Перманентні елементи, такі як репозиторії, сервіси та команди, об’єднуються, тож дублікати вузлів ніколи не з’являються. Події, пов’язані з певною моментом часу, наприклад розгортання або інцидент, щоразу додаються як нові вузли, що забезпечує точність часової шкали та зберігає попередню історію недоторканною. Різниця полягає у тому, що ніхто не повинен підтримувати код відповідності між трьома API, які змінюють структуру даних за власним графіком.
Окрім обробки даних, Neocarta додає свій сервер MCP. Як тільки граф заповнений, він стає доступним як кінець точки MCP, і клієнт, який підтримує MCP, зокрема LangGraph, може виконувати багатоетапні запити до графа як звичайні виклики інструментів. Код агента не потребує шару драйверів баз даних для запису чи підтримки.
# LangGraph's context-fetching node talks to Neocarta over MCP,
# not to a Neo4j driver directly
from langchain_mcp_adapters.client import MCPClient
neocarta_client = MCPClient(server_url="http://neocarta-mcp:8080")
tools = await neocarta_client.get_tools() # graph_query, graph_traverse, etc.
Контроль схеми залишається в руках інженерів. Обмеження та індекси визначаються, як завжди, безпосередньо в Neo4j.
CREATE CONSTRAINT unique_service_id IF NOT EXISTS
FOR (s:Service) REQUIRE s.id IS UNIQUE;
CREATE INDEX incident_state_index IF NOT EXISTS
FOR (i:Incident) ON (i.state);
Рівень 3: цикл LangGraph
Цей рівень можна назвати агентним. Замість одного виклику ШІ моделі міркування відбуваються у вигляді машини станів із чітко визначеними вузлами та ребрами, тож кожен шлях прийняття рішень можна перевірити, протестувати та проаналізувати, на відміну від непрозорого циклу багатьох агентів.
Стан — це типований словник, який передається через граф.
class AIOpsAgentState(TypedDict):
incident_id: str
failing_service_id: str
graph_context_summary: Optional[str] = None
safety_gate_passed: Optional[bool] = None
chosen_action: Optional[str] = None
target_repository: Optional[str] = None
execution_result: Optional[str] = None
Чотири вузли керують цим циклом:
FetchGraphContextвикликає інструмент graph_traverse у сервері MCP Neocarta, щоб простежити інцидент назад до відповідної служби, потім до версії програмного забезпечення, яка її змінила, до відповідного репозиторію та до команди, яка нею керує. Код агента ніколи не підтримує пряме з’єднання з базою даних.VerifySafetyGateчерез ту саму інтерфейсну систему запитів MCP перевіряє, чи вже були застосовані заходи щодо цієї служби протягом останньої години. Цей механізм захисту запобігає безкінечному циклу роботи агента з нестабільною службою.GeminiReasoningзапускається лише у разі, якщо перевірка пройшла успішно. Gemini 2.5 Pro отримує узагальнення контексту графа разом із конкретною системною інструкцією, причому єдиною прийнятною відповіддю є один із двох фіксованих токенів.
ExecuteRemediationTool запускає процедуру виправлення та записує вузол RemediationAction назад у Neo4j через Neocarta, що завершує цикл.Якщо якийсь компонент заслуговує на найбільшу увагу, це система безпеки. Вона описана тут як виклик інструменту MCP, а не як пряма сесія драйвера.
async def evaluate_remediation_safety_gate(state: AIOpsAgentState) -> Dict:
result = await neocarta_client.call_tool(
"graph_query",
cypher="""
MATCH (s:Service {id: $service_id})<-[:EXECUTED_AGAINST]-(a:RemediationAction)
WHERE a.timestamp >= datetime() - duration('PT1H')
RETURN count(a) as active_actions
""",
params={"service_id": state["failing_service_id"]},
)
return {"safety_gate_passed": (result["active_actions"] == 0)}
Автономний цикл дій без захисного механізму ніколи не повинен потрапляти у виробництво. Саме цей механізм запобігає тому, що агент буде знову ініціювати скасування дії кожні тридцять секунд через те, що основна аномалія ще не усунута.
Вузол Gemini робиться нудним навмисно, і саме це є його перевагою.
system_instruction = (
"You are an automated Agentic AIOps architect. "
"Analyze the provided graph context summary. "
"If a deployment recently modified the service state, "
"output EXACTLY the word TRIGGER_ROLLBACK. "
"If the context is clear but safe guidelines are violated, "
"output HALT_ESCALATE. Do not append any other characters."
)
Обмеження вихідних даних моделі до двох точних токенів робить її виклик більш схожим на функцію з введенням параметрів, ніж на відповідь у чаті, що є правильною характеристикою у випадку, коли результат спричиняє скасування операції в продакшені.
Рівень 4: закриття циклу
Останній вузол або ініціює скасування через API GitHub Actions, або нічого не робить, окрім як фіксує це у журналі. У будь-якому разі граф оновлюється через той самий шлях запису MCP, що й усе інше, тому для збереження даних не потрібні окремі облікові дані бази даних.
await neocarta_client.call_tool(
"graph_write",
cypher="""
MATCH (s:Service {id: $service_id}), (i:Incident {id: $incident_id})
CREATE (a:RemediationAction {id: $action_id, timestamp: datetime(), status: 'SUCCESS_ROLLBACK'})
CREATE (a)-[:EXECUTED_AGAINST]->(s)
CREATE (a)-[:ATTEMPTED_TO_FIX]->(i)
""",
params={"service_id": service_id, "incident_id": incident_id, "action_id": action_id},
)
Те, що робить цю систему замкнутого циклу, а не простим скриптом автоматизації, — це простий деталь: результат власних дій агента стає контекстом для наступної ситуації, яку він аналізує, тож з часом платформа стає все більш обізнаною щодо ситуації, а не менш.
Інцидент від початку до кінця
У проекті передбачена симуляція без реальних дій, яка показує, як всі елементи взаємодіють, і її результати є корисними для розуміння.
- 14:00:00. Сервіс платіжного шлюзу завершує розгортання, що додає відповідний вузол Deployment, підключений до цього сервісу.
- 14:05:00. Dynatrace виявляє критичну аномалію у тому ж сервісі.
- 14:06:00. У ServiceNow з’являється інцидент рівня P1, який стає вузлом Incident та пов’язується з сервісом за допомогою краю ALERTS_ON.
Від моменту виникнення аномалії до її усунення проходить кілька хвилин, а не потрібен дзвінок у оперативну кімнату. Кожен крок логічних міркувань залишається прозорим у графі, тож можна дізнатися, чому агент вчинив саме так.
Як тільки інцидент нанесений на карту, він утворює єдину пов’язану структуру, яка охоплює команду, код, процес розгортання, сервіс, сам інцидент та дії агента з його усунення. Саме цей підграф є об’єктом аналізу Gemini, і саме наявність однієї пов’язаної структури замість трьох окремих панелей керування дозволяє агентові простежити інцидент рівня P1 аж до відповідного коміту у Git.
Цю історію можна розділити на три етапи, які сформували граф: розгортання, збій та усунення. Кожен з цих етапів є окремим записом у базі даних, проте разом вони створюють єдину послідовну часову лінію, яка простягається від злиття коду у Git через сповіщення про проблеми в продакшені до завершення усунення проблеми протягом семи хвилин.
Надання інженерам можливості бачити граф
Автономна система, яку інженери не можуть перевірити, є джерелом ризиків. Тому план включає панель керування Streamlit, створену на основі pyvis, яка відображає актуальну топологію графа та постійний облік виконаних дій.
net = Network(height="600px", width="100%", bgcolor="#1a1c1e", directed=True)
color_map = {
"Team": "#5f3dc4", "Repository": "#24292e", "Deployment": "#007acc",
"Service": "#11a685", "Incident": "#c41c1c", "RemediationAction": "#cc0088"
}
Інженери мають можливість переглядати всю ланцюгову структуру — від злиття коду в Git до інциденту в продакшені та автоматичного виправлення — з можливістю перетягування елементів та зумування. Також є бічна панель із списком усіх дій, виконаних агентом, у порядку їх виконання. Саме така прозорість робить автономну систему достатньо надійною для використання в продакшені, адже жодна з її дій не залишається непрозорою.
Розгортання, яке не завдає шкоди продакшену
Рекомендований підхід є обережним: він складається з трьох етапів, а не передбачає одночасне ввімкнення системи.
- 1-й тиждень: отримання даних та їх перевірка. Налаштуйте конектори Neocarta на копії даних з кожного джерела у сандбоксі, створіть обмеження для графа та перевірте, чи вузли правильно відображаються та пов’язані між собою, перш ніж почати використовувати дані з продакшену.
Лише після того, як усі три етапи пройдуть успішно, інструменти для усунення проблем можуть бути спрямовані на кінцеві точки продакшну.
Чому така конструкція є ефективною
Кілька рішень відрізняють демо-версію від надійного рішення в умовах продакшну.
- Машини станів кращі за цикли агентів з вільною формою. LangGraph робить кожен шлях прийняття рішень прозорим та піддаємим перевірці, при цьому не існує прихованих ланцюгів міркувань, які неможливо відтворити.
- Перед кожним викликом LLM, який може спричинити дію, існує захисний бар’єр. Якщо нещодавно була виконана процедура усунення проблеми, агент не може отримати доступ до вузла міркувань. Ця перевірка знаходиться у детермінованому коді, а не у запиті.
- Контракт вихідних даних є обмеженим. Від Gemini не вимагають написання прозового тексту. Обмеження кількості символів до одного з двох токенів робить його результат настільки надійним, як значення, що повертається функцією.
- Граф виконує функцію пам’яті, а не лише сховища. Дії з усунення проблем записуються в той самий граф, який читає агент, тож його усвідомлення ситуації накопичується та не скидається з кожним інцидентом.
- MCP — це з’єднувальний елемент між агентом та графом. Завдяки серверу MCP від Neocarta, який знаходиться між LangGraph та Neo4j, агент ніколи не використовує драйвер бази даних та не керує пулами з’єднань. Він просто викликає необхідні інструменти. Цей з’єднувальний елемент також дозволяє замінити Gemini на інший модель чи LangGraph на інший оркестратор, не торкаючись процесу отримання даних чи шару графа.
Контекст, який нативно знаходиться в графі, логічний цикл із фіксованими кроками та механізм захисту, вбудований у код, разом роблять автономне вирішення проблем чимось, що можна запустити на практиці, а не лише чимось, що виглядає гарно на слайді. Логічними наступними кроками буде розробка цього комплексу з використанням Docker Compose та надсилання сповіщень у Slack з роутера 4-го рівня, щоб люди дізнавалися про кожну автономну дію, навіть якщо їм не потрібно було втручатися.