TL;DR
TG-CI (Task-Graph Contextual Integrity) — это метод защиты данных в мультиагентных системах, который перед выдачей любого факта из общей памяти оценивает не только агента-получателя, но и весь дальнейший маршрут этого факта по графу задач (MATG) с учётом того, что каждый из последующих агентов уже знает. Управление строится в двух режимах: Full-Scope (полная блокировка на входе, если хотя бы одному агенту внизу по цепочке эти данные видеть нельзя) и Auto-Region (выдача данных только на «безопасный участок» маршрута с автоматической установкой пограничных фильтров на рёбрах графа, где полномочия заканчиваются).
В обычных мультиагентных пайплайнах безопасность проверяют локально на текущем шаге: «можно ли агенту-планировщику прочитать карточку клиента из памяти прямо сейчас?». Для планировщика доступ законен, и фильтр пропускает данные. Но дальше срабатывают две скрытые ловушки: транзитивная утечка (планировщик пересылает свой черновик агенту отправки уведомлений или внешнему подрядчику, которому эти детали видеть категорически нельзя) и накопительная утечка (безобидный сам по себе кусок данных складывается у получателя с прошлыми сообщениями и вскрывает коммерческую или медицинскую тайну).
TG-CI решает проблему за счёт упреждающего расчёта зоны допуска до начала пересылки. Контроллер разбивает ответ из памяти на отдельные смысловые факты, сверяет каждый факт с историей знаний и ролями всех агентов вниз по графу, а в режиме Auto-Region позволяет ближайшим агентам спокойно работать с данными без повторных вызовов LLM-судьи на каждом шаге, автоматически вырезая секреты только на «границе дозволенного» (frontier gate).
Схема метода
ШАГ 1 (Декомпозиция памяти): Запрос агента r0 к памяти → разбивка ответа на отдельные факты m_i = <субъект, атрибут, значение>
ШАГ 2 (Прогноз по графу задач MATG): Для каждого факта m_i проверка всех рёбер дальнейшего маршрута с учётом истории знаний D_t(v) каждого агента v
ШАГ 3 (Выбор режима допуска):
├── Режим Full-Scope: Если хотя бы одно ребро ниже по графу нарушает правила → БЛОКИРОВКА m_i ещё на выходе из памяти
└── Режим Auto-Region: Вычисление максимальной допустимой зоны P* вокруг r0 → ВЫДАЧА m_i + установка фильтра на граничных рёбрах ∂P*
ШАГ 4 (Передача сообщений внутри графа):
├── Внутри зоны P*: сообщения между агентами идут напрямую без проверок и траты токенов
└── На границе ∂P* (Frontier Gate): при переходе в недопустимую зону фильтр вырезает факт m_i из текста сообщения (или блокирует отправку, если вырезать безопасно нельзя)
В эталонной реализации авторов метод работает как программная обвязка (контроллер памяти и шлюз сообщений) вокруг мультиагентного графа (LangChain + Mem0), но сама логика проверки маршрута и пограничной очистки также переносится в инструкции агента-оркестратора и системного судьи.
Пример применения
Задача: В крупной российской клинике (или HR-платформе уровня «Поток» / Huntflow) работает цепочка из четырёх ИИ-агентов для обработки обращений сотрудников: Агент-Триаж (читает медкарту и историю больничных из общей памяти) → Агент-График (согласует слот приёма и перенос смен) → Агент-Бухгалтерия (считает выплаты по ДМС) → Агент-Уведомления (шлёт сообщение в корпоративный мессенджер Пачка / Telegram руководителю отдела и внешнему провайдеру пропуска). Нужно не допустить, чтобы диагноз сотрудника утек к руководителю через цепочку пересылок или вычислился по косвенным признакам.
Промпт:
Ты — Контроллер Контекстной Целостности Графа Задач (TG-CI Judge) для мультиагентного пайплайна.
Узлы и текущие подзадачи τ(v):
1. Agent_Triage: первичный разбор заявки сотрудника и подбор профильного врача.
2. Agent_Schedule: бронирование окна в расписании и проверка пересечений со сменами.
3. Agent_Billing: проверка лимита ДМС по коду услуги.
4. Agent_Notify: отправка уведомления руководителю отдела в мессенджер Пачка и заказ гостевого пропуска.
Маршрут передачи данных (рёбра E):
Memory -> Agent_Triage -> Agent_Schedule -> Agent_Notify
Agent_Triage -> Agent_Billing -> Agent_Notify
История уже известных агентам фактов D_t(v):
- Agent_Schedule уже знает: {"сотрудник": "Иванов И.", "отдел": "Разработка", "врач": "Хирург-онколог каб. 402"}.
- Agent_Notify уже знает: {"сотрудник": "Иванов И.", "получатель_чата": "Тимлид отдела разработки"}.
Из памяти запрошены записи по сотруднику "Иванов И.":
- m1: <Иванов И., клинический_диагноз, "Подозрение на новообразование щитовидной железы (C73)">
- m2: <Иванов И., длительность_приёма_минут, "45">
- m3: <Иванов И., результат_биопсии_код, "Требуется повторная пункция в стационаре">
- m4: <Иванов И., номер_полиса_ДМС, "СОГАЗ-778899">
Для каждого элемента памяти m1..m4 выполни проверку TG-CI перед выдачей его агенту Agent_Triage:
1. Прогони каждый элемент по ВСЕМУ дальнейшему маршруту в графе (прямая передача + накопление с D_t(v) + транзитивная пересылка до конечных узлов).
2. Определи три вида рисков:
- Прямое нарушение (нужен ли факт самому Agent_Triage для его подзадачи?).
- Накопительное нарушение (не вскроет ли этот факт тайну в сумме с тем, что уже лежит в D_t(v) у получателя?).
- Транзитивное нарушение (какому узлу дальше по цепочке этот факт передавать запрещено?).
3. Выдай решение в режиме **Auto-Region**:
- Укажи разрешённую зону распространения P* (список агентов, которым можно видеть факт).
- Укажи точные пограничные рёбра ∂P* (Frontier Gates), на которых шлюз обязан вырезать этот факт перед передачей сообщения следующему агенту.
- Обнови состояние знаний D_{t+1}(v) для узлов внутри P*.
Результат:
Модель-контроллер разберёт каждый факт отдельно: m2 (длительность 45 минут) получит полный допуск по цепочке записи; m4 (номер полиса) будет ограничен веткой Agent_Triage -> Agent_Billing с установкой пограничного фильтра на ребре Agent_Billing -> Agent_Notify; а для m1 и m3 контроллер заметит как транзитивный риск (уход медицинских данных в Agent_Notify к тимлиду), так и накопительный риск (у Agent_Schedule уже есть специальность врача в D_t, и добавление m3 однозначно раскроет диагноз), поэтому ограничит зону допуска только узлом Agent_Triage и выставит жёсткое правило очистки на рёбрах Agent_Triage -> Agent_Schedule и Agent_Triage -> Agent_Billing.
Почему это работает
В мультиагентных системах главная дыра безопасности возникает на стыке правильных локальных решений. Когда судья оценивает один изолированный шаг («агент А просит запись из памяти для своей задачи»), он не видит, куда агент А перешлёт свой ответ через два шага и какие куски мозаики уже скопились у агента Б. Более того, если пытаться проверять LLM-судьёй вообще каждое сообщение между агентами на лету (Online Atomic CI), система всё равно пропускает транзитивные утечки, а расход токенов взлетает до небес.
Сильная сторона графового планирования в том, что структура маршрута задач известна заранее. Если перед выдачей данных из памяти посмотреть на весь подграф получателей сразу, можно заранее увидеть, на каком именно переходе полезный рабочий факт превращается в утечку конфиденциальных данных.
Режим Auto-Region использует эту механику максимально экономно. Вместо того чтобы запрещать выдачу данных первому агенту из-за того, что где-то в конце цепочки стоит ненадёжный агент уведомлений (как делает жёсткий режим Full-Scope), система очерчивает вокруг первого агента «чистую зону» и ставит фильтр только на внешних границах этой зоны. Внутри чистой зоны агенты общаются свободно и без задержек, а при пересечении границы пограничный шлюз прицельно вырезает из текста только запрещённые факты из чёрного списка этого ребра.
Рычаги управления:
- Выбор между Full-Scope и Auto-Region → включай Full-Scope для критических секретов (ключи, персональные медицинские диагнозы, суммы сделок M&A), где малейший риск попадания факта в цепочку с внешним агентом недопустим; включай Auto-Region, когда важно сохранить высокую точность решения задачи и не блокировать работу первых агентов.
- Гранулярность памяти (<субъект, атрибут, значение>) → чем мельче нарезаны записи при чтении из памяти, тем точнее система отсекает только токсичные поля, оставляя агентам нужные для работы метаданные.
- Устройство пограничного фильтра → в коде его можно сделать на дешёвых локальных моделях (авторы использовали связку MiniLM + DeBERTa без траты токенов платного API), а в прототипе без кода — поручить очистку текста отдельному системному промпту на переходе между субагентами.
Шаблон промпта
Агенты и их подзадачи:
{список_агентов_и_подзадач}
Направленные рёбра передачи данных (кто кому передаёт результат):
{ребра_графа}
Текущая история раскрытия по агентам D_t(v) (что каждый агент уже знает к этому шагу):
{история_знаний_агентов}
Запрошенные элементы данных:
{список_элементов_памяти}
Выполни проверку TG-CI для каждого элемента данных:
1. Разбей данные на атомарные элементы mi = <субъект, атрибут, значение>.
2. Проверь допустимость передачи каждого элемента по всем достижимым рёбрам вниз по графу от {агент_отправитель_запроса} с учётом:
- Прямой уместности для подзадачи получателя;
- Кумулятивного эффекта в сочетании с текущей историей D_t(v) и другими одобренными элементами этого же пакета;
- Транзитивной передачи следующим узлам.
3. Если выбран режим Full-Scope: верни RELEASE только если элемент допустим на ВСЕХ рёбрах ниже по графу, иначе BLOCK.
4. Если выбран режим Auto-Region: построй максимальную связную допустимую зону P* от {агент_отправитель_запроса}, верни список узлов P* и список пограничных рёбер ∂P* с правилом фильтрации (какие именно утверждения нужно вырезать при передаче через ребро u -> v).
Что подставлять в плейсхолдеры:
- {список_агентов_и_подзадач} — имена субагентов и конкретная роль каждого в текущем запуске.
- {ребра_графа} — маршрут движения данных (например, Агент_А -> Агент_Б -> Агент_В).
- {история_знаний_агентов} — краткая сводка чувствительных фактов, которые уже были переданы каждому агенту на прошлых шагах.
- {агент_отправитель_запроса} — узел, который сейчас запрашивает данные из памяти или базы знаний.
- {список_элементов_памяти} — найденные в памяти записи или поля документа.
- {режим_FullScope_или_AutoRegion} — Full-Scope (строгая блокировка на входе) или Auto-Region (локальный допуск с очисткой на границах зоны).
🚀 Быстрый старт — вставь в чат:
Вот шаблон TG-CI (Task-Graph Contextual Integrity). Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какие субагенты участвуют в вашей цепочке, кто кому передаёт данные и какие типы клиентских или внутренних сведений нужно защитить от утечки — потому что без карты маршрута и ролей невозможно рассчитать границы допустимой зоны. Она возьмёт паттерн из шаблона и адаптирует под задачу.
Ограничения
⚠️ Нужен заранее известный граф маршрута: Метод предполагает, что схема передачи задач между агентами (MATG) зафиксирована на время выполнения задачи. Если агенты динамически на лету придумывают новые маршруты и вызывают случайных субагентов, границы зон придётся пересчитывать.
⚠️ Требует системного посредника при работе со взломанными агентами: Если один из агентов в цепочке скомпрометирован (например, через промпт-инъекцию), просто попросить его в инструкции «не пересылай секреты дальше» недостаточно — пограничный фильтр (
Frontier Gate) должен работать как внешний перехватчик сообщений между агентами.
⚠️ Увеличение расхода токенов судьи: Предварительная проверка элемента по всему дереву последующих агентов обходится примерно втрое дороже по токенам судьи, чем простая локальная проверка одного шага (около 133–144 тыс. токенов на сценарий против ~44 тыс. у локального фильтра).
Как исследовали
Исследователи из Токийского института науки (Institute of Science Tokyo) заметили, что существующие системы защиты памяти ИИ-агентов проверяют безопасность только в точке выдачи («можно ли отдать этот факт текущему агенту»), полностью игнорируя то, куда этот факт поползёт дальше по цепочке делегирования. Чтобы проверить масштаб бедствия в управляемых условиях, они собрали бенчмарк MAPLE-Bench из 144 сценариев в четырёх сферах — медицина, финансы, HR и личные сервисы. В каждом кейсе работала система из 4 агентов (на базе LangChain и памяти Mem0) с тремя вариантами топологии графа (цепочка, дерево, ветвление), где 1 или 2 агента были намеренно скомпрометированы, а в памяти лежало 30 фактов (7 нужных для решения тестовых вопросов и 23 отвлекающих). Проверяли три связки моделей на базе GPT-5.6 Luna и Claude Haiku 4.5.
Результаты наглядно показали, почему обычные фильтры дырявые. Без защиты агенты допускали в среднем 15,84 незаконного раскрытия за прогон, причём главным источником проблем были именно транзитивные утечки вниз по цепочке. Стандартный локальный фильтр с памятью истории (Local-History CI) снижал число утечек лишь до 10,47, а пошаговая проверка каждого сообщения на лету (Online Atomic CI) — до 6,11, всё равно пропуская массу транзитивных сливов.
Внедрение TG-CI обрушило число утечек на порядок: до 1,49 в режиме Auto-Region и до 0,62 в режиме Full-Scope (снижение на 85,8–94,1% относительно Local-History CI!), сохранив при этом 93,6–96,1% точности решения самих рабочих задач. При этом режим Auto-Region показал себя золотой серединой для практики: за счёт того, что он не блокирует данные на самом входе из-за далёкого несовместимого узла, а ставит точечный фильтр на границе разрешённой зоны (где отсевом занимались лёгкие локальные модели MiniLM и DeBERTa), он сохранял более высокую полезность ответов и тратил на 7,8% меньше токенов LLM-судьи, чем жёсткий Full-Scope.
Адаптации и экстраполяции
💡 Адаптация для оркестратора субагентов (Claude Code / кастомные пайплайны без внешнего кода):
Если у вас нет собственного сервера-перехватчика на LangChain, но главный агент-оркестратор сам вызывает субагентов и передаёт им контекст, вшейте правило пограничной фильтрации (Frontier Gate) прямо в системный промпт оркестратора:
Перед тем как передать контекст из памяти субагенту, посмотри на всю цепочку следующих вызовов. Раздели данные на две корзины: 1. [Full-Chain Safe] — данные, которые можно видеть всем последующим субагентам, включая финальный вывод. 2. [Local-Only] — данные, нужные только текущему субагенту. Передавай их с пометкой НЕ ВКЛЮЧАТЬ В ОТЧЁТ и перед вызовом следующего субагента в цепочке удаляй их из передаваемого саммари.
🔧 Техника: Транзакционный черновик памяти (Transaction-Local State) → защита от утечки через комбинацию фактов в одном ответе
Часто один запрос к базе знаний возвращает сразу 5–10 записей, которые по отдельности безобидны, но вместе выдают секрет. Авторы решают это простым приёмом: когда судья проверяет список из $n$ найденных фактов, каждый одобренный факт $m_1$ сразу же виртуально добавляется в историю знаний получателя перед проверкой следующего факта $m_2$ из того же пакета. Добавьте в промпт судьи строчку: «Оценивай каждый следующий пункт выдачи так, будто все предыдущие одобренные пункты из этого же ответа уже известны получателю и всем агентам в его зоне допуска».
Ресурсы
Исследование: Judging Before Propagation: Task-Graph Contextual Integrity for Multi-Agent Privacy (arXiv:2610.39532)
Авторы: Hengyu Wu, Blaise Delattre, Yang Cao
Университет: Institute of Science Tokyo (Япония)
