Граф вместо цепочки: почему AI-агент упирается не в модель, а в форму работы
Пять агентов — это количество. Граф — это форма. Разбираем, как перестать выстраивать шаги в очередь: узлы и рёбра, сплиттер, изоляция контекста, верификаторы на ребре, гейт по цене ошибки и память о том, почему решение было принято.
Почти любая многошаговая AI-автоматизация, которую я открываю, устроена одинаково: шаг первый, шаг второй, шаг третий — каждый вежливо ждёт предыдущий. И если присмотреться, примерно половине этих шагов ждать было нечего.
Они не ветвятся. Не разделяют работу. Не запускают ничего параллельно. Просто стоят в очереди — одна голова, один контекст, одно дело за раз, пока окно не заполнится и агент тихо не забудет, с чего начинал.
Дальше происходит предсказуемое: владелец процесса решает, что виновата модель, и идёт покупать модель подороже. Не помогает. Потолок был не в модели.
Потолок — в форме работы, которую вы ей нарисовали.
Базовую механику — что такое узел и ребро, почему половина стрелок в вашей схеме фиктивные и как собрать первый «ромб» — я разбирал в инженерии графов. Здесь идём на уровень глубже: как режется работа, кто кому даёт разрешение, что возвращается назад и во что всё это обходится.
Пять слоёв, а говорят обычно про два
Промпт — это фраза. Контекст — то, что модель видит. Харнесс — пол, на котором агент стоит: цикл, инструменты, права, память, условие остановки. Агенты — те, кто делает работу. А форма самой работы — что идёт до чего, что может идти одновременно, что действительно обязано ждать всех — это граф.
flowchart LR
P["Промпт<br/>одна формулировка"] --> C["Контекст<br/>что видно модели"]
C --> H["Харнесс<br/>цикл, инструменты,<br/>права, память"]
H --> A["Агенты<br/>кто выполняет"]
A --> G["Граф<br/>форма всей работы"]
Последние два года индустрия шлифовала первые два слоя и почти не трогала последний. Отсюда и ощущение «модели умные, а толку мало».
Здесь же прячется различие, которое переворачивает картину: модель — это не агент. Одну и ту же модель можно посадить в вашу базу и получить уверенную чушь, сломанные проверки и потерю задачи к сороковому шагу. А можно обернуть в правильные леса — и получить работу с логом того, что пробовали, что откатили и почему.
Модель одна. Результат разный. Разница — в харнессе и в форме.
Показательно, что разработчики моделей всё чаще пишут это прямо в документации: харнесс — часть продукта, модель проектировалась под жизнь внутри него. Вам продают не «мозг», а мозг вместе с лесами вокруг него.
Узел и ребро: словарь на два слова
В графе ровно две сущности, и путаница почти всегда именно в них.
Узел — единица работы. Один агент, одна ограниченная задача, один вход, один выход.
Ребро — зависимость. Выход этого узла является входом того. Всё, определение закончилось.
Ошибка, которую совершают практически все: «а потом» принимают за ребро. «Суммируй документ, а потом проверь остатки на складе» — здесь нет ни одного ребра. Остатки не потребляют саммари. Это две независимые задачи, которые линейный сценарий склеил в очередь только потому, что вы их в таком порядке напечатали.
Отсюда простая проверка, которую стоит прогнать по каждой стрелке в уже работающем процессе:
Читает ли следующий шаг результат предыдущего? Если вы не можете назвать данные, которые пересекают границу, — ребра нет, а ожидание есть.
В типичной цепочке таких стрелок находится две-три. Их удаление обычно даёт самое большое ускорение из доступных — и стоит ноль рублей.
flowchart LR
A1["Собрать заявки<br/>за неделю"] --> A2["Проверить<br/>конкурентов"]
A2 --> A3["Посчитать<br/>юнит-экономику"]
A3 --> A4["Свести<br/>отчёт"]
Вот та же работа после проверки на настоящие рёбра. Конкуренты не читают заявки. Юнит-экономика не читает конкурентов. Ждал их всех только отчёт.
flowchart TD
S["Сплиттер:<br/>режет задачу на полосы"] --> B1["Заявки"]
S --> B2["Конкуренты"]
S --> B3["Юнит-экономика"]
B1 & B2 & B3 --> M["Слияние:<br/>обычный код, не модель"]
M --> R["Отчёт"]
Разница не косметическая. Линейный процесс из сорока однотипных проверок по восемь секунд каждая — это больше пяти минут. Те же сорок проверок, разложенные по полосам, ограничены самой медленной из них.
Количество агентов — это не покрытие
Здесь начинается самая дорогая иллюзия. «Запустим пять агентов вместо одного» звучит как ответ, но отвечает на другой вопрос.
Пять агентов — это количество. Граф — это форма. Ответ меняет только вторая.
Направьте пять агентов на одну кучу с одним и тем же окном контекста — и они сойдутся. Первый напишет вывод, остальные его прочитают, и все пять отчётов будут центрированы вокруг одного и того же. Вы заплатили пять раз за одно мнение и четыре эха.
- Количество покупает пропускную способность: пять дел вместо одного.
- Форма покупает покрытие: пять разных дел вместо одного и того же пять раз.
Нужны обе вещи. Вторую почти никто не проектирует.
Сплиттер решает больше, чем все остальные узлы
Узел, который режет работу на полосы, стоит в начале — и определяет качество всего, что случится дальше. Разрежете не по той оси — и вся мощность внизу уйдёт впустую.
Классический пример из аудита кода: разрежьте репозиторий по папкам — и четыре агента будут проверять одни и те же три файла. Разрежьте по цене ошибки — и каждый увидит то, чего не видят остальные.
Бизнес-аналог такой же. Разрежете анализ клиентской базы по алфавиту — получите четыре одинаковых отчёта. Разрежете по причине ухода, по каналу привлечения, по сумме чека, по стадии сделки — четыре разных.

И вторая половина того же механизма: раздельный контекст — это не приятная мелочь, это и есть механизм.
Если два агента должны произвести разное, они не должны делить окно. Если они должны произвести одно и то же — вам не нужны были два агента.
Четыре типа узлов, и один из них — не модель
Словарь целиком: сплиттер, воркер, код-узел, гейт.
Сплиттер режет работу на единицы. Воркер делает одну единицу, одной линзой, в своём контексте. Гейт решает, пропускать ли результат дальше.
А код-узел — тот, о существовании которого забывают. Слияние, ранжирование, дедупликация, сравнение «было — стало», отсев пустых ответов. Ничего из этого не является рассуждением: у каждой операции ровно один правильный ответ, каждая — несколько строк обычного кода. Прогон её через модель добавляет стоимость, задержку и разброс к шагу, у которого ничего этого не было.
Если преобразование можно описать, не используя слова «оцени», «реши», «выбери» или «сформулируй», — это код, а не агент.
Граф, где каждое ребро — агент, платит аренду за собственную проводку. И платит токенами.
Ромб: разделить, сделать, слить
Соедините разветвление и слияние — получите форму, на которой держится большинство серьёзных процессов.
flowchart TD
IN["Задача"] --> SP["Сплиттер"]
SP --> W1["Полоса 1"]
SP --> W2["Полоса 2"]
SP --> W3["Полоса 3"]
W1 & W2 & W3 --> RED["Свод: код<br/>дедуп, ранжирование"]
RED --> SYN["Синтез:<br/>агент пишет ответ"]
SYN --> OUT["Результат"]
Канонический порядок стоит запомнить: разветвить → свести кодом → синтезировать агентом. Разветвление даёт широту, код её сжимает, финальный агент пишет ответ.
Как только вы видите ромб, вопрос «как заставить агента делать больше шагов» заменяется на «где здесь разрез и где слияние». Второй вопрос — тот, который масштабируется.
Барьер против конвейера: где утекает время
Самая частая техническая ошибка при переходе к графам — синхронизировать то, что синхронизировать не нужно.
Барьер — точка, где все ждут всех. Он оправдан ровно тогда, когда следующему шагу действительно нужен весь набор сразу: дедуп по всем источникам, ранняя остановка, если все полосы пустые, сравнение находки со всеми остальными.
Конвейер — когда каждый элемент проходит все стадии сам по себе. Элемент А может быть уже на третьей стадии, пока Б всё ещё на первой.
Проверка на лишний барьер простая до неприличия: если у вас «разветвили → преобразовали → снова разветвили», а в среднем преобразовании нет зависимости между элементами — барьер там не нужен. «Так чище читается» и «стадии концептуально разные» не аргументы: раздельно — не то же самое, что синхронно.
Верификатор на ребре
Главный выигрыш графа — не в том, что агентов стало больше. В том, что вокруг них можно построить структуру, дающую уверенность.
Верификатор — узел, который стоит на ребре до того, как результат попадёт дальше, и его единственная задача — попытаться убить находку. Выжила — проходит. Нет — не доходит до вашего отчёта.
Три рабочих шаблона:
- Состязательная проверка. На каждую находку — несколько независимых скептиков, которым поручено её опровергнуть. Оставляем то, что пережило большинство.
- Проверка разными линзами. Каждому проверяющему — своя оптика: корректность, безопасность, воспроизводимость, стоимость. Разнообразие ловит то, чего пять одинаковых проверок не поймают никогда.
- Судейская панель. Несколько попыток с разных углов, параллельные судьи, синтез из победителя с пересадкой лучших кусков от остальных.
Ключевая деталь, которую легко потерять: агент, проверяющий собственную работу, к себе снисходителен — ровно как вы не видите своих опечаток. Отдельный проверяющий, который работу не делал, ловит принципиально другой класс ошибок. Это структурное изменение, а не косметическое.
Об этом же — двадцать loop-паттернов, которые отличают систему от одноразового агента: там подробно про цикл внутри узла.
Где живёт цикл, а где граф
Одна фраза снимает всю путаницу: цикл живёт внутри узла, граф — между узлами.
Внутри единицы работы: сделать → проверить → исправить → повторять до зелёного. Между единицами: разрезать, разветвить, слить, пропустить через гейт, отправить назад.
Ничего из второго списка невозможно выразить изнутри одной единицы. Поэтому выбирать не приходится: граф без циклов в узлах производит непроверенную работу параллельно — что хуже, чем последовательно, потому что её больше. Цикл без графа вокруг — один очень хороший шаг в очереди, которую никто не проектировал.
И отдельно про сам цикл: цикл — это проверка, которая может провалить работу. Если ничто не способно завалить результат, пока вас нет в комнате, у вас не цикл, а планировщик. Условие пишется первым и так, чтобы его мог вычислить код: «тесты зелёные», «сумма сходится с выгрузкой», «во всех карточках заполнено поле», а не «выглядит хорошо».
Отсутствие ошибки — не доказательство правильности. Постройте цикл на этом — получите систему, которая уверенно повторяет одну и ту же ошибку до конца бюджета, с чистым логом всю дорогу.
Если выбираете, с какой формы начать — одного агента в цикле, цепочки, маршрутизации или графа с параллельными ветками, — посмотрите лестницу из шести паттернов оркестрации и признаки, по которым стоит подниматься на ступень выше.
Возвращать единицу, а не партию
Самая дорогая ошибка на обратном пути — и её стоит проговорить отдельно.
Четыре куска работы сделаны. Один провалил проверку. Если назад уезжает вся партия, три корректных куска переписываются заново. Их новая версия не лучше — она просто другая. Теперь проверять надо снова все четыре, и любой из трёх может упасть уже по своей причине.
Один провал превратился в четыре неопределённых исхода — за ваши деньги. Повторите дважды за прогон, и процесс перестанет сходиться вообще.
Снаружи это выглядит как «модель тупит». На деле это обратный путь, уничтожающий корректную работу.
flowchart TD
G{"Гейт"} -- "провал в куске 3" --> R["Возврат:<br/>только кусок 3"]
R --> W3["Тот же воркер,<br/>что делал кусок 3"]
W3 --> G
G -- "остальные приняты" --> OK["Идут дальше<br/>без переделки"]
R -.- N["С возвратом едет:<br/>что именно сломалось ·<br/>чем проверялось ·<br/>рамка правки ·<br/>номер попытки"]
Строчка про рамку правки важнее, чем кажется. Без неё возвращённая единица разрастается: агент открывает файл, замечает рядом ещё две проблемы, чинит и их — и правка одного куска превращается в изменение на четыре файла, которое никто не смотрел.
Ограничение на три попытки — разумный дефолт. Если единица не проходит три коррекции, проблема в плане, который её породил, а плана цикл не видит.
Гейт открывается по цене ошибки, а не по уверенности
Стандартный подход — посчитать оценку уверенности, задать порог, пропускать всё выше него. Это неверная переменная.
Уверенность — самый слабый вход в этом решении по простой причине: это единственная переменная, на которую модель может повлиять.
Сильная переменная — что произойдёт, если решение окажется неверным. Сортируйте работу по стоимости отката:
| Полоса | Что туда попадает | Когда открывается |
|---|---|---|
| Обратимо и локально | Текст на странице, черновик письма, изолированный кусок с тестами | Первой: цена ошибки — один откат |
| Обратимо, но широко | Общий шаблон, новое поле в схеме, то, чем пользуются все | По детерминированным проверкам плюс чистая траектория прогона |
| Необратимо | Миграции, удаление данных, отправка клиентам, движение денег | Не открывается — независимо от оценки |
Третья строка — это не «очень высокий порог». Это полоса, которая не открывается. Разница принципиальная: пороги со временем подкручивают, закрытые полосы — нет.
Внутри открытой полосы гейт читает свидетельства по порядку: сначала детерминированные результаты, затем траектория этого прогона, затем история откатов по этому узлу, и только последним — самооценку модели.

Второе обратное ребро, которое почти никто не строит
Граф без обратного пути — это конвейер. Он производит результат и забывает. Через неделю стартует из той же точки с теми же слепыми зонами.
У работающих систем обратных путей два, и делают они разное:
- Ребро коррекции — короткое. Гейт отправляет единицу назад тому, кто её сделал. Чинит текущий прогон.
- Ребро обучения — длинное. Принятый результат возвращается к сплиттеру в виде ограничения. Чинит все последующие прогоны.
Первое строят почти все. Второе — почти никто. Признак: система быстрая, но год за годом не становится умнее.
Важно, куда именно приземляется ребро обучения. Не в инструкцию воркера, а в бриф, по которому режется работа. Подтверждённая причина становится правилом, и следующая поломка стартует там, где закончилась эта.
flowchart LR
SP["Сплиттер<br/>+ накопленные ограничения"] --> W["Воркеры"]
W --> G{"Гейт"}
G -- "не прошло" --> W
G -- "принято" --> OUT["Результат"]
OUT -. "правило, а не текст результата" .-> SP
Память о том, почему
Самый интересный разворот темы — граф не как порядок исполнения, а как память о причинах.
В одном опубликованном разборе схема выглядит так: шесть узлов действуют, седьмой помнит, зачем действовали. Каждый шаг несёт с собой предположение, которое делает его корректным. Отдельный узел-реестр хранит решения вместе с предположениями. Когда предположение оказывается ложным, пересчитывается не всё подряд, а только то, что на нём стояло.
flowchart TD
I["ЦЕЛЬ<br/>зачем задача. Никогда — как"] --> D["РАЗБОР<br/>шаги, у каждого —<br/>явное предположение"]
D --> W["ИСПОЛНИТЕЛЬ<br/>делает один шаг,<br/>больше не видит ничего"]
W --> A["АУДИТ<br/>сверяет с предположением,<br/>а не с целью"]
A --> DR["ДРЕЙФ<br/>сравнивает шаг с ЦЕЛЬЮ,<br/>отмечает расхождение"]
DR --> L["РЕЕСТР<br/>решение + предположение,<br/>которое его оправдало"]
L --> RT["КОРЕНЬ<br/>предположение сломалось →<br/>пересчитать только зависимое"]
RT -.-> D
Цифры из того же разбора: месяц прогонов, 4100 шагов, 380 из них построены на предположении, которое стало ложным на третий день. Прежний процесс выпустил все 380 и не связал их ни с чем.
Для бизнеса это переводится буквально. Отдел месяц строил кампании на гипотезе «основной трафик приходит с мобильных из поиска». Гипотеза оказалась неверной на третий день. Вопрос не в том, что делать с гипотезой, — вопрос в том, какие из шестидесяти уже принятых решений на ней стояли. Без реестра ответа нет: либо переделывать всё, либо жить с этим.

Что это стоит
Честная часть разговора. Форма — не бесплатный обед.
Мультиагентная схема может съедать до пятнадцати раз больше суммарных токенов, чем один диалог: каждая полоса заново подгружает своё ядро контекста. Вы меняете суммарные токены на чистое главное окно и на покрытие. Обычно это правильный размен — но это размен, а не подарок.
Лечится это не отказом от графа, а распределением моделей по узлам. Скучные узлы — «извлеки поле», «классифицируй обращение», «приведи к формату» — уходят на дешёвую модель. Дорогие токены остаются там, где живёт суждение: синтез, разбор спорной находки, финальный вердикт. Форма графа при этом не меняется вообще — меняется счёт. Подробности расчёта — в учёте расходов на AI.
Второе, что стоит знать до масштабирования: упавшая полоса не роняет партию — она возвращает пустоту. Это и есть локализация отказа, ровно так и задумано. Но следствие неприятное: слияние тихо получает укороченный список.
- Отсеивайте пустые ответы до слияния, иначе одна мёртвая полоса отравит весь результат.
- Никогда не адресуйте результаты слияния по позиции: восемь удачных полос и одна упавшая сдвинут всё на единицу, молча.
- На слиянии сверяйте количество пришедших результатов с ожидаемым и явно помечайте разрыв.
Пропустите это — и прогон будет выглядеть успешным. Просто в отчёте не будет одной полосы, и ничего нигде не упадёт.
Три места, где графы ломаются предсказуемо
Схлопывание контекста. Разветвили на двести полос и пытаетесь скормить двести выходов одному финальному узлу — окно кончится раньше синтеза. Лечение: слоёное слияние. Группы по 20–50, саммари каждой группы, потом сводим саммари, а не сырьё.
Ложная независимость. Два узла кажутся независимыми, потому что их формулировки не ссылаются друг на друга. А пишут они в один файл или дёргают один сервис с лимитом запросов. Это скрытое ребро. Аудируйте не только общие данные, но и общие ресурсы.
Тихий отказ узла. В цепочке падение останавливает всё — неприятно, зато заметно. В графе одна упавшая полоса из двухсот исчезает в отчёте, который выглядит целым.
Не путайте с графовыми базами
Слово «граф» сейчас живёт в двух разных мирах, и их постоянно смешивают.
Есть графовые базы данных и графы знаний — Neo4j, Cypher, Graph RAG: способ хранить связанные данные и рассуждать по связям вместо плоского поиска по похожести. Полезная вещь, особенно там, где нужны многошаговые ответы и объяснимость.
А есть граф как форма работы агентов — то, о чём весь этот текст. Здесь узел — не запись в базе, а единица работы; ребро — не отношение между сущностями, а зависимость по данным между шагами.
Пересечение есть: граф знаний может быть источником, из которого сплиттер берёт разрезы. Но это разные дисциплины, и «мы внедрили графовую базу» никак не решает проблему очереди из шагов.
С чего начать на своей работе
Возьмите один процесс, который вы повторяете. Не самый сложный — самый частый.
- Нарисуйте текущую цепочку и прогоните по каждой стрелке вопрос: следующий шаг читает результат предыдущего? Назовите данные, которые пересекают границу. Не назвали — стрелку убираем.
- Постройте гейт первым. Не воркеров. Пока ничто не может громко провалить работу, граф — просто более быстрый способ производить непроверенное.
- Определите разрез. По какой оси режем работу, чтобы полосы видели разное, а не одно и то же.
- Раздайте полосам отдельный контекст. Общее окно — это сходимость, то есть одно мнение и эхо.
- Слияние сделайте кодом. Дедуп, сортировка, отсев пустых — это не работа для модели.
- Поставьте человека на один шаг — в точке наибольшей необратимости. Утверждайте слияние и то, что уходит наружу. Не промежуточные результаты и не каждый шаг: человек посреди графа становится самым медленным узлом, и вся система идёт со скоростью чтения.
- Добавьте ребро обучения последним — раньше просто нечего накапливать.
По ходу пригодятся соседние темы: память агента — для реестра решений, шаблон правил проекта — для того самого брифа, куда приземляется ребро обучения, и команды агентов — если полос становится много.
Что здесь на самом деле важно
Если унести из текста три вещи, пусть это будут эти.
Режьте стрелки, по которым не течёт ни байта. Самое дешёвое ускорение из существующих.
Стройте проверку до того, как строите объём. Непроверенная работа, произведённая в пять потоков, — это в пять раз больше непроверенной работы.
Любой провал, который вы не превратили в постоянное ограничение, вы встретите снова. Обязательно.
Потолок вашей автоматизации почти никогда не в модели. Он в форме работы, которую вы ей отдали. Цепочка заставляет один контекст держать всё, один отказ останавливать всё и каждый быстрый шаг стоять за самым медленным. Граф размазывает контекст по полосам, локализует отказ в узле и даёт место, куда можно повесить проверку.
И самое недооценённое: слой координации — это код. Согласование восемнадцати агентов между собой стоит ноль токенов, потому что скрипт — не диалог.
Большинство продолжит настраивать один цикл и называть это системой. Те, кто нарисует вокруг него граф, будут запускать флот — и никогда толком не поймут, почему остальным так тяжело за ними успевать.
🗺 Собрать маркетинг-план на 90 днейБесплатно, в Telegram-боте @uspeshnyybot








Комментарии
Войдите через Telegram, чтобы оставить комментарий:
Пока нет комментариев. Будьте первым.