1. Паралельний workflow ламається на розмитих межах
Паралельний workflow найчастіше ламається саме на розмитих межах, і сама схема ролей ще нічого не рятує. Поки в ролей немає scope, forbidden zones, stop condition і handoff, pattern лишається діаграмою. Тут і parallel workflow тріщить по швах.
Коли люди вперше пробують кілька агентів, помилка майже завжди одна й та сама: вони ділять не задачу, а надію. У голові звучить щось на кшталт «один нехай робить backend, другий frontend, третій перевіряє». Це не інженерний дизайн, а побажання Всесвіту. Claude працює там, де межі задані файлами, контрактами й артефактами, а не настроєм.
Найпростіше уявити це як ремонт кухні. Сказали трьом «ну ви тут пофарбуйте нормально» — один пофарбує стіни, другий заодно зачепить стелю, третій принесе думку про палітру. У коді те саме, тільки замість стелі страждає OrderService.java, а замість запаху фарби лишається merge conflict.
Проблема паралельної роботи рідко в тому, що агент «недостатньо розумний». Набагато частіше річ у надто широкому формулюванні.
| Розмите формулювання | Що зазвичай відбувається | Робоче формулювання |
|---|---|---|
| «Агент 1 робить backend» | Зачепить API, utils, тести, а іноді й конфіг «заодно» | «Змінює лише src/api/orders/*, публічний контракт не чіпає» |
| «Агент 2 робить frontend» | Полізе в спільний ui-kit, бо “так зручніше” | «Змінює лише src/web/orders/*, не редагує спільні компоненти» |
| «Агент 3 перевіряє» | Поверне думку, а не перевірюваний результат | «Читає diff, запускає smoke-check, повертає findings з evidence» |
У гарній паралельній роботі ви заздалегідь відповідаєте на три запитання. Хто володіє якою областю змін. За яким сигналом роль зупиняється. Який артефакт передає далі. Залишили хоч один у режимі «по ходу розберемося» — конфлікт уже записаний у календар.
Саме тому parallel workflow починається не із запуску другого агента, а з меж. Спочатку карта. Потім двигуни.
2. По якій осі розрізати роботу
Коли ви чуєте «розділити ownership», легко скотитися до грубого «backend окремо, frontend окремо». Іноді цього досить. Але частіше важливіше запитати: по якій осі задача ділиться природно. Інакше ролі різні лише на папері, а фактично штовхаються ліктями в одному місці. Ось карта осей.
| Вісь поділу | Коли корисна | Приклад |
|---|---|---|
| Файли | Маленька точкова задача | Один агент змінює лише OrderRefundService.java |
| Каталоги | Ізольовані шматки проєкту | src/api/orders/* окремо від src/web/orders/* |
| Модулі | Бізнес-області вже розділені архітектурою | orders, support, dashboard |
| Шари | Є стабільний контракт між UI та API | backend-шар окремо від frontend-шару |
| Користувацькі сценарії | Задача ріжеться за flow, а не за шарами | «фільтр замовлень» окремо від «експорт CSV» |
| Артефакти | Потрібні різні типи результату | один робить PLAN.md, інший — diff, третій — review notes |
| Ризик-зони | Важливо ізолювати небезпечні частини | payments/, migrations/, auth/ як окремі зони уваги |
Ключова ідея тут у тому, що вісь має бути одна головна. Факторів у житті завжди кілька, але базова логіка поділу має читатися. Розрізаєте одночасно за шарами, сценаріями й папками, не назвавши головного, — отримаєте не делегування, а квест на уважність.
Наприклад, якщо в Commerce OS потрібно додати фільтр за статусом повернення на сторінку замовлень, то головна вісь тут шар плюс каталог: backend-виконавцю src/api/orders/*, frontend-виконавцю src/web/orders/*. А переробляти один legacy-клас поруч із платежами за шарами безглуздо: один owner, одна сесія, максимум — окремий reviewer.
Є ще одне корисне правило: один owner на один файл або модуль, якщо це взагалі можливо. Щойно двоє правлять один клас, DTO або спільний util, ви перестаєте вигравати час і починаєте інвестувати в конфлікт. Інвестиція дуже дорога.
3. Delegation brief коротший, ніж здається
Ось тут pattern нарешті перетворюється на виконуваний контракт. Після verdict про паралельність і схеми ролей зʼявляється третій шар — delegation brief: хто, де, до якого сигналу і що повертає далі.
У новачків тут часто два режими, і вас потягне в одну з крайнощів. «Занадто мало»: “зроби backend”. «Занадто багато»: півтори сторінки, де корисне потонуло в проєкті. Хороший бриф посередині — коротка інженерна записка, яку роль або приймає, або одразу повертає на уточнення.
У брифу є пʼять обовʼязкових частин. Не бюрократія, а мінімум, без якого роль починає «корисно» виходити за межі.
| Поле | Навіщо потрібне | Приклад |
|---|---|---|
| Scope | Де саме можна працювати | |
| Preserve | Що не можна зламати | публічний API, контракт відповіді |
| Don’t touch | Заборонені зони | migrations/, UI, shared utils |
| Stop when | Умова зупинки | тести зелені, diff не зріс |
| Return | Що передати далі | список файлів, вивід тестів, ризики |
Ось приклад поганого брифу. Він короткий, але марний:
# Погано
Агент 1 робить backend.
Агент 2 робить frontend.
Агент 3 перевіряє.
Такий бриф не говорить взагалі нічого. Де backend? Що не можна чіпати? Коли робота завершена? Що поверне reviewer? Відповідь одна: «та якось». А «якось» у multi-agent роботі перекладається як «дорого й неприємно».
Тепер нормальний варіант для backend owner:
# Backend owner
Scope: src/api/orders/*
Preserve: публічний API з api/orders/openapi.yaml
Add: 1 integration test у tests/api/orders/
Don't touch: UI, shared utils, migrations/
Stop when: тести проходять, diff <= 200 LOC
Return: змінені файли + вивід тестів + risk note
Тут немає магії, зате є все, що потрібно. Виконавець знає, куди можна, а куди не можна. Reviewer знає, за чим перевіряти. Ви знаєте, що читати в handoff.
Особливо корисно берегти рядок Don't touch. Виглядає суворо — економить масу часу. У Claude, як і в людей, є схильність «ну раз я вже тут, давайте ще трішечки покращу». Так у PR на 120 рядків раптом приїжджають правки DateUtils і перейменування половини полів форми. Не заборонили зайве явно — дозволили йому мовчки.
4. Дослідження, реалізація і перевірка — різні ролі
Коли задача щойно досліджена, виникає спокуса одразу дати тому самому агенту писати код: «він же вже прочитав файли, хай і змінює». Але тут є підступ. Read-only дослідження і write-робота — різні режими мислення. У першому ви збираєте evidence, у другому ухвалюєте рішення, що змінюють проєкт. Змішаєте без контролю — проскочите шлях від «знайшов причину» до «заодно все підправив».
Для цього у Workflow Kit і існує ідея формального контракту передачі. Не «я усно розповів», а короткий handoff, який перевіряється очима. Шматок із AGENT_HANDOFF_CONTRACT.md:
## Передача
Input: PLAN.md + affected files list
Allowed scope: src/web/orders/*
Forbidden: src/api/**, migrations/**
Stop condition: фільтр працює локально
Output: diff + screenshot + changed files
Evidence: smoke result + file refs
Такий формат здається сухим лише до першого конфлікту. Після нього він виглядає як дуже добра і турботлива річ.
Окремо корисно за замовчуванням розділяти ролі й за характером доступу. Дослідник читає й збирає evidence. Виконавець змінює код у вузькій зоні. Reviewer працює на свіжому контексті й нічого не редагує. Tester запускає тести й за потреби змінює тестові файли, але не production-код. Щойно reviewer починає «трошки підправляти» код, він перетворюється на другого виконавця — а це інший тип ризику.
Гарна новина в тому, що це правило не робить процес повільнішим — навпаки: з явним поділом вам потім не треба гадати, звідки в diff зміни і хто зачепив зайвий файл.
5. Умова зупинки важливіша за ентузіазм
Одна з найбільш недооцінених частин брифу — stop condition. Немає її — агент зупиниться за внутрішнім відчуттям прекрасного. А воно в AI, мʼяко кажучи, щедре: він не знає, що вам потрібен маленький PR на сьогодні, а не «ще трішки поліпшити архітектуру».
Тому умова зупинки має бути або перевірюваною машиною, або дуже конкретною для людини. Не «коли все готово», а «коли локально проходить такий-то тест і зміни не вийшли за approved scope». Не «коли UI виглядає нормально», а «коли фільтр видно на сторінці, він надсилає параметр у запит і smoke-check проходить».
| Формулювання | Що з ним не так | Робочий варіант |
|---|---|---|
| «Зупинися, коли буде готово» | ніхто не знає, що таке «готово» | «зупинися після зеленого smoke-check і diff summary» |
| «Поверни результат» | результат може бути чим завгодно | «поверни список файлів, вивід тестів і risk note» |
| «Перевір зміни» | review без evidence перетворюється на думку | «поверни findings з file refs і severity» |
Приклад у YAML-стилі:
stop_when:
- "gradle test --tests OrdersFilterIT green"
- "змінені файли лише в src/api/orders/* та tests/api/orders/*"
return:
- "зведення git diff"
- "вивід тестів"
- "risk note"
Тут чудово те, що такий brief читається і людиною, і Claude — і його легко оскаржити до старту: бачите, що diff <= 200 LOC для задачі нереалістичний, змінюєте очікування заздалегідь, а не наприкінці на емоціях.
І ще одна важлива річ: evidence — не прикраса. Виконавець пише «все працює», а в handoff немає списку файлів, виводу тестів і хоча б короткої примітки про ризики — перевіряти нічого. У вас є лише віра. А курс, нагадаю, будується не на вірі, а на перевірюваних артефактах.
6. Порядок інтеграції вигадують до старту
Коли кілька ролей справді працюють паралельно, постає ще одне практичне запитання: у якому порядку їхні результати з’єднаються. І тут багато хто робить класичну помилку — вважає, що merge order вигадується потім. «Потім» зазвичай означає «коли два агенти вже змінили один контракт і дивляться на вас як на винуватця».
Порядок не обовʼязково має бути складним, але обовʼязково має бути названий заздалегідь — базовий потрібен навіть без повноцінної merge-стратегії. Наприклад, для фільтра замовлень у Commerce OS він може бути таким:
| Порядок | Роль | Що віддає |
|---|---|---|
| 1 | Планувальник | PLAN.md + заморожений API contract |
| 2 | Власник backend | diff + вивід integration test |
| 3 | Власник frontend | diff + screenshot/smoke result |
| 4 | Перевіряльник | REVIEW.md з findings |
| 5 | Людина | рішення про merge |
Зверніть увагу, тут frontend іде після backend не тому, що «так завжди треба», а тому, що UI залежить від контракту відповіді. Поки контракт плаває, frontend-виконавець стріляє по рухомій мішені. Іноді це допустимо, але частіше — зайвий ризик.
Буває й зворотна ситуація: два виконавці здаються незалежними, а в них спільний OrderFilterDto. Якщо обидва змінюють його одночасно, справжньої паралельності немає. Або спочатку заморозити контракт, або чесно серіалізувати роботу. Трагедії тут ніякої. Гірше — вдавати, що робота паралельна, хоча ви просто відклали конфлікт на пів години.
Можна сформулювати просте правило: не можете у двох-трьох рядках описати порядок передачі результатів — задача ще не готова до паралельного виконання. Ролі вигадали, а як вони живуть разом — ні.
7. Agent pipeline для Commerce OS: один артефакт
Тепер давайте зберемо все на одному реальному сценарії. Задача в Commerce OS: додати фільтр за статусом повернення на сторінку замовлень в адмінці. Велика — в одній сесії не хочеться, але не настільки хаотична, щоб кликати цілу agent team. Гарний кандидат на чіткий pipeline.
Спочатку фіксуємо схему ролей — не заради краси, а щоб кожен у ланцюжку розумів своє місце.
[Планувальник / режим планування]
артефакт: PLAN.md + API contract
↓
[Власник backend / subagent]
scope: src/api/orders/* + tests/api/orders/*
output: diff + вивід тестів
↓
[Власник frontend / нова сесія]
scope: src/web/orders/*
output: diff + screenshot + smoke result
↓
[Перевіряльник / reviewer agent]
read-only, перевіряє diff bundle + tests
output: REVIEW.md
↓
[Людина]
рішення про merge
Ось у цей момент зазвичай і стає видно, здорова задача чи ні. Pipeline малюється коротко — ownership достатньо ясний. Замість схеми виходить пів сторінки уточнень і стрілок «можливо» — отже, ви або зарано полізли в паралельність, або задачу ще не дорізали.
Тепер приклад handoff від backend owner до frontend owner:
Input: PLAN.md + оновлений приклад API-відповіді
Frontend assumes: контракт відповіді заморожений
Forbidden: backend edits, shared utils
Stop when: фільтр видно і він надсилає параметр
Return: screenshot + changed files + smoke result
Зверніть увагу, скільки конфліктів знімає ця маленька записка. Frontend отримує не «ну backend уже начебто щось зробив», а конкретний вхід і конкретні межі. Знає, що API-контракт не попливе під ногами. Знає, чого не чіпати. Знає, який результат повернути далі verifier-у.
Усе це і є практичний сенс лекції. Не вивчити термін delegation design, а перестати запускати паралельну роботу в режимі «сподіваюся, агенти самі домовляться». Домовлятися самі вони не повинні. Це ваша робота як розробника.
Зберіть чотири речі разом — названу межу, короткий перевірюваний brief, конкретну умову зупинки і заздалегідь продуманий порядок передачі — і паралельна робота перестає бути генератором merge conflict'ів. Конфлікт більше не призначається в календар за замовчуванням: він або виключений поділом ownership, або чесно перетворений на послідовний крок. Ви не сподіваєтесь, що агенти розійдуться по своїх зонах, — ви ці зони розрізали заздалегідь. Саме це відрізняє делегування від роздачі задач у порожнечу.
Від цього місця важливі вже не нові назви ролей, а звичайна робоча дисципліна: де ви тримаєте статус потоків — у agent view, task list чи issue note, — як ставите checkpoints, у якому порядку зводите результати й за якими метриками розумієте, що pipeline не розповзається.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ