Главная / Статьи

Агенты по расследованию происхождения в Neo4j и LangGraph

Агент для анализа происхождения данных в Neo4j и LangGraph, который сортирует и просматривает ребра FEEDS_INTO по каждому арендатору, проверяет гипотезы и записывает результаты аудита в MLflow.

Издатель: REACTAPP.TOP17 мин чтения3878 слов

Источники: Production-Grade AI-Powered Data Lineage Observability Agent with LangGraph, Airflow, DBT, Neo4j, MLflow, Gradio, GEval

Инциденты с данными редко начинаются с панели управления, на которой загорается красный свет. Они возникают на более ранних этапах — при вводе данных, их преобразовании и объединении, процессы которых никто не может описать в условиях стресса. Эта технологическая стек превращает цепочку операций с данными в инструмент расследования: Neo4j хранит связи типа FEEDS_INTO, LangGraph выполняет алгоритм из шести узлов (с дополнительными уточнениями), FastAPI обеспечивает доступ к данным, MLflow фиксирует результаты выполнения, а Gradio предоставляет операторам консоль управления.

Хранилище и обзор

Проект включает инфраструктуру как код, граф цепочек операций с данными, инструмент для организации расследований, HTTP-API, систему отслеживания экспериментов и простой интерфейс пользователя. Среднее время расследования составляет менее полуминуты, причем структурированные цепочки гипотез оцениваются по стандартному набору критериев для инцидентов.

Технологический стек

Terraform используется для управления облачными ресурсами, Neo4j — для отслеживания происхождения данных, LangGraph — для управления потоком выполнения, FastAPI — для создания API, MLflow — для хранения параметров, метрик и артефактов, Gradio — для улучшения пользовательского интерфейса операторов, а сеть судей — для оценки в автономном режиме.

Обзор архитектуры

Сигналы тревоги поступают на этап сортировки; алгоритмы прослеживания определяют пути предков узлов; профилирование дает общую картину состояния узлов; формируются гипотезы о причинах происходящего; выполняются проверки на безопасность; генерируются структурированные отчеты. При отсутствии идентификатора уточняются причины сбоев.

Инфраструктура как код с использованием Terraform

terraform init
terraform plan # previews 16 resources across containers, volumes, images, network
terraform apply # provisions all infrastructure
terraform destroy

Сначала разрабатывается план, затем он реализуется; результаты операций — URL-адреса графов, имена бакетов, секреты webhook-сервисов — встраиваются в конфигурацию выполнения, а не копируются из консоли в ноутбуки.

Модель данных

Клиенты, наборы данных, задания и таблицы становятся узлами; ребра FEEDS_INTO отражают направление передачи данных. Метки многоклиентской архитектуры предотвращают проникновение данных одного клиента в данные другого.

Создание графа происхождения в Neo4j

Поиск предков для определения зоны поражения:

MATCH path = (ancestor)-[:FEEDS_INTO*1..10]->(target {name: $name})
RETURN
ancestor.name AS name,
labels(ancestor)[0] AS node_type,
ancestor.layer AS layer,
ancestor.client_id AS client_id,
length(path) AS depth
ORDER BY depth ASC

Проход через граф с использованием фильтров клиентов:

MATCH path = (upstream {client_id: $client_id})-[:FEEDS_INTO*2..]->(downstream {client_id: $client_id})
MERGE (upstream)-[:UPSTREAM_OF]->(downstream)

Агент расследования — шесть узлов плюс инструменты для уточнения

TRIAGE

Классифицирует степень серьезности и выбирает узел в графе на основе данных тревоги.

TRAVERSE

Расширяет поиск вверх и вниз в пределах установленного числа шагов, соблюдая фильтры клиентов.

PROFILE

Присваивает кандидатским узлам информацию о свежести данных, объеме и характеристиках ошибок.

HYPOTHESIZE

Структурированные гипотезы с рангами:

class Hypothesis(TypedDict):
    rank: int
    hypothesis: str
    confidence: float
    verified: bool
    evidence_query: str | None
    class AgentState(TypedDict, total=False):
    # Webhook input
    run_id: str
    dag_id: str
    client_id: str
    failed_task_id: str
    exception_message: str
    # TRIAGE output
    error_type: str
    severity: str # P1 / P2 / P3
    # TRAVERSE output
    lineage_chain: list[dict[str, Any]]
    affected_models: list[str]
    # PROFILE output
    run_history: list[dict[str, Any]]
    dbt_failures: list[dict[str, Any]]
    # HYPOTHESIZE output
    hypotheses: list[Hypothesis]
    # VERIFY output
    verified_cause: str
    fix_suggestion: str
    # REPORT output
    incident_id: int | None
    mlflow_run_id: str | None
    # CLARIFY branch
    needs_clarification: bool
    clarification_msg: str

Инструменты для анализа шаблонов ошибок:

_ERROR_PATTERNS: list[tuple[re.Pattern, str]] = [
(re.compile(r"schema|column.*(not found|missing|mismatch)", re.I), "schema_change"),
(re.compile(r"not.null|null.*check|null.*value", re.I), "null_check"),
(re.compile(r"fresh|stale|sla|last.*loaded", re.I), "freshness"),
(re.compile(r"timeout|timed out|exceed.*limit|pool.*exhaust", re.I), "timeout"),
(re.compile(r"upstream.*fail|dependent.*not.*material|cannot execute", re.I), "dependency"),
]
_MART_TASKS = {"run_mart_daily_revenue", "run_mart_inventory_health"}
_INT_TASKS = {"run_int_order_fulfillment"}
def triage_node(state: AgentState) -> AgentState:
  exception_msg = state.get("exception_message", "")
  failed_task_id = state.get("failed_task_id", "")
  error_type = _classify_error(exception_msg)
  severity = _assign_severity(error_type, failed_task_id)
  return {**state, "error_type": error_type, "severity": severity}

Логика узлов гипотез:

def hypothesize_node(state: AgentState) -> AgentState:
      run_history  = state.get("run_history", [])
      total_runs   = len(run_history)
      failed_runs  = sum(1 for r in run_history if r.get("status") == "failed")
      failure_rate = failed_runs / total_runs if total_runs else 0.0

      prompt = _USER_TEMPLATE.format(
          max_hypotheses=settings.agent_max_hypotheses,
          dag_id=state.get("dag_id", ""),
          client_id=state.get("client_id", ""),
          failed_task_id=state.get("failed_task_id", ""),
          error_type=state.get("error_type", "unknown"),
          severity=state.get("severity", "P3"),
          exception_message=state.get("exception_message", ""),
          lineage_chain=json.dumps(state.get("lineage_chain", []), indent=2),
          affected_models=json.dumps(state.get("affected_models", []), indent=2),
          dbt_failures=json.dumps(state.get("dbt_failures", [])[:10], indent=2),
          total_runs=total_runs,
          failed_runs=failed_runs,
          failure_rate=failure_rate,
      )

      message = _client.messages.create(
          model=settings.anthropic_model,
          max_tokens=1024,
          system=_SYSTEM_PROMPT,
          messages=[{"role": "user", "content": prompt}],
      )

      raw = message.content[0].text.strip()
      # Strip markdown code fences if Claude wrapped the JSON
      if raw.startswith("```"):
          raw = raw.split("```", 2)[1]
          if raw.startswith("json"):
              raw = raw[4:]
          raw = raw.strip()

      hypotheses: list[Hypothesis] = json.loads(raw)
      for h in hypotheses:
          h.setdefault("verified", False)
          h.setdefault("evidence_query", None)

      return {**state, "hypotheses": hypotheses}

VERIFY

Только безопасные форматы данных для чтения:

_SELECT_ONLY = re.compile(r"^\s*SELECT\b", re.I)
  _CONFIDENCE_THRESHOLD = 0.55

  def _is_safe_query(query: str) -> bool:
      return bool(_SELECT_ONLY.match(query.strip()))

  def verify_node(state: AgentState) -> AgentState:
      hypotheses: list[Hypothesis] = state.get("hypotheses", [])
      updated: list[Hypothesis] = []

      with Session(_sync_engine) as session:
          for h in hypotheses:
              query = h.get("evidence_query")
              if query:
                  evidence = _run_evidence_query(query, session)
                  h = dict(h)
                  h["verified"] = bool(evidence and "error" not in evidence)
              updated.append(h)

      verified_cause, confidence = _pick_verified_cause(updated)
      needs_clarification = confidence < _CONFIDENCE_THRESHOLD
      fix_suggestion = _build_fix_suggestion(verified_cause, state)

      return {
          **state,
          "hypotheses": updated,
          "verified_cause": verified_cause,
          "fix_suggestion": fix_suggestion,
          "needs_clarification": needs_clarification,
      }

Маршрутизация после проверки:

def _route_after_verify(state: AgentState) -> str:
      if state.get("needs_clarification", False):
          return "clarify"
      return "report"

  def build_investigation_graph() -> StateGraph:
      graph = StateGraph(AgentState)
      graph.add_node("triage",      triage_node)
      graph.add_node("traverse",    traverse_node)
      graph.add_node("profile",     profile_node)
      graph.add_node("hypothesize", hypothesize_node)
      graph.add_node("verify",      verify_node_with_mlflow)
      graph.add_node("report",      report_node)
      graph.add_node("clarify",     clarify_node)

      graph.add_edge(START, "triage")
      graph.add_edge("triage",      "traverse")
      graph.add_edge("traverse",    "profile")
      graph.add_edge("profile",     "hypothesize")
      graph.add_edge("hypothesize", "verify")

      graph.add_conditional_edges(
          "verify",
          _route_after_verify,
          {"report": "report", "clarify": "clarify"},
      )

      graph.add_edge("report",  END)
      graph.add_edge("clarify", END)
      return graph.compile()

  investigation_graph = build_investigation_graph()

Отчет

Собирает описательную информацию и данные в формате, понятном машинам, для людей и тикетов.

Уточнение

Прерывает работу, если идентификатор клиента или актива неоднозначен — лучше приостановиться, чем обработать данные неверного пользователя.

Сборка графа

Построение цепочки операций: START → триаж → обработка → анализ профиля → формулировка гипотезы → проверка → (цикл или отчет) → END, причем операция уточнения выполняется в качестве условного отклонения. Используется контрольный указатель для того, чтобы длительные исследования сохранялись при перезапуске процесса.

Бэкенд FastAPI

Реализуются концовки для запуска, возобновления и получения статуса, соответствующие методам invoke / Command(resume=…). Осуществляется аутентификация операторов; критические учетные данные никогда не передаются браузеру в необработанном виде.

Наблюдаемость с помощью MLflow

Записывайте параметры сортировки логов в начале процесса; отслеживайте показатели количества пройденных этапов, счёт гипотез, результаты проверок на успех/неудачу и время выполнения; сохраняйте материалы для отчёта в формате Markdown, JSON с гипотезами и транскрипции данных в формате Cypher.

Панель управления Gradio

Разделите окна на зоны для приёма сигналов тревоги, отображения текущего состояния и вывода окончательного отчёта. Виджеты для возобновления работы должны возвращать ответы в тот же идентификатор потока.

Webhooks

def _fire_webhook(context: dict) -> None:
      ti = context["task_instance"]
      payload = {
          "dag_id":          context["dag"].dag_id,
          "run_id":          context["run_id"],
          "client_id":       context["dag"].dag_id.split("__")[0],
          "task_id":         ti.task_id,
          "execution_date":  context["execution_date"].isoformat(),
          "exception":       str(context.get("exception", "")),
          "log_url":         ti.log_url,
      }
      try:
          resp = requests.post(
              f"{BACKEND_URL}/webhook/airflow",
              json=payload,
              headers={"X-API-Key": API_KEY},
              timeout=10,
          )
          resp.raise_for_status()
          log.info("Webhook fired successfully: %s", resp.json())
      except requests.RequestException as exc:
          log.error("Failed to fire investigation webhook: %s", exc)

Активируйте webhook при завершении формирования отчёта для передачи его в систему управления тикетами, не блокируя путь возврата данных графа; повторные попытки должны выполняться в рабочем процессе webhook, а не на основном узле.

Сам по себе граф без процедуры расследования — это просто визуальная схема. Процедура без графа — это лишь догадки. Вместе с инфраструктурой, настроенной с использованием Terraform, безопасными способами обработки данных, проверками с использованием только оператора SELECT и аудитом в формате MLflow они превращаются в функциональный инструмент для решения инцидентов, а не в простую демонстрационную записку.

Записывайте имена ответственных за принятие решений рядом с узлами и целями webhook.

В циклах с ненадежным кодом предпочитайте использовать только запросы SELECT для проверки.

Создавайте снимки критических инцидентов перед изменением параметров сортировки.

Уведомляйте о циклах с неудачной проверкой так же, как сервисы уведомляют о кодах ошибок 5xx.

С самого начала разделяйте клиентских абонентов с помощью меток в графе.

Документируйте результаты работы Terraform, которые использует фоновый процесс агента.

Указывайте ответственных за принятие решений рядом с узлами и целями webhook.

В циклах с ненадежным кодом предпочитайте использовать только запросы SELECT для проверки.

Создавайте снимки критических инцидентов перед изменением параметров сортировки.

Уведомляйте о циклах с неудачной проверкой так же, как сервисы уведомляют о кодах ошибок 5xx.

С самого начала разделяйте клиентских абонентов с помощью меток в графе.

Документируйте результаты работы Terraform, которые использует фоновый процесс агента.

Указывайте ответственных за принятие решений рядом с узлами и целями webhook.

В циклах с ненадежным кодом предпочитайте использовать только запросы SELECT для проверки.

Сделайте снимок критических инцидентов до изменения параметров триажа.

Уведомляйте при циклах с ошибками проверки так же, как сервисы уведомляют при кодах ошибок 5xx.

С самого начала разделяйте клиентских арендаторов с помощью меток в графе.

Задокументируйте результаты работы Terraform, которые использует фоновый процесс агента.

Укажите ответственных за принятие решений рядом с узлами и целями webhook-сообщений.

В ненадежных циклах предпочитайте запросы проверки, содержащие только оператор SELECT.

Сделайте снимок критических инцидентов до изменения параметров триажа.

Уведомляйте при циклах с ошибками проверки так же, как сервисы уведомляют при кодах ошибок 5xx.

С самого начала разделяйте клиентских арендаторов с помощью меток в графе.

Задокументируйте результаты работы Terraform, которые использует фоновый процесс агента.

Укажите ответственных за принятие решений рядом с узлами и целями webhook-сообщений.

В ненадежных циклах предпочитайте запросы проверки, содержащие только оператор SELECT.

Сделайте снимок критических инцидентов до изменения параметров триажа.

Сигнализируйте о циклах с неудачной верификацией так же, как сервисы сигнализируют о кодах ошибок 5xx.

С самого начала разделяйте клиентских абонентов с помощью меток в графе.

Документируйте результаты работы Terraform, которые использует движок агента.

Указывайте ответственных за принятие решений рядом с узлами и целями webhook-сообщений.

В ненадежных циклах предпочитайте запросы верификации, содержащие только оператор SELECT.

Создавайте снимки критических инцидентов перед изменением параметров сортировки.

Сигнализируйте о циклах с неудачной верификацией так же, как сервисы сигнализируют о кодах ошибок 5xx.

С самого начала разделяйте клиентских абонентов с помощью меток в графе.

Документируйте результаты работы Terraform, которые использует движок агента.

Указывайте ответственных за принятие решений рядом с узлами и целями webhook-сообщений.

В ненадежных циклах предпочитайте запросы верификации, содержащие только оператор SELECT.

Создавайте снимки критических инцидентов перед изменением параметров сортировки.

Сигнализируйте о циклах с неудачной верификацией так же, как сервисы сигнализируют о кодах ошибок 5xx.

С самого начала разделяйте клиентских арендаторов с помощью меток графа.

Документируйте результаты работы Terraform, которые использует движок агента.

Указывайте ответственных за принятие решений рядом с узлами и целями webhook-сообщений.

В ненадежных циклах предпочитайте запросы для проверки, содержащие только оператор SELECT.

Создавайте снимки состояния при критических инцидентах перед изменением параметров сортировки.

Уведомляйте о циклах с ошибками проверки так же, как сервисы уведомляют о кодах ошибок 5xx.

С самого начала разделяйте клиентских арендаторов с помощью меток графа.

Документируйте результаты работы Terraform, которые использует движок агента.

Рядом с каждым изменением в графе или агенте указывайте ответственных, необходимые настройки и примечания по откату, чтобы демонстрации не опережали уровень работоспособности.

Рядом с каждым изменением в графе или агенте указывайте ответственных, необходимые настройки и примечания по откату, чтобы демонстрации не опережали уровень работоспособности.

Рядом с каждым изменением в графе или агенте указывайте ответственных, необходимые настройки и примечания по откату, чтобы демонстрации не опережали уровень работоспособности.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, настройках и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, конфигурациях и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, конфигурациях и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.

Храните информацию об ответственных лицах, конфигурациях и записях о возврате к предыдущему состоянию рядом с каждой диаграммой или изменением агента, чтобы демонстрации не превосходили возможности системы.