# 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.