Human-in-the-Loop через middleware: README.md

This commit is contained in:
2026-05-28 05:48:01 +00:00
parent 1a6ccc4678
commit 6f46f73dcd
@@ -1,140 +1,86 @@
# HumanintheLoop Agent via Middleware (LangGraph) # HumanintheLoop Agent with LangGraph
This repository contains a minimal example of a **HumanintheLoop** agent built on top of LangGraph. This repository contains a minimal example of a **HumanintheLoop** (HITL) agent built on top of [LangGraph](https://github.com/langchain-ai/langgraph).
The agent pauses whenever it needs to call an external tool, prints the tool request and waits for a user decision (`approve` or `reject`). After the decision is supplied, execution resumes automatically. The agent pauses whenever it needs to call an external tool, presents the tool output to the user and waits for a decision (`approve` or `reject`). After the decision is made the conversation continues automatically.
> ⚠️ The example uses OpenAIs API (or any compatible LLM). Make sure you have an API key set in the environment variable `OPENAI_API_KEY`. > **⚠️ Prerequisites** The example uses OpenAIcompatible APIs.
> Make sure you have an API key set in the environment variable `OPENAI_API_KEY`.
--- ---
## Table of Contents ## 📦 Installation
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Running the Agent](#running-the-agent)
- [Interactive Demo (`solution.py`)](#interactive-demo-solutionpy)
- [Unit Tests (`tests/test_solution.py`)](#unit-tests-test_solutionpy)
- [Example Usage](#example-usage)
- [License](#license)
---
## Features
| Feature | Description |
|---------|-------------|
| **HumanintheLoop** | Agent stops before calling any tool, prints the request and waits for user input. |
| **Interrupts via `interrupt_before=["tools"]`** | Configurable interruption point in LangGraph. |
| **Tool Example** | Simple `get_weather(city, date)` function that returns a mock weather string. |
| **Checkpointing** | Uses an inmemory checkpoint (`MemorySaver`) to preserve state across interruptions. |
---
## Prerequisites
- Python 3.10+
- An OpenAI API key (or any compatible LLM endpoint)
```bash ```bash
export OPENAI_API_KEY="sk-..." # 1️⃣ Clone the repo (or copy solution.py into a new folder)
``` git clone https://github.com/your-username/hitl-langgraph.git
cd hitl-langgraph
--- # 2️⃣ Create and activate a virtual environment (optional but recommended)
## Installation
1. **Clone the repository**
```bash
git clone https://github.com/yourusername/human-in-loop-langgraph.git
cd human-in-loop-langgraph
```
2. **Create a virtual environment (optional but recommended)**
```bash
python -m venv .venv python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate source .venv/bin/activate # Windows: .\.venv\Scripts\activate
# 3️⃣ Install dependencies
pip install --upgrade pip
pip install langchain-openai langgraph langchain-tools
``` ```
3. **Install dependencies** > **Tip** If you want to use a different LLM (e.g., Anthropic, Gemini), replace the `ChatOpenAI` import with the appropriate wrapper and adjust the model name.
```bash
pip install -r requirements.txt
```
*If you dont have a `requirements.txt`, create one with the following content:*
```text
langchain-openai>=0.2.0
langgraph>=0.1.0
```
--- ---
## Running the Agent ## 🚀 Running the Agent
### Interactive Demo (`solution.py`) The main logic is in `solution.py`.
Run it directly:
The main script demonstrates how to start the agent and handle interruptions.
```bash ```bash
python solution.py python solution.py
``` ```
**What happens:** ### What Happens?
1. The user enters a prompt (e.g., “Whats the weather in Paris on 20241201?”). 1. The agent starts a conversation.
2. The agent processes the request, decides it needs to call `get_weather`, and pauses. 2. When it decides to call the `get_weather` tool, the execution pauses.
3. The tool request is printed: 3. The tool output (e.g., `"Погода в Москва на 2024-05-28: солнечно 25°C."`) is printed to the console.
4. You are prompted to type **approve** or **reject**:
``` - `approve`: the agent resumes with the tool result as normal input.
Tool requested: get_weather - `reject`: the agent receives a `ToolMessage` indicating rejection and can decide what to do next.
Arguments: {'city': 'Paris', 'date': '2024-12-01'}
```
4. You are prompted to type `approve` or `reject`.
5. After your decision, the agent resumes and prints the final answer.
--- ---
### Unit Tests (`tests/test_solution.py`) ## 🔧 Example Interaction
Run the test suite to verify that the interruption logic works as expected: ```text
$ python solution.py
```bash Agent: Какую погоду вы хотите узнать?
pytest tests/test_solution.py User: Москва на 2024-05-28
Agent (calling tool): get_weather(city='Москва', date='2024-05-28')
Tool output: Погода в Москва на 2024-05-28: солнечно 25°C.
Please type 'approve' or 'reject': approve
Agent: Спасибо! Как ещё могу помочь?
``` ```
The tests simulate a user approving the tool call automatically and check that the final output contains the weather string. If you type `reject`, the agent will receive a rejection message and can, for example, ask for clarification.
--- ---
## Example Usage ## 📁 Project Structure
Below is a quick snippet you can paste into a Python REPL or another script to see the agent in action: | File | Purpose |
|------|---------|
```python | `solution.py` | Full implementation of the HITL agent. |
from solution import agent, memory # assuming solution.py defines them | `README.md` | This documentation file. |
# Start a new thread/session
config = {"configurable": {"thread_id": "demo-session"}}
# Invoke with a user message
response = agent.invoke(
{"messages": [{"role": "user", "content": "What's the weather in Tokyo on 2025-01-15?"}]},
config=config,
)
print("\nFinal response:")
print(response["messages"][-1]["content"])
```
When you run this, youll see the same interruption prompt as described above.
--- ---
## License ## 🛠️ Customization
MIT © 2026. Feel free to fork and adapt for your own projects. - **Add more tools** Decorate any function with `@tool` and add it to the `tools=[...]` list.
- **Change prompt** Edit `system_prompt` in `create_react_agent`.
- **Persist memory** Replace `MemorySaver()` with a filebased or database checkpoint if you need persistence across runs.
---
## 📜 License
MIT © 2026. Feel free to fork and adapt for your own projects!