<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ИИ on Михаил Шогин</title><link>https://mshogin.ru/categories/%D0%B8%D0%B8/</link><description>Recent content in ИИ on Михаил Шогин</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>Михаил Шогин</copyright><lastBuildDate>Fri, 22 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mshogin.ru/categories/%D0%B8%D0%B8/index.xml" rel="self" type="application/rss+xml"/><item><title>Главная задача — научить агента вовремя остановиться</title><link>https://mshogin.ru/blog/agent-pipeline-discipline/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://mshogin.ru/blog/agent-pipeline-discipline/</guid><description>&lt;img src="https://mshogin.ru/blog/agent-pipeline-discipline/cover.svg" alt="Featured image of post Главная задача — научить агента вовремя остановиться" /&gt;&lt;h2 id="в-этой-статье"&gt;В этой статье
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#%d0%b3%d0%b4%d0%b5-%d0%bb%d0%be%d0%bc%d0%b0%d0%b5%d1%82%d1%81%d1%8f-%d0%b0%d0%b2%d1%82%d0%be%d0%bd%d0%be%d0%bc%d0%b8%d1%8f" &gt;Где ломается автономия&lt;/a&gt;: тихий ремонт и скрытый дрейф&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80-%d0%bf%d1%80%d0%be%d0%b2%d0%b0%d0%bb%d0%b0" &gt;Пример провала&lt;/a&gt;: как pipeline закрыл задачу с расходящимися отчётами&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-1-%d0%ba%d0%be%d0%bd%d1%82%d1%80%d0%b0%d0%ba%d1%82-%d0%bc%d0%b5%d0%b6%d0%b4%d1%83-%d1%84%d0%b0%d0%b7%d0%b0%d0%bc%d0%b8-%d0%ba%d0%b0%d0%ba-json" &gt;Решение 1&lt;/a&gt;: JSON-контракт между фазами&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-2-%d0%bd%d0%b5%d0%b7%d0%b0%d0%b2%d0%b8%d1%81%d0%b8%d0%bc%d1%8b%d0%b9-verify" &gt;Решение 2&lt;/a&gt;: независимый VERIFY вне периметра агента&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-3-%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%bc%d0%be%d0%b4%d0%b5%d0%bb%d0%b5%d0%b9-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-router" &gt;Решение 3&lt;/a&gt;: router и пять моделей под разные фазы&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#%d0%bf%d1%80%d0%b8%d0%bd%d1%86%d0%b8%d0%bf%d1%8b" &gt;Принципы&lt;/a&gt; и &lt;a class="link" href="#%d0%b8%d1%82%d0%be%d0%b3" &gt;Итог&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="где-ломается-автономия"&gt;Где ломается автономия
&lt;/h2&gt;&lt;p&gt;Технический долг — задачи, на которые всегда нет времени. Идеальная цель для автоматизации: распределить роли (PM, системный аналитик, разработчик, QA) и запустить автономный цикл обработки тикетов.&lt;/p&gt;
&lt;p&gt;На бумаге это работает. На практике автономия превращается в тихий ремонт.&lt;/p&gt;
&lt;p&gt;Агент сталкивается с проблемой в окружении — и не отчитывается о блоке. Вместо этого начинает править соседний код, лезть в конфиги, &amp;ldquo;оптимизировать&amp;rdquo; то, о чём его не просили. На выходе &amp;ldquo;Done&amp;rdquo;, но половина окружения уехала со спецификации.&lt;/p&gt;
&lt;p&gt;Я называю это скрытым дрейфом. Каждая отдельная правка локально выглядит как улучшение. Накапливаются они в &amp;ldquo;тихий ремонт&amp;rdquo;, который никто не запрашивал — и который очень трудно откатить, потому что Git diff давно перестал отражать одну задачу.&lt;/p&gt;
&lt;h2 id="пример-провала"&gt;Пример провала
&lt;/h2&gt;&lt;p&gt;Сегодня pipeline закрыл задачу как DONE. Developer честно сделал работу, запустил &lt;code&gt;check_command&lt;/code&gt;, получил &lt;code&gt;exit=0&lt;/code&gt;, отчитался &lt;code&gt;passed=true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Независимая параллельная проверка дала &lt;code&gt;exit=1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Никто не соврал. &lt;code&gt;check_command&lt;/code&gt; содержал паттерн &lt;code&gt;test&lt;/code&gt;, который ведёт себя по-разному на linux и macOS. Артефакт сборки оказался несовместим со средой проверки. Агент видел &amp;ldquo;успех&amp;rdquo; со своей колокольни. С другой колокольни — провал.&lt;/p&gt;
&lt;p&gt;Этот один случай задаёт всю архитектуру дальше. Если мы доверяем self-report агента, мы доверяем фрагменту окружения, в котором он находится. А окружение — переменная.&lt;/p&gt;
&lt;h2 id="решение-1-контракт-между-фазами-как-json"&gt;Решение 1: контракт между фазами как JSON
&lt;/h2&gt;&lt;p&gt;В первых итерациях фазы общались свободным текстом. Аналитик описывал план, разработчик читал и интерпретировал. Звучит как нормальный человеческий процесс. На практике даёт три проблемы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;модель додумывает поля, которые не запрашивались&lt;/li&gt;
&lt;li&gt;следующая фаза вынуждена парсить свободный текст&lt;/li&gt;
&lt;li&gt;&amp;ldquo;я подумал и решил сделать ещё&amp;rdquo; — реальная фраза в логах&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Перешли к JSON-схеме между каждой парой фаз. Constrained generation через tool_use заставляет модель заполнить именно те поля, которые ожидает следующая фаза, и не заполнять ничего сверх.&lt;/p&gt;
&lt;div class="mermaid"&gt;
stateDiagram-v2
[*] --&gt; PLAN
PLAN --&gt; SPEC: JSON plan
SPEC --&gt; DEV: JSON spec
DEV --&gt; QA: JSON diff + report
QA --&gt; VERIFY: JSON review
VERIFY --&gt; DONE: independent pass
VERIFY --&gt; BLOCKED: mismatch
PLAN --&gt; BLOCKED: cannot plan
SPEC --&gt; BLOCKED: ambiguity
DEV --&gt; BLOCKED: env issue
QA --&gt; BLOCKED: review fail
BLOCKED --&gt; [*]: handover to human
DONE --&gt; [*]
&lt;/div&gt;
&lt;p&gt;Каждый переход — структурный артефакт по схеме. Никакого &amp;ldquo;свободного творчества&amp;rdquo;. Хочешь добавить мысль — нет поля в схеме, мысль не передаётся. Свободный текст остаётся только в одном месте — в комментариях для человека, и они не влияют на следующий шаг.&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph LR
A[Issue] --&gt;|JSON: goal, constraints| B[PLAN]
B --&gt;|JSON: steps, owners| C[SPEC]
C --&gt;|JSON: contract, acceptance| D[DEV]
D --&gt;|JSON: diff, check_command, passed| E[QA]
E --&gt;|JSON: review verdict| F[VERIFY]
F --&gt;|JSON: status| G[DONE or BLOCKED]
&lt;/div&gt;
&lt;p&gt;Что важно: схема — это не &amp;ldquo;лучший формат&amp;rdquo; для людей, она для следующей фазы. Если на ревью вы хотите видеть что-то ещё — отдельный человеко-читаемый рендер из той же JSON. Не смешивайте каналы.&lt;/p&gt;
&lt;h2 id="решение-2-независимый-verify"&gt;Решение 2: независимый VERIFY
&lt;/h2&gt;&lt;p&gt;Из примера с &lt;code&gt;check_command&lt;/code&gt; я вытащил жёсткое правило: проверка должна жить отдельно от агента.&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph TB
subgraph agentenv ["Agent environment"]
A1[Developer agent]
A2[Local config]
A3[Cache, env vars]
A4[Build artifact]
A1 --- A2
A1 --- A3
A1 --- A4
end
subgraph verifyenv ["Verify environment"]
V1[Fresh clone]
V2[Clean container]
V3[Independent check_command]
V1 --- V2
V2 --- V3
end
A1 --&gt;|reports passed=true| C{Compare}
V3 --&gt;|independent exit code| C
C --&gt;|match| OK[DONE]
C --&gt;|mismatch| BL[BLOCKED]
&lt;/div&gt;
&lt;p&gt;Слева — среда агента. Он работает в ней: знает свои зависимости, локальные конфиги, кеши, переменные окружения. Может что угодно. Главное — отчитывается о результате.&lt;/p&gt;
&lt;p&gt;Справа — verify-среда. Свежий клон репозитория, чистый контейнер, никаких артефактов от агента, никаких &amp;ldquo;уже собранных&amp;rdquo; бинарников. Запускает тот же &lt;code&gt;check_command&lt;/code&gt; из независимой точки. Если результаты расходятся — задача в BLOCKED.&lt;/p&gt;
&lt;p&gt;Это не дороже, чем доверять. Один лишний прогон проверки стоит сильно меньше, чем тихое закрытие задачи со скрытым дрейфом. Аудит таких закрытий потом всё равно придётся проводить — просто на месяц позже и с потерянным контекстом.&lt;/p&gt;
&lt;h2 id="решение-3-специализация-моделей-через-router"&gt;Решение 3: специализация моделей через router
&lt;/h2&gt;&lt;p&gt;Один универсальный agent на все задачи — анти-паттерн. У каждой фазы своя нагрузка, и универсальная модель либо переплачивает, либо недоезжает.&lt;/p&gt;
&lt;div class="mermaid"&gt;
graph LR
IN[Phase request] --&gt; R{Local router}
R --&gt;|structural JSON| M1[Planner]
R --&gt;|deep reasoning| M2[Reasoning specialist]
R --&gt;|long document| M3[Long-context]
R --&gt;|short patch| M4[Executor]
R --&gt;|simple reply| M5[Fast chat]
M1 --&gt; OUT[Structural artifact]
M2 --&gt; OUT
M3 --&gt; OUT
M4 --&gt; OUT
M5 --&gt; OUT
&lt;/div&gt;
&lt;p&gt;Пять ролей под пять типов нагрузки:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;planner&lt;/strong&gt; — структурные решения, последовательность и точность над JSON&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;reasoning specialist&lt;/strong&gt; — тяжёлое обоснование, разбор архитектурных вопросов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;long-context&lt;/strong&gt; — суммаризация документов и длинных тикетов&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;executor&lt;/strong&gt; — короткие патчи, рутинные операции&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fast chat&lt;/strong&gt; — диалоговые реплики, простые ответы&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Router смотрит на тип фазы и сложность артефакта, направляет вызов в соответствующую модель. Локально, без привязки к одному провайдеру. Это и про стоимость, и про то, что разные модели сильны в разном — нет смысла делать структурный план моделью, заточенной под длинный диалог.&lt;/p&gt;
&lt;h2 id="принципы"&gt;Принципы
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Дисциплина контракта важнее скорости генерации.&lt;/strong&gt; Свободный текст между фазами — приглашение к дрейфу.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Не доверяй self-report.&lt;/strong&gt; Verify живёт вне периметра агента.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Останавливайся явно.&lt;/strong&gt; BLOCKED — это статус, а не fallback. Если что-то не сходится — задача стоит и ждёт человека. Не закрывается с &amp;ldquo;Done&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Специализация важнее универсальности.&lt;/strong&gt; Pipeline из специализированных моделей дешевле и стабильнее, чем одна большая модель на всё.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="итог"&gt;Итог
&lt;/h2&gt;&lt;p&gt;Автономия агентов — это не свобода. Это контракт. Чем плотнее контракт и чем независимее проверка, тем меньше дрейфа и тихих закрытий.&lt;/p&gt;
&lt;p&gt;Останавливаться — это умение. Pipeline, который умеет сказать &amp;ldquo;не знаю&amp;rdquo;, безопаснее pipeline&amp;rsquo;а, который всегда говорит &amp;ldquo;готово&amp;rdquo;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Архитектурный вопрос:&lt;/strong&gt; где в вашем процессе self-report агента сейчас считается за истину, и какой минимальный шаг добавит туда независимую проверку?&lt;/p&gt;
&lt;/blockquote&gt;</description></item></channel></rss>