Зупинка та відновлення агентів LangGraph за допомогою interrupt() та Command
Як функції interrupt() та Command у LangGraph використовують чекпоїнти та потоки для призупинення агента з метою отримання схвалення, внесення змін чи введення даних від людини, а потім безпечного його продовження пізніше.
Агент, який може переміщувати гроші, видаляти ресурси чи запускатися у продакшні, не повинен завжди мати можливість довести до кінця те, що почав. Іноді граф мусить навмисно зупинитися, чекати кілька годин на людину, а потім продовжити саме з того місця, де зупинився. У цій статті пояснюється, як LangGraph реалізує це за допомогою interrupt() та Command, чому це залежить від чекпоїнтів та потоків, а також які рішення все ще залишаються у вашому контролі перед запуском агентів з участю людини (HITL) у продакшні.
Основні елементи
HITL базується на трьох шарах. По-перше, виконання графу: стан потрапляє у вузол, а ребро вибирає наступний вузол.
STATE
↓
NODE
↓
EDGE
↓
NEXT NODE
По-друге, керування станом: вузли повертають оновлення, а редьюсери об’єднують їх у новий стан.
NODE
↓
STATE UPDATE
↓
REDUCER
↓
NEW STATE
По-третє, персистентність: чекпоїнтер зберігає стан у вигляді чекпоїнтів, групованих за потоками.
STATE
↓
CHECKPOINT
↓
CHECKPOINTER
↓
THREAD
↓
PERSISTENCE
Разом це дозволяє агенту працювати, пам’ятати інформацію та виживати після перезапуску. Що бракує, — це способу вирішити, чи варто йому взагалі продовжувати роботу.
Коли агент не повинен просто продовжувати
Користувач просить асистента з оплатами: «Перекажіть 50 000 рупій на цей рахунок». Агент готує транзакцію, і технічно немає нічого, що б заважало її виконанню.
User
↓
Agent
↓
Prepare Transfer
↓
Transfer ₹50,000
↓
Execute
Для такої значущої дії людина повинна спочатку переглянути пропозицію, щоб процес розвивався залежно від людського рішення.
User
↓
Agent
↓
Prepare Transfer
↓
┌─────────────────────┐
│ HUMAN APPROVAL │
└──────────┬──────────┘
│
┌───┴───┐
↓ ↓
Approve Reject
│ │
↓ ↓
Execute Cancel
Тепер граф повинен навмисно зупинитися: не через помилку чи збій, а тому що тут процес вимагає людського втручання.
Що означає участь людини
HITL включає людські рішення у автоматизований процес. Замість того, щоб безпосередньо переходити від рішення до дії,
Agent
↓
Decision
↓
Action
агент пропонує дію, зупиняється та чекає на перегляд.
Agent
↓
Proposed Action
↓
PAUSE
↓
Human Review
↓
Decision
↓
Continue
Рецензент може схвалити, відхилити пропозицію, внести зміни, надати бракуючі дані, виправити агента чи обрати один із варіантів. Це підходить для будь-якого кроку з реальними наслідками.
Financial transactions
Sending emails
Deleting resources
Production deployments
Database modifications
Legal workflows
Publishing content
Access approvals
Sensitive tool calls
Що насправді потрібно для призупинення графа
Візьмемо ланцюг із кроком схвалення перед останнім вузлом.
Node A
↓
Node B
↓
Human Approval
↓
Node C
Якщо рецензент відповідає через шість годин, блокування процесу — це неправильна відповідь: це марнує ресурси працівника та призводить до зупинки під час першого запуску.
sleep(21600)
Натомість потрібно зберегти стан та зупинитися,
Node B
↓
SAVE STATE
↓
PAUSE EXECUTION
↓
потім відновити його пізніше, можливо, в іншому процесі, та продовжити роботу на наступному вузлі.
Application can stop──────── 6 HOURS LATER ────────Human responds
↓
RESTORE STATE
↓
CONTINUE EXECUTION
↓
Node C
Персистентність вже розв’язує половину цієї проблеми. Контрольні точки, механізм контролю, потоки та thread_id — саме те, що потрібно для тривалої призупинки.
Checkpoint
Checkpointer
Thread
thread_id
Persistence
Як interrupt() зупиняє виконання
interrupt() зупиняє граф та запитує зовнішній світ про значення. Його викликають усередині вузла з навантаженням, яке можна серіалізувати у форматі JSON та яке описує, що має побачити користувач. Цей фрагмент написаний на Python, попри початкову позначку.
from langgraph.types import interrupt
def approval_node(state):
decision = interrupt({
"question": "Do you approve this transaction?",
"amount": state["amount"]
})
return {
"decision": decision
}
Коли виконання доходить до цього виклику,
interrupt(...)
вузол не доходить до оператора повернення. Виконання призупиняється, а навантаження повертається викликаючому для відображення.
approval_node
│
↓
interrupt()
│
↓
┌─────────────────┐
│ EXECUTION PAUSED│
└─────────────────┘
Важливі два моменти. interrupt() вимагає графу, скомпільованого з checkpointer, оскільки стан зупинки має бути де-небудь збережений. Коли виконання продовжується, LangGraph знову запускає перерваний вузол з початку, причому interrupt() тепер повертає значення, введене користувачем, тож код перед цим викликом виконується двічі. Утримуйте побічні ефекти подалі від цієї частини вузла та перевірте поведінку у вашій версії в документації LangGraph.
Що зберігається під час переривання
Розгляньмо цю діаграму.
START
↓
Prepare Transfer
↓
Human Approval
↓
Execute Transfer
↓
END
Вузол підготовки оновлює стан, записується контрольна точка, а вузол схвалення викликає interrupt().
START
↓
Prepare Transfer
↓
State Updated
↓
Checkpoint
↓
Approval Node
↓
interrupt()
Текущий стан фіксується та записується у пам’ять.
Current State
│
↓
Checkpoint
│
↓
Persistent Storage
Тепер потік містить деталі передачі, статус очікування та причину зупинки.
THREAD: transaction-123
Checkpoint
────────────────────
amount ₹50,000
recipient Account X
status pending
────────────────────
Execution:
PAUSED
Reason:
Human approval required
Це все, що потрібно для подальшої роботи. Без збереження даних процес просто зникне після переривання.
Agent
↓
interrupt
↓
process disappears
↓
???
Коли перевіряючий наступного дня пише „Схвалено“, ніхто не може зрозуміти, що саме було схвалено, де зупинилася діаграма чи який вузол слідує далі. Завдяки контрольним точкам стан завантажується з потоку та відновлюється перед продовженням роботи.
INTERRUPT
│
↓
CHECKPOINT
│
↓
THREAD
│
↓
PERSISTENT STORAGE
...time passes...
HUMAN INPUT
│
↓
THREAD
│
↓
LOAD CHECKPOINT
│
↓
RESTORE STATE
│
↓
RESUME
Повернення до роботи за командою
Додаток відображає зміст переривання у вигляді запитання
Approve transfer of ₹50,000?
з двома кнопками,
[ APPROVE ] [ REJECT ]
і переглядач обирає одну з них.
APPROVE
Відповідь надсилається через Command, який вказує графу, як діяти далі. Щоб продовжити, викличте граф за допомогою Command(resume=...) замість звичайного введення.
from langgraph.types import Command
graph.invoke(
Command(resume="approved"),
config=config
)
config має мати ту саму потокову структуру, що й призупинений запуск,
thread_id = transaction-123
адже ідентифікатор потоку — це те, що дозволяє LangGraph визначити, про яку призупинену виконуваність йдеться.
Етапи життєвого циклу поетапно
Запуск починається зі звичайного виклику,
graph.invoke()
читає свій поток з конфігурації,
thread_id = transaction-123
входить у вузол підготовки,
START
↓
Prepare Transfer
та записує дані про передачу у стан системи.
amount = ₹50,000
recipient = Account X
status = pending
Вузол схвалення викликає interrupt(),
Approval Node
↓
interrupt()
і виконання призупиняється.
EXECUTION PAUSED
Останній пункт перевірки залишається в безпеці під потоком.
Thread
↓
Checkpoint
↓
Persistent Storage
Людина бачить запит
Approve ₹50,000 transfer?
і відповідає.
YES
Додаток надсилає команду відновлення
Command(resume="approved")
до того самого потоку.
transaction-123
LangGraph відновлює виконання, передає рішення вузлу схвалення та продовжує до кінця.
Restore Execution
↓
Human Decision = approved
↓
Continue Graph
↓
Execute Transfer
↓
END
Кожен з наведених нижче варіантів є модифікацією цього життєвого циклу.
Людські рішення, крім «так» чи «ні»
Відповідь переглядача не обов’язково має бути двійковою.
YES / NO
Схвалення виконує пропозицію.
Agent Proposal
↓
Human
↓
APPROVE
↓
Execute
Відхилення скасовує її.
Agent Proposal
↓
Human
↓
REJECT
↓
Cancel
Редагування змінює її частини, наприклад суму, перш ніж граф продовжить роботу.
Agent:
Send ₹50,000
↓
Human:
Change to ₹40,000
↓
Graph continues with
updated information
Надання відсутньої інформації перетворює переривання на запитання.
Agent
↓
Missing Account Number
↓
INTERRUPT
↓
Human provides account
↓
RESUME
Вибір дозволяє агенту пропонувати альтернативи та залишити остаточне рішення людині.
Agent generates:
Option A
Option B
Option C
↓
Human chooses B
↓
Graph continues
HITL — це загальний спосіб введення даних від користувача у діючу структуру графа, а не лише діалог затвердження.
Команда як потік даних та контрольний потік
Команда також може оновлювати стан та вибирати наступну точку призначення.
Resume Execution
Update State
Choose Next Destination
Одна команда може встановити статус та надіслати виконання до конкретного вузла; у LangGraph ця форма зазвичай повертається від вузла.
Command(
update={
"status": "approved"
},
goto="execute"
)
Це поєднує два аспекти,
DATA FLOW
+
CONTROL FLOW
адже маршрутизація раніше належала лише до ребер.
Edges control where we go.
Тепер один об’єкт може містити як зміну стану, так і наступний крок.
Command can participate in
state updates + control decisions.
Корекція стану перед продовженням
Припустимо, що держава тримає цю суму,
amount = 50000
і перевіряючий схвалює її з внесенням корекцій.
Approve, but change amount to 40000.
Потік даних проходить від початкового значення, через перевірку, до оновленого значення, і лише тоді продовжується (другий фрагмент виводиться на одну лінію).
BEFORE
amount = 50000 ↓Human Review ↓UPDATEamount = 40000 ↓RESUME
Запит змінюється з „Чи можу я продовжити?“ на „Перевірити, виправити за потреби, а потім продовжити“.
Контроль викликів чутливих інструментів
HITL є найбільш практичним для використання перед ризикованими інструментами.
search_web()
read_database()
send_email()
delete_resource()
transfer_money()
Пошук в Інтернеті може виконуватися автоматично,
search_web()
↓
Execute Automatically
тоді як при видаленні ресурсу потрібно чекати на схвалення.
delete_resource()
↓
INTERRUPT
↓
Human Approval
Кожен виклик інструменту проходить перевірку на чутливість: безпечні виклики виконуються, а чутливі зупиняються для отримання схвалення або скасування.
Agent
│
↓
Tool Call
│
↓
Sensitive Tool?
/ \
NO YES
│ │
↓ ↓
Execute INTERRUPT
│ │
│ ↓
│ Human
│ / \
│ Approve Reject
│ │ │
└─────────┘ ↓
Cancel
Щоб дізнатися більше про повну реалізацію з підтримкою сховища, дивіться агентів з контролем схвалення в LangGraph.
Перегляд як свідома межа контролю
Людський перегляд — це не спосіб виправити агента, який недостатньо розумний. Це межа, яку ви ставите навмисно. Робота з низьким рівнем ризику виконується автоматично,
LOW RISK
Search
Read
Summarize
↓
Automatic
а робота з високим рівнем ризику проходить через людину.
HIGH RISKSend
Delete
Purchase
Transfer
Deploy
↓
Human Approval
Мета — визначити, де доцільна автономія, а не скорочувати її всюди.
Обробка відхилень та мовчання
Відхилення вимагають належного проектування.
Agent
↓
Prepare Action
↓
Interrupt
↓
Human
↓
REJECT
Запишіть результат у стан,
status = "rejected"
потім спрямуйте виконання залежно від нього за допомогою умовного ребра.
Decision
/ \
approved rejected
│ │
↓ ↓
Execute Cancel
│ │
↓ ↓
END END
Усі попередні концепції беруть участь, а людський вхід — це просто додаткова інформація, яка впливає на виконання.
State
Reducers
Conditional Routing
Checkpoints
Threads
Commands
Рецензенти також можуть ніколи не відповісти.
Interrupt
↓
Waiting for approval
↓
1 hour
↓
1 day
↓
7 days
Зупинений поток може чекати необмежено, тому вашому додатку потрібні правила керування.
Expiration
Timeout
Cancellation
Reminder
Escalation
Поширеним рішенням є обмежений за часом очікування, яке зазвичай реалізується через планувальник, що відновлює застарілі потоки після закінчення тайм-ауту.
Approval Requested
│
↓
Wait up to 24 hours
│
┌───┴────┐
↓ ↓
Response Timeout
│ │
↓ ↓
Resume Cancel
LangGraph надає примітиви; бізнес-правила — це ваша справа.
Кілька контрольних точок та стрімінг
Агент розгортання може просити схвалення свого плану, а також ще раз перед запуском у продакшені.
START
↓
Analyze Code
↓
Generate Deployment Plan
↓
Human Approval #1
↓
Deploy to Staging
↓
Run Tests
↓
Human Approval #2
↓
Deploy Production
↓
END
Кожна контрольна точка зупиняє та відновлює один і той самий поток, залишаючи історію контрольних точок та переривань.
Thread
│
├── CP1
│
├── CP2
│
├── INTERRUPT
│
├── RESUME
│
├── CP3
│
├── INTERRUPT
│
├── RESUME
│
└── END
Це стійкий робочий процес, яким користуються люди та агент. До цього моменту кожен приклад використовував блокуючий виклик,
graph.invoke(...)
який повертається лише після завершення виконання або зупинки.
START → A → B → C → END
↓
RESULT
Інтерактивні додатки потребують оновлень статусу у момент їх виникнення, аж до подання запиту на схвалення.
START
↓
Planner Update ─────────→ UI
↓
Tool Call ──────────────→ UI
↓
Tool Result ────────────→ UI
↓
Approval Required ──────→ UI
Стрімінг передає ці події, щоб інтерфейс користувача міг відображати завершені кроки та поточне рішення.
┌──────────────────────────────────┐
│ Deployment Agent │
├──────────────────────────────────┤
│ │
│ ✓ Analyzed repository │
│ │
│ ✓ Generated deployment plan │
│ │
│ ✓ Staging tests passed │
│ │
│ ⚠ Production deployment ready │
│ │
│ Human approval required │
│ │
│ [ APPROVE ] [ REJECT ] │
│ │
└──────────────────────────────────┘
За цим екраном події надходять на фронтенд, а рішення повертається через Command(resume=...).
LangGraph
│
↓
Streaming
│
↓
Frontend
│
↓
Human Decision
│
↓
Command(resume=...)
│
↓
LangGraph
Повна модель виконання
У одній діаграмі: користувач ініціює виконання на певному потоці, статус переміщується між вузлами та редюсерами, записуються контрольні точки, маршрутизація вибирає наступний крок, а конфіденційні дії спрямовуються на переривання, яке вирішує людина.
USER
│
↓
graph.invoke()
│
↓
THREAD
│
↓
CHECKPOINTER
│
↓
STATE
│
↓
NODE
│
↓
STATE UPDATE
│
↓
REDUCER
│
↓
NEW STATE
│
↓
CHECKPOINT
│
↓
EDGE / ROUTING
│
↓
SENSITIVE ACTION?
/ \
NO YES
│ │
↓ ↓
NEXT NODE interrupt()
│
↓
PAUSED
│
↓
HUMAN
/ | \
/ | \
Approve Edit Reject
│ │ │
└────────┼────────┘
↓
Command(resume)
│
↓
SAME thread_id
│
↓
RESTORE CHECKPOINT
│
↓
CONTINUE GRAPH
│
↓
END
Як історія: надходить запит.
User Input
і починається виконання.
START
Вузли читають стан та повертають оновлення, редуктори їх об’єднують, чекпоїнти зберігають їх у межах потоку, а ребра визначають, що буде виконано далі. Граф може розгалужуватися, утворювати цикли чи викликати інструменти.
BRANCH
LOOP
CALL TOOLS
Коли потрібна допомога людини, переривання призупиняє виконання.
interrupt()
Людина реагує,
APPROVE
REJECT
EDIT
PROVIDE INPUT
команда продовження роботи продовжує виконання з збереженого потоку,
Command(resume=...)
і граф завершується.
END
Більшість проектів починаються з одного виклику моделі,
LLM
↓
Response
а закінчуються графом, який поєднує вузли LLM та інструментів, редуктори, чекпоїнти, механізми маршрутизації, переривання та команди.
USER
│
↓
START
│
↓
STATE
│
↓
NODE
│
┌──────┴──────┐
│ │
LLM TOOL
│ │
└──────┬──────┘
↓
STATE UPDATE
│
↓
REDUCER
│
↓
NEW STATE
│
↓
CHECKPOINT
│
↓
THREAD
│
↓
ROUTING
/ | \
/ | \
NODE LOOP INTERRUPT
│
↓
HUMAN
/ | \
Approve Edit Reject
\ | /
\ | /
↓
COMMAND
│
↓
RESUME
│
↓
NEXT NODE
│
↓
END
Чек-лист для продакшну
Зберігайте вузли фокусованими
Маленькі вузли з однією функцією легше тестувати, перезапускати та безпечно переривати,
Plan Node
Search Node
Validate Node
Execute Node
на відміну від одного вузла, який робить усе.
do_everything_agent()
Ретельно проектуйте стани та редуктори
Зберігайте лише те, що потрібно вузлам, адже все фіксується як контрольні точки та може бути показано перевіряючим. Ретельно обирайте редуктори для полів, які накопичують дані.
messages
events
results
observations
Робіть побічні ефекти ідемпотентними
З операціями, які не можна скасувати, потрібно бути обережними.
Send Email
Charge Card
Delete Resource
Deploy
Transfer Money
Перепробування та відновлення ніколи не повинні їх повторювати. Оскільки перерваний вузол запускається знову під час відновлення, розміщуйте операції, які не можна скасувати, після точки затвердження або у окремому вузлі, та використовуйте ключі ідемпотентності там, де це підтримують API.
Використовуйте надійне зберігання
Контрольні точки в пам’яті підходять для навчання; у продакшені потрібне надійне зберігання, що відповідає вашим вимогам до надійності.
Запишіть межі та обмеження
Чітко визначте їх для кожного робочого процесу,
What can AI do automatically?
What requires approval?
What can humans modify?
When does approval expire?
та вкажіть умови завершення циклів.
Maximum attempts
Timeouts
Validation
Failure paths
Escalation
Коли HITL є корисним
Людський огляд виправдовує себе у певних ситуаціях.
Cost of wrong action is high
Action is irreversible
Policy requires approval
Agent confidence is insufficient
Sensitive information is involved
Human judgment adds value
Розкидані скрізь, вони унеможливлюють автоматизацію та змушують оглядачів клацати далі, не читаючи.
Agent
↓
Ask Human
↓
Agent
↓
Ask Human
↓
Agent
↓
Ask Human
Кращий дизайн надає агенту автономну зону для планування та міркувань із одним кордоном перед виконанням дії.
AUTONOMOUS ZONE
┌───────────────────────┐
│ │
│ Plan → Search → Think │
│ │
└───────────┬───────────┘
│
↓
CONTROL BOUNDARY
│
↓
HUMAN
│
↓
APPROVED ACTION
Як взаємодіють шари
Виконання графа охоплює вузли, ребра та маршрутизацію;
Graph
Nodes
Edges
START
END
Loops
Conditional Routing
Керування станом охоплює оновлення та редуктори;
State
State Updates
Reducers
Messages
State Evolution
Стабільність даних охоплює контрольні точки, потоки та відновлення;
Checkpoints
Checkpointer
Threads
thread_id
State History
Recovery
А HITL додає переривання, команди та шаблони огляду.
interrupt()
Command
Pause
Resume
Approve
Reject
Edit
Human Control
Зібрані разом, вони утворюють одну систему обробки.
GRAPH
↓
STATE
↓
NODE
↓
UPDATE
↓
REDUCER
↓
CHECKPOINT
↓
THREAD
↓
ROUTING
↓
INTERRUPT
↓
HUMAN
↓
COMMAND
↓
RESUME
↓
END
Основні висновки
Лексика може здаватися перевантаженою,
StateGraph
MessagesState
Reducers
Checkpointers
Threads
Commands
Interrupts
Але кожен елемент вирішує одну частину єдиної мети: агент, який знає, діє, оновлює інформацію, приймає рішення, зберігає прогрес, зупиняється у потрібний момент, запитує людину та безпечно продовжує роботу.
Remember what it knows
↓
Perform some work
↓
Update what it knows
↓
Decide what to do next
↓
Persist its progress
↓
Pause when necessary
↓
Ask a human
↓
Resume safely
↓
Continue until complete
- Стан – це те, що знає агент; вузли – це те, що він робить; ребра – це напрямок його руху; редуктори – це способи зміни стану.
- Чекпоїнти фіксують місце, де знаходився агент; потоки вказують, до якої історії належить певна операція.
interrupt()визначає місце зупинки та запиту;Commandвказує, як продовжити роботу, завжди в тому самому потоці.- Перервані вузли перезапускаються під час продовження роботи, тому необхідно зберігати незворотні наслідки після точки схвалення.
- Перевірку слід розміщувати на справжніх межах керування з чіткими правилами таймауту та ескалації.