120 lines
3.0 KiB
Markdown
120 lines
3.0 KiB
Markdown
# Human‑in‑the‑Loop Agent via Middleware
|
||
|
||
This repository contains a minimal example of an **LLM agent** that pauses every time it wants to call an external tool and asks the user for confirmation (`approve` or `reject`).
|
||
The pause is implemented with LangChain’s built‑in `HumanInTheLoopMiddleware`, which automatically generates the prompt, captures the user input, and resumes execution via a `Command`.
|
||
|
||
> **Why use middleware?**
|
||
> Unlike the `interrupt_before=['tools']` approach that requires manual handling of interruptions, the middleware handles everything internally: it creates the confirmation request, processes the response, and resumes the agent with the chosen decision.
|
||
|
||
---
|
||
|
||
## 📦 Installation
|
||
|
||
```bash
|
||
# Create a virtual environment (optional but recommended)
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||
|
||
# Install required packages
|
||
pip install langchain langgraph openai rich
|
||
```
|
||
|
||
> **OpenAI API key**
|
||
> The example uses an OpenAI model. Set your key in the environment:
|
||
|
||
```bash
|
||
export OPENAI_API_KEY="sk-…"
|
||
```
|
||
|
||
---
|
||
|
||
## 📁 Project Structure
|
||
|
||
| File | Purpose |
|
||
|------|---------|
|
||
| `solution.py` | Main script that creates the agent, defines a simple tool (`get_weather`), and runs an interactive loop. |
|
||
|
||
> The repository contains only one Python file for clarity.
|
||
|
||
---
|
||
|
||
## 🚀 Running the Example
|
||
|
||
```bash
|
||
python solution.py
|
||
```
|
||
|
||
You will see something like:
|
||
|
||
```
|
||
User: What's the weather in London?
|
||
Agent: (pauses) Подтвердите вызов инструмента get_weather
|
||
- approve
|
||
- reject
|
||
Your choice:
|
||
```
|
||
|
||
Type `approve` to let the agent call the tool, or `reject` to skip it.
|
||
After your decision, the agent continues its reasoning and eventually returns a final answer.
|
||
|
||
---
|
||
|
||
## 🛠️ Customizing
|
||
|
||
### Changing the Tool
|
||
|
||
Replace the `get_weather` function with any other LangChain tool:
|
||
|
||
```python
|
||
@tool
|
||
def get_time() -> str:
|
||
"""Return current UTC time."""
|
||
return datetime.utcnow().isoformat()
|
||
```
|
||
|
||
Add it to the `tools` list when creating the agent.
|
||
|
||
### Adjusting Middleware Settings
|
||
|
||
- **Interrupt on specific decisions**
|
||
```python
|
||
interrupt_on={
|
||
"get_weather": {"allowed_decisions": ["approve", "reject"]} # no edit option
|
||
}
|
||
```
|
||
|
||
- **Custom prompt prefix**
|
||
```python
|
||
description_prefix="Please confirm the tool call:"
|
||
```
|
||
|
||
### Using a Different LLM
|
||
|
||
Swap `llm` for any LangChain-compatible model (e.g., GPT‑4o, Claude, etc.):
|
||
|
||
```python
|
||
from langchain_openai import ChatOpenAI
|
||
llm = ChatOpenAI(model_name="gpt-4o-mini")
|
||
```
|
||
|
||
---
|
||
|
||
## 📖 Example Interaction
|
||
|
||
```
|
||
User: Tell me the weather in Paris.
|
||
Agent: (pauses) Подтвердите вызов инструмента get_weather
|
||
- approve
|
||
- reject
|
||
Your choice: approve
|
||
Agent: The current temperature in Paris is 18°C with clear skies.
|
||
Final answer: It’s sunny and mild in Paris today.
|
||
```
|
||
|
||
---
|
||
|
||
## 📜 License
|
||
|
||
This project is provided under the MIT license. Feel free to adapt it for your own experiments.
|
||
|
||
--- |