diff --git a/README.md b/README.md index 9e04e50..9706b2d 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,63 @@ -# Minimal ASGI Middleware +# Human‑in‑the‑Loop Agent -## Overview -This repository contains a simple ASGI middleware implementation that can be used with frameworks such as FastAPI or Starlette. It logs the path of every incoming HTTP request. +This repository implements a simple command‑line agent that pauses before each tool call and asks the user to approve or reject the action. It uses **LangChain** and **LangGraph**'s `HumanInTheLoopMiddleware`. -## Installation -No external dependencies are required. Just copy the files into your project. +## Prerequisites + +- Python 3.11+ (tested with 3.11 and 3.12) +- An OpenAI API key or a local LLM compatible with the OpenAI API (e.g., Ollama) + +## Setup ```bash -# If you prefer a virtual environment +# Create a virtual environment python -m venv .venv source .venv/bin/activate -# Install any dependencies (none for this minimal example) -# pip install -r requirements.txt +# Install dependencies +pip install -r requirements.txt +``` + +## Configuration + +*OpenAI API key* + +```bash +export OPENAI_API_KEY="YOUR_KEY" +``` + +*Local model (e.g., Ollama)* + +If you run a local model, edit **agent.py** and uncomment/adjust the `base_url` and `api_key` arguments in the `ChatOpenAI` constructor: + +```python +ChatOpenAI( + base_url="http://localhost:11434/v1", + api_key="ollama", + model="llama3", +) ``` ## Usage -Import the `get_middleware` helper and wrap your ASGI application: - -```python -from fastapi import FastAPI -from middleware import get_middleware - -app = FastAPI() -app = get_middleware(app) - -@app.get("/") -async def root(): - return {"message": "Hello World"} -``` - -Run the app with Uvicorn or any ASGI server: ```bash -uvicorn main:app --reload +python agent.py ``` -You should see log messages for each request in the console. +You will be prompted to enter a question. The agent will invoke the `get_weather` tool and pause for confirmation. + +``` +Enter your question: What is the weather in Kazan today? + +Action 1: get_weather +Arguments: {'city': 'Kazan', 'date': 'today'} +Decision (a=approve, r=reject): a + +Agent response: +Weather in Kazan on today +``` + +*If you reject an action, you will be asked for a reason, which is sent back to the agent as feedback.* ## License MIT