Агентные 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 до поступления оповещения в производственной среде и завершения устранения проблемы в течение семи минут.
Предоставление инженерам возможности просматривать граф
Автономная система, которую инженеры не могут проверить, представляет собой риск. Поэтому в проект включена панель управления 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-го уровня, чтобы все знали о каждом автономном действии, даже если никому не пришлось вмешиваться.