140 lines
3.6 KiB
Markdown
140 lines
3.6 KiB
Markdown
# Human‑in‑the‑Loop Agent via Middleware (LangGraph)
|
||
|
||
This repository contains a minimal example of a **Human‑in‑the‑Loop** agent built on top of 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 example uses OpenAI’s API (or any compatible LLM). Make sure you have an API key set in the environment variable `OPENAI_API_KEY`.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [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 |
|
||
|---------|-------------|
|
||
| **Human‑in‑the‑Loop** | 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 in‑memory checkpoint (`MemorySaver`) to preserve state across interruptions. |
|
||
|
||
---
|
||
|
||
## Prerequisites
|
||
|
||
- Python 3.10+
|
||
- An OpenAI API key (or any compatible LLM endpoint)
|
||
|
||
```bash
|
||
export OPENAI_API_KEY="sk-..."
|
||
```
|
||
|
||
---
|
||
|
||
## 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
|
||
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
||
```
|
||
|
||
3. **Install dependencies**
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
*If you don’t have a `requirements.txt`, create one with the following content:*
|
||
|
||
```text
|
||
langchain-openai>=0.2.0
|
||
langgraph>=0.1.0
|
||
```
|
||
|
||
---
|
||
|
||
## Running the Agent
|
||
|
||
### Interactive Demo (`solution.py`)
|
||
|
||
The main script demonstrates how to start the agent and handle interruptions.
|
||
|
||
```bash
|
||
python solution.py
|
||
```
|
||
|
||
**What happens:**
|
||
|
||
1. The user enters a prompt (e.g., “What’s the weather in Paris on 2024‑12‑01?”).
|
||
2. The agent processes the request, decides it needs to call `get_weather`, and pauses.
|
||
3. The tool request is printed:
|
||
|
||
```
|
||
Tool requested: get_weather
|
||
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`)
|
||
|
||
Run the test suite to verify that the interruption logic works as expected:
|
||
|
||
```bash
|
||
pytest tests/test_solution.py
|
||
```
|
||
|
||
The tests simulate a user approving the tool call automatically and check that the final output contains the weather string.
|
||
|
||
---
|
||
|
||
## Example Usage
|
||
|
||
Below is a quick snippet you can paste into a Python REPL or another script to see the agent in action:
|
||
|
||
```python
|
||
from solution import agent, memory # assuming solution.py defines them
|
||
|
||
# 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, you’ll see the same interruption prompt as described above.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
MIT © 2026. Feel free to fork and adapt for your own projects. |