# Human‑in‑the‑Loop Agent via Middleware This repository contains a minimal example of an LLM agent that pauses whenever it wants to call a tool and asks the user for approval before proceeding. The core idea is to use **`HumanInTheLoopMiddleware`** from LangChain, which intercepts every tool invocation, prints a prompt with the action details, and waits for the user to respond (`approve`, `reject`, or optionally edit the request). > **Why this matters** – In many real‑world scenarios you want an LLM to ask for human confirmation before performing potentially sensitive actions (e.g., sending emails, accessing databases, calling external APIs). --- ## Table of Contents - [Project Structure](#project-structure) - [Installation](#installation) - [Running the Agent](#running-the-agent) - [Interactive Mode](#interactive-mode) - [Scripted Example](#scripted-example) - [Example Usage](#example-usage) - [Extending the Agent](#extending-the-agent) --- ## Project Structure ``` ├── solution.py # Main script with the agent implementation └── README.md # This file ``` `solution.py` contains: 1. **LLM configuration** – uses `ChatOpenAI`. 2. **A simple tool** (`get_weather`) that returns a fake weather string. 3. **Memory checkpoint** via `MemorySaver`. 4. **Agent creation** with `create_react_agent` and the middleware. 5. **Execution loop** that keeps asking for user input until the conversation ends. --- ## Installation 1. **Clone the repo** ```bash git clone https://github.com/your-username/human-in-the-loop-agent.git cd human-in-the-loop-agent ``` 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 --upgrade pip pip install langchain langgraph openai ``` 4. **Set your OpenAI API key** ```bash export OPENAI_API_KEY="sk-..." # Windows: setx OPENAI_API_KEY "sk-..." ``` --- ## Running the Agent ### Interactive Mode Simply run the script: ```bash python solution.py ``` You will see a prompt like: ``` Agent wants to call tool `get_weather` with arguments: city = "Moscow" date = "2025-10-01" Please type one of: approve / reject (or edit ) > ``` Type **`approve`** to let the agent proceed, or **`reject`** to stop it. If you want to modify the arguments before approval, use `edit city=London date=2025-12-25`. The conversation continues until the user types `stop` or the agent finishes its plan. ### Scripted Example You can also run a quick demo that automatically approves all calls: ```bash python - <<'PY' from solution import agent, llm, memory # Override middleware to auto‑approve for demonstration agent.middleware[0].interrupt_on = {"get_weather": False} print(agent.run("What's the weather in New York tomorrow?")) PY ``` --- ## Example Usage ```bash $ python solution.py User: What's the weather in Paris next Friday? Agent wants to call tool `get_weather` with arguments: city = "Paris" date = "2025-10-06" Please type one of: approve / reject (or edit ) > approve Assistant: Погода в Париже на 2025‑10‑06: солнечно 25°C. User: Thank you! ``` --- ## Extending the Agent 1. **Add more tools** – decorate any function with `@tool` and add it to the `tools` list in `create_react_agent`. 2. **Change the interrupt policy** – modify `interrupt_on` dict (e.g., `{ "get_weather": True, "send_email": False }`). 3. **Persist conversation state** – replace `MemorySaver()` with a database checkpoint if you need long‑term memory. 4. **Custom prompts** – tweak `system_prompt` or add a custom `description_prefix`. --- Happy hacking! 🚀