A small, reusable framework for building LLM agents on top of LangGraph — plus two example applications that show different ways to put agents to work, including an experimental "agent-as-the-backend" web app where LLM agents implement the REST API and generate the UI at request time.
Agents are backed by Azure OpenAI and call tools you provide; one set of example tools does full CRUD against Azure AI Search.
A thin, composable layer over LangGraph's StateGraph + ToolNode agent loop, with checkpointed memory and human-in-the-loop support:
Agent— the base class. Wires a model, a list of tools, and a system prompt into a compiled LangGraph graph (agent → tools → agent) with aMemorySavercheckpointer. Supports interrupts so a tool can pause and ask a human, via pluggablemessage_listener/user_input_listenercallbacks.CommandLineAgent— anAgentwired for interactive terminal chat: it prints the agent's progress and reads user input from the console (including resuming after an interrupt).WorkflowAgent— anAgentfor non-interactive, programmatic use.run_workflow(data)feeds JSON in and returns the parsed JSON result — handy for using an agent as a step inside a larger pipeline.HTMLAgent— anAgentspecialized to return a complete, renderable HTML page.
tools.py— interaction primitives:ask_for_instruction(pauses for human input via a LangGraphinterrupt) andreport_progress.ai_search_tools.py— Azure AI Search operations: search, create/update/delete documents, and list/create/delete/describe indexes.html_tools.py— helpers for generating Bootstrap HTML (templates, buttons, search bars, list rendering).
-
main.py— a command-line Azure AI Search assistant. ACommandLineAgentis given the AI Search tools and a system prompt, so you can manage indexes and documents in plain English ("find documents about X", "create an index with these fields", "delete that document"). -
app.py— an experimental Flask app where agents are the backend. Instead of hand-written route handlers, each request is handed to an agent:POST /api/<path>— aWorkflowAgentinterprets the path + payload, picks the right AI Search tool (search/create/update/delete), runs it, and returns JSON.GET /ui/<path>— anHTMLAgentgenerates a complete Bootstrap web page for the requested view on the fly.
It's a deliberately exploratory pattern — useful for prototyping and for thinking about how much of an API an agent can stand in for — not a production design.
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtCreate a .env file in the project root (it is gitignored):
# Azure OpenAI
AZURE_OPENAI_ENDPOINT=your_azure_openai_endpoint
AZURE_OPENAI_KEY=your_azure_openai_key
AZURE_OPENAI_DEPLOYMENT_NAME=your_deployment_name
AZURE_OPENAI_API_VERSION=your_api_version
# Azure AI Search (only needed for the AI Search tools / example apps)
AZURE_SEARCH_SERVICE_ENDPOINT=your_azure_search_endpoint
AZURE_SEARCH_INDEX_NAME=your_index_name
AZURE_SEARCH_API_KEY=your_azure_search_api_keypython main.pypython app.py # serves on http://127.0.0.1:5000 (debug)
# then hit, e.g. POST http://127.0.0.1:5000/api/search or GET http://127.0.0.1:5000/ui/searchimport os
from dotenv import load_dotenv
from langchain_openai import AzureChatOpenAI
from agents import CommandLineAgent
from tools import ask_for_instruction, report_progress
load_dotenv()
model = AzureChatOpenAI(
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
api_key=os.getenv("AZURE_OPENAI_KEY"),
deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"),
temperature=0,
)
agent = CommandLineAgent(
model=model,
tools=[ask_for_instruction, report_progress],
agent_prompt="You are a helpful assistant that can provide information.",
)
agent.run()To use an agent programmatically instead, swap CommandLineAgent for WorkflowAgent and call
agent.run_workflow({...}) to get a parsed JSON result back.
- Python 3.10+
- An Azure OpenAI deployment (and an Azure AI Search service for the search tools)
This is a personal, work-in-progress project for exploring agent patterns with LangGraph. The agent base classes are reusable; the example apps — especially the agent-as-the-backend Flask app — are experiments meant for learning and prototyping rather than production use.
MIT — see LICENSE.