4.3 KiB
Human‑in‑the‑Loop Middleware Demo
This repository contains a minimal LangChain/LangGraph example that demonstrates how to pause an agent whenever it wants to call a tool and ask the user for approval (approve / reject).
The pausing logic is handled by HumanInTheLoopMiddleware, which automatically generates a prompt, receives the user’s decision, and resumes execution via a Command(resume={…}).
Why this matters – In many real‑world scenarios an LLM should not act autonomously. By inserting a human checkpoint you can keep control over every tool call, ensuring safety, compliance or simply giving the user a chance to correct mistakes.
📦 Installation
# 1️⃣ Clone the repo
git clone https://github.com/your‑org/human‑in‑the‑loop-demo.git
cd human‑in‑the‑loop-demo
# 2️⃣ Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3️⃣ Install dependencies
pip install -r requirements.txt
Requirements
- Python ≥ 3.10
langchain(>=0.2)langgraph(>=0.1)openaior any LLM provider you prefer
The requirements.txt file contains the exact versions used for this demo.
📁 Project Structure
.
├── agent.py # Agent definition with HumanInTheLoopMiddleware
├── main.py # CLI entry point – runs the agent interactively
├── tools.py # Example tool(s) (e.g., get_weather)
└── README.md # This file
🚀 Running the Demo
1️⃣ Start the Agent
python main.py
You will see a prompt like:
Assistant: What would you like to do?
User: Tell me the weather in London.
Assistant: (Thinking...)
When the agent decides to call get_weather, it pauses and prints:
Human-in-the-loop checkpoint:
The assistant wants to execute tool 'get_weather' with arguments {'location': 'London'}.
Please type one of the following decisions: approve / reject
Type approve to let the tool run, or reject to cancel it.
After your decision, the agent continues:
Assistant: The weather in London is 18°C and sunny.
2️⃣ Using a Different Tool
If you want to test another tool (e.g., get_time), add it to tools.py, import it in agent.py, and adjust the middleware configuration accordingly.
📚 Example Usage
# main.py
from agent import agent
def run():
print("Welcome! Type 'exit' to quit.")
while True:
user_input = input("\nUser: ")
if user_input.lower() == "exit":
break
response = agent.invoke({"input": user_input})
print(f"Assistant: {response['output']}")
if __name__ == "__main__":
run()
# agent.py
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import MemorySaver
from tools import get_weather # <-- your tool(s)
memory = MemorySaver()
agent = create_agent(
model="gpt-4o-mini", # or any LLM you have access to
tools=[get_weather],
system_prompt="You are a helpful assistant.",
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={"get_weather": True},
description_prefix="Please confirm the tool call:",
),
],
checkpointer=memory,
)
# tools.py
from langchain.tools import BaseTool
class GetWeather(BaseTool):
name = "get_weather"
description = "Returns current weather for a location."
args_schema = ... # define your schema here
def _run(self, location: str) -> str:
# Dummy implementation – replace with real API call
return f"The weather in {location} is 18°C and sunny."
get_weather = GetWeather()
🔧 Customization Tips
| Feature | How to change |
|---|---|
| Allowed decisions | interrupt_on={"get_weather": {"allowed_decisions": ["approve", "reject"]}} |
| Prompt prefix | Change description_prefix in the middleware. |
| Tool list | Add or remove tools in the tools=[...] array. |
| LLM model | Pass a different model name or a custom LLM instance to create_agent. |
📜 License
This project is licensed under the MIT License – see the LICENSE file for details.