110 lines
3.0 KiB
Markdown
110 lines
3.0 KiB
Markdown
# Human‑in‑the‑loop (Interrupt / Resume) – LangGraph Demo
|
||
|
||
This repository contains a minimal example of a **LangGraph** that pauses execution to ask the user for confirmation via a custom interrupt.
|
||
The graph demonstrates how to:
|
||
|
||
* Define a typed state with fields that will be filled by a human.
|
||
* Trigger an interrupt from a node, passing a structured payload (`type`, `question`, `allow_responds`).
|
||
* Handle the interrupt in a loop: display the question in the console (using *questionary*), capture the answer and resume the graph.
|
||
|
||
---
|
||
|
||
## 📦 Installation
|
||
|
||
```bash
|
||
# Create a virtual environment if you wish
|
||
python -m venv .venv
|
||
source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
|
||
|
||
# Install dependencies
|
||
pip install langgraph questionary
|
||
```
|
||
|
||
> **Tip**: If you plan to extend the graph with LLM calls, add `langchain` and an appropriate provider (e.g., `langchain-openai`) to your requirements.
|
||
|
||
---
|
||
|
||
## 📁 Project Structure
|
||
|
||
```text
|
||
.
|
||
├── interrupt_graph.py # The LangGraph implementation
|
||
└── README.md # This file
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Running the Example
|
||
|
||
The graph is executed in a simple loop that keeps running until the user chooses to stop.
|
||
Run it with:
|
||
|
||
```bash
|
||
python interrupt_graph.py
|
||
```
|
||
|
||
You should see something like:
|
||
|
||
```
|
||
[Graph] Starting new run...
|
||
[Interrupt] type: confirm
|
||
Question: Уверены, что хотите продолжить?
|
||
Options: approve / reject
|
||
|
||
Your choice: approve
|
||
[Graph] Resuming after interrupt...
|
||
|
||
[Graph] Run finished. Final state:
|
||
{'human_value': 'approve', 'foo': None}
|
||
```
|
||
|
||
If you answer `reject`, the graph will still resume but with a different value.
|
||
|
||
---
|
||
|
||
## 📄 Example Usage in Code
|
||
|
||
```python
|
||
# interrupt_graph.py (excerpt)
|
||
|
||
from langgraph.types import interrupt
|
||
|
||
def node_with_interrupt(state: GraphState) -> GraphState:
|
||
if state.get("human_value") is not None:
|
||
return state
|
||
|
||
payload = {
|
||
"type": "confirm",
|
||
"question": "Уверены, что хотите продолжить?",
|
||
"allow_responds": ["approve", "reject"],
|
||
}
|
||
# Pause the graph until a human responds
|
||
return interrupt(payload)
|
||
```
|
||
|
||
The main loop in `interrupt_graph.py` handles this payload:
|
||
|
||
```python
|
||
while True:
|
||
result = graph.run(state=state, config=config)
|
||
if isinstance(result, Command):
|
||
# Show question and get answer
|
||
choice = questionary.select(
|
||
result.payload["question"],
|
||
choices=result.payload["allow_responds"]
|
||
).ask()
|
||
state["human_value"] = choice
|
||
continue # resume graph
|
||
else:
|
||
break # finished
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 What You Can Learn
|
||
|
||
* How to **pause** a LangGraph node and wait for user input.
|
||
* How to structure the interrupt payload so that it can be rendered in any UI (console, web, etc.).
|
||
* The pattern of looping over `graph.run()` until no more `Command` objects are returned.
|
||
|
||
Feel free to fork this repository and experiment with different interrupt types or add LLM calls to make the graph more complex! |