CLI tool to create new AI agent projects based on LangGraph and FastAPI
Project description
FastAPI Base Project
A modular FastAPI project template with JWT authentication, SQLAlchemy ORM, Alembic migrations, and LangGraph AI agents.
Purpose
This project serves as a production-ready template for building AI agents with LangGraph and exposing them through FastAPI endpoints. It eliminates the need to configure authentication, database management, API routing, and agent infrastructure from scratch.
Key Goals:
- Rapid Agent Development: Start building LangGraph agents immediately without boilerplate setup
- Production-Ready API: Pre-configured FastAPI with JWT authentication, CORS, and comprehensive error handling
- State Persistence: Built-in PostgreSQL checkpointing for maintaining conversation history
- Developer Experience: Hot-reloading with
langgraph dev, interactive API docs, and comprehensive testing tools - Scalability: Modular architecture that scales from simple chatbots to complex multi-agent systems
Whether you're prototyping a conversational AI, building a production agent system, or learning LangGraph, this template provides everything you need to get started quickly.
Features
- FastAPI - Modern, fast web framework for building APIs
- SQLAlchemy ORM - Powerful database ORM with support for multiple databases
- JWT Authentication - Secure authentication using JSON Web Tokens
- Alembic - Database migration management
- LangGraph Agents - AI agents with state persistence using LangGraph
- Modular Architecture - Clean separation of concerns with routers, services, and models
- Pydantic Schemas - Request/response validation and serialization
- CORS Support - Cross-Origin Resource Sharing enabled
- Base Models - Pre-built User and Profile models with relationships
Project Structure
agent-base-project/
├── src/
│ ├── main.py # Application entry point
│ ├── core/ # Core configuration and security
│ │ ├── config.py # Settings and environment variables
│ │ ├── security.py # JWT and password hashing utilities
│ │ └── constants.py # Application constants
│ ├── db/ # Database configuration
│ │ ├── database.py # SQLAlchemy engine setup
│ │ ├── session.py # Database session management
│ │ └── checkpoint.py # LangGraph checkpoint configuration
│ ├── models/ # SQLAlchemy ORM models
│ │ ├── base.py # Declarative base
│ │ ├── user.py # User model
│ │ └── profile.py # Profile model
│ ├── schemas/ # Pydantic schemas
│ │ ├── user.py # User schemas (Create, Update, Read)
│ │ ├── profile.py # Profile schemas
│ │ ├── token.py # Authentication token schemas
│ │ └── common.py # Common/shared schemas
│ ├── services/ # Business logic layer
│ │ ├── auth_service.py # Authentication logic
│ │ ├── user_service.py # User management logic
│ │ └── profile_service.py # Profile management logic
│ ├── routers/ # API endpoints
│ │ ├── auth.py # Authentication routes
│ │ ├── chatbot.py # Chatbot/Agent routes
│ │ ├── users.py # User management routes
│ │ └── profiles.py # Profile routes
│ └── dependencies.py # Shared dependencies (auth, etc.)
├── agents/ # LangGraph agents
│ └── basic/ # Basic chatbot agent
│ ├── agent.py # Agent graph definition
│ ├── state.py # Agent state schema
│ └── nodes/ # Agent nodes
│ └── chatbot/ # Chatbot node
│ ├── node.py # Node implementation
│ └── prompt.py # System prompt
├── alembic/ # Database migrations
├── tests/ # Test suite
├── .env.example # Environment variables template
├── langgraph.json # LangGraph configuration
├── requirements.txt # Python dependencies
└── README.md # This file
Setup Instructions
Follow these steps to set up and run the project:
Step 1: Create Virtual Environment
# Create virtual environment
python -m venv venv
Step 2: Activate Virtual Environment
On Windows:
venv\Scripts\activate
On Linux/Mac:
source venv/bin/activate
Step 3: Install Dependencies
pip install -r requirements.txt
Step 4: Configure Environment Variables
On Windows:
copy .env.example .env
On Linux/Mac:
cp .env.example .env
Then edit the .env file with your configuration:
# Database Configuration
DATABASE_URL=sqlite:///./app.db
# JWT Configuration
SECRET_KEY=your-super-secret-key-here-change-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# OpenAI Configuration (Required for LangGraph Agent)
OPENAI_API_KEY=sk-your-openai-api-key-here
# LangSmith Configuration (Optional - for tracing and monitoring)
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=lsv2_xxx
Generate a secure SECRET_KEY:
# Using openssl
openssl rand -hex 32
# Or using Python
python -c "import secrets; print(secrets.token_hex(32))"
Important: You need to set your OpenAI API key to use the chatbot agent. Get your API key from OpenAI Platform.
Step 5: Initialize Database
Create the initial database migration:
alembic revision --autogenerate -m "initial migration"
Apply the migration to create tables:
alembic upgrade head
Note: The application also has
Base.metadata.create_all(bind=engine)insrc/main.pywhich will create tables automatically if they don't exist. However, using Alembic migrations is recommended for production and better database version control.
Step 6: Run the Application
Option 1: Using the run script
python run.py
Option 2: Using uvicorn directly
# Development mode with auto-reload
uvicorn src.main:app --reload
# Production mode
uvicorn src.main:app --host 0.0.0.0 --port 8000
The API will be available at:
- URL: http://localhost:8000
- Swagger Documentation: http://localhost:8000/docs
- ReDoc Documentation: http://localhost:8000/redoc
Alternative Setup Methods
Using Docker Compose
If you prefer using Docker:
docker-compose up
This will start both the application and a PostgreSQL database.
API Endpoints
Root
-
GET /- Root endpoint, returns API information- No authentication required
- Returns project name, status, and docs link
-
GET /health- Health check endpoint- No authentication required
- Returns health status
Authentication (/auth)
-
POST /auth/register- Register a new user- Body:
{ "username", "email", "password", "first_name"?, "last_name"? } - Returns: User object (without password)
- Status: 201 Created
- Automatically creates a Profile for the user
- Validates email format and password strength (min 8 chars)
- Returns 400 if email or username already exists
- Body:
-
POST /auth/token- Login and get JWT access token- Body: Form data with
username(email) andpassword - Returns:
{ "access_token", "token_type": "bearer" } - Status: 200 OK
- Returns 401 if credentials are invalid
- Updates user's
last_logintimestamp - Token expires according to
ACCESS_TOKEN_EXPIRE_MINUTESsetting
- Body: Form data with
Users (/users)
🔒 All user endpoints require authentication (Bearer token)
-
GET /users/me- Get current authenticated user information- Returns: Complete user object with all fields
- Status: 200 OK
-
GET /users/{id}- Get user by ID- Returns: User object
- Status: 200 OK
- Permissions: Users can only view their own profile unless they are staff/superuser
- Returns 403 if insufficient permissions
- Returns 404 if user not found
-
PATCH /users/{id}- Update user information- Body: Any of
{ "username", "email", "password", "first_name", "last_name", "is_active" } - Returns: Updated user object
- Status: 200 OK
- Permissions: Users can only update their own profile unless they are superuser
- Regular users cannot modify
is_activefield - Password will be automatically hashed if provided
- Returns 403 if insufficient permissions
- Returns 404 if user not found
- Body: Any of
Profiles (/profiles)
🔒 All profile endpoints require authentication (Bearer token)
-
GET /profiles/me- Get current user's profile- Returns: Profile object with
time_zone,language,preferences, timestamps - Status: 200 OK
- Returns 404 if profile not found (shouldn't happen if created with user)
- Returns: Profile object with
-
PATCH /profiles/me- Update current user's profile- Body: Any of
{ "time_zone", "language", "preferences", "is_active" } - Returns: Updated profile object
- Status: 200 OK
preferencesfield can store JSON string for custom settings- Returns 404 if profile not found
- Body: Any of
Chatbot (/chatbot)
🔒 All chatbot endpoints require authentication (Bearer token)
-
POST /chatbot- Send a message to the chatbot agent- Body:
{ "message": "your message here" } - Returns: String with the agent's response
- Status: 200 OK
- Uses LangGraph agent with state persistence (thread_id: "1")
- Maintains conversation history across requests
- Body:
-
POST /chatbot/stream- Send a message and receive streaming response- Body:
{ "message": "your message here" } - Returns: Server-Sent Events (SSE) stream with agent's response chunks
- Status: 200 OK
- Content-Type:
text/event-stream - Uses LangGraph agent with state persistence (thread_id: "2")
- Streams response in real-time as it's generated
- Body:
Usage Examples
1. Register a New User
curl -X POST "http://localhost:8000/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "john_doe",
"email": "john@example.com",
"password": "securepass123",
"first_name": "John",
"last_name": "Doe"
}'
Response (201 Created):
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"is_active": true,
"is_staff": false,
"is_superuser": false,
"date_joined": "2024-01-15T10:30:00Z",
"last_login": null
}
2. Login and Get Token
curl -X POST "http://localhost:8000/auth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=john@example.com&password=securepass123"
Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
3. Get Current User Info (Authenticated)
curl -X GET "http://localhost:8000/users/me" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
4. Update User Profile
curl -X PATCH "http://localhost:8000/users/1" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jane",
"last_name": "Smith"
}'
5. Get Current User's Profile
curl -X GET "http://localhost:8000/profiles/me" \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
6. Update Profile Settings
curl -X PATCH "http://localhost:8000/profiles/me" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"time_zone": "America/New_York",
"language": "es",
"preferences": "{\"theme\": \"dark\", \"notifications\": true}"
}'
7. Chat with the Agent (Non-Streaming)
curl -X POST "http://localhost:8000/chatbot" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"message": "Hello! What can you help me with?"
}'
Response:
"Hello! I'm here to help you with a variety of tasks..."
8. Chat with the Agent (Streaming)
curl -X POST "http://localhost:8000/chatbot/stream" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"message": "Tell me a short story"
}'
Response (Server-Sent Events):
data: Once
data: upon
data: a
data: time
data: ...
Database Migrations
# Create a new migration
alembic revision --autogenerate -m "description of changes"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1
# View migration history
alembic history
# View current version
alembic current
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=src --cov-report=html
# Run specific test file
pytest tests/test_auth.py
# Run with verbose output
pytest -v
# Run and stop on first failure
pytest -x
LangGraph Agent Testing
The project includes a basic chatbot agent built with LangGraph. You can test it in multiple ways:
Option 1: Testing with LangGraph Studio (LangSmith)
LangGraph Studio provides a visual interface for testing and debugging your agents with full tracing capabilities.
Prerequisites
-
Install LangGraph CLI (if not already installed):
pip install langgraph-cli
-
Configure LangSmith (optional but recommended for tracing):
Get your API key from LangSmith and add to
.env:LANGSMITH_TRACING=true LANGSMITH_API_KEY=lsv2_your_api_key_here
-
Set OpenAI API Key in
.env:OPENAI_API_KEY=sk-your-openai-api-key-here
Start LangGraph Dev Server
Run the following command in your project root:
langgraph dev
This will:
- Start the LangGraph development server
- Open LangGraph Studio in your browser (typically at
http://localhost:8123) - Enable hot-reloading for agent changes
- Provide visual debugging and tracing
Using LangGraph Studio
- Select the Agent: Choose the
chatbotgraph from the dropdown - Configure Thread: Set a thread ID for conversation persistence
- Send Messages: Type messages in the input box and see responses
- View State: Inspect the agent's state at each step
- Trace Execution: See detailed traces of LLM calls and node executions
LangGraph Configuration
The agent is configured in langgraph.json:
{
"dependencies": ["."],
"graphs": {
"chatbot": "agents/basic/agent.py:make_graph"
},
"env": ".env"
}
Option 2: Testing via FastAPI Endpoints
You can test the agent through the FastAPI endpoints after starting the application.
Start the FastAPI Server
# Using the run script
python run.py
# Or using uvicorn directly
uvicorn src.main:app --reload
Test Non-Streaming Endpoint
Using curl:
# First, get an authentication token
TOKEN=$(curl -s -X POST "http://localhost:8000/auth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=your_email@example.com&password=your_password" \
| jq -r '.access_token')
# Then chat with the agent
curl -X POST "http://localhost:8000/chatbot" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Hello! Can you help me?"
}'
Using Python:
import requests
# Login
response = requests.post(
"http://localhost:8000/auth/token",
data={"username": "your_email@example.com", "password": "your_password"}
)
token = response.json()["access_token"]
# Chat with agent
response = requests.post(
"http://localhost:8000/chatbot",
headers={"Authorization": f"Bearer {token}"},
json={"message": "Hello! Can you help me?"}
)
print(response.text)
Using the provided api.http file:
Open api.http in VS Code with the REST Client extension:
- First, execute the login request to get a token
- Copy the
access_tokenfrom the response - Update the
@tokenvariable at the top of the file - Execute the chatbot requests
### Chat (Non-Streaming)
POST {{baseUrl}}/chatbot HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"message": "Hello! What can you help me with?"
}
### Chat (Streaming)
POST {{baseUrl}}/chatbot/stream HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}
{
"message": "Tell me a short story"
}
Test Streaming Endpoint
Using curl:
curl -N -X POST "http://localhost:8000/chatbot/stream" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Tell me a story"
}'
Using Python with SSE:
import requests
import json
# Login first (same as above)
response = requests.post(
"http://localhost:8000/auth/token",
data={"username": "your_email@example.com", "password": "your_password"}
)
token = response.json()["access_token"]
# Stream chat response
response = requests.post(
"http://localhost:8000/chatbot/stream",
headers={"Authorization": f"Bearer {token}"},
json={"message": "Tell me a story"},
stream=True
)
for line in response.iter_lines():
if line:
decoded_line = line.decode('utf-8')
if decoded_line.startswith('data: '):
content = decoded_line[6:] # Remove 'data: ' prefix
print(content, end='', flush=True)
Option 3: Testing via Swagger UI
- Start the FastAPI server:
python run.py - Open http://localhost:8000/docs
- Authenticate:
- Click "Authorize" button
- Login via
/auth/tokenendpoint - Copy the access token
- Enter
Bearer <token>in the authorization dialog
- Test the chatbot endpoints:
- Expand
/chatbotPOST endpoint - Click "Try it out"
- Enter your message in the request body
- Click "Execute"
- Expand
Agent Architecture
The basic chatbot agent consists of:
- State: Defined in
agents/basic/state.py- Manages conversation messages - Graph: Defined in
agents/basic/agent.py- Orchestrates the conversation flow - Nodes:
chatbotnode inagents/basic/nodes/chatbot/node.py- Handles LLM interaction
- Checkpoint: PostgreSQL-based state persistence for conversation history
- LLM: Uses OpenAI's GPT-4o-mini model
Conversation Persistence
The agent uses PostgreSQL checkpointing to maintain conversation history:
- Thread ID: Each conversation has a unique thread ID
- State Persistence: Messages are stored and retrieved across requests
- Multiple Conversations: Different thread IDs maintain separate conversations
Example with different threads:
# Conversation 1 (thread_id: "1" - used by /chatbot endpoint)
curl -X POST "http://localhost:8000/chatbot" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "My name is Alice"}'
curl -X POST "http://localhost:8000/chatbot" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "What is my name?"}'
# Response: "Your name is Alice"
# Conversation 2 (thread_id: "2" - used by /chatbot/stream endpoint)
# This will be a separate conversation with no memory of "Alice"
Customizing the Agent
To modify the agent behavior:
-
Change the LLM model: Edit
agents/basic/nodes/chatbot/node.pyllm = init_chat_model("openai:gpt-4o", temperature=0.7)
-
Modify the system prompt: Edit
agents/basic/nodes/chatbot/prompt.py -
Add new nodes: Create new node files in
agents/basic/nodes/ -
Update the graph: Modify
agents/basic/agent.pyto add edges and nodes -
Test changes: Use
langgraph devfor hot-reloading during development
Architecture Principles
This template follows these key principles:
- Layered Architecture: Clear separation between routers (HTTP), services (business logic), and models (data)
- No Business Logic in Routers: All business logic resides in service layer
- Dependency Injection: Database sessions and authentication via FastAPI's Depends
- Schema Separation: Distinct Create, Update, and Read schemas for each model
- Bidirectional Relationships: Models use SQLAlchemy relationships properly
- Security First: Passwords hashed with bcrypt, JWT for stateless auth
Extending the Template
Adding a New Model
- Create model in
src/models/new_model.py(inherit fromBase) - Create schemas in
src/schemas/new_model.py(Create, Update, Read) - Create service in
src/services/new_model_service.py - Create router in
src/routers/new_model.py - Include router in
src/main.py - Generate migration:
alembic revision --autogenerate -m "add new_model" - Apply migration:
alembic upgrade head
Database Support
The template works with:
-
SQLite (default, for development)
DATABASE_URL=sqlite:///./app.db
-
PostgreSQL (recommended for production)
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
-
MySQL
DATABASE_URL=mysql+pymysql://user:password@localhost:3306/dbname
Change DATABASE_URL in .env accordingly.
Docker Support
Using Docker Compose (Recommended)
The project includes a docker-compose.yml that sets up both the application and a PostgreSQL database.
# Start all services
docker-compose up
# Start in detached mode
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Stop and remove volumes (⚠️ deletes database data)
docker-compose down -v
The application will be available at http://localhost:8000 with PostgreSQL running on port 5432.
Using Docker Only
# Build the image
docker build -t fastapi-base .
# Run the container
docker run -d -p 8000:8000 \
-e DATABASE_URL="sqlite:///./app.db" \
-e SECRET_KEY="your-secret-key" \
fastapi-base
Environment Variables Reference
| Variable | Description | Default | Required |
|---|---|---|---|
DATABASE_URL |
Database connection string | sqlite:///./app.db |
Yes |
SECRET_KEY |
JWT signing secret key | - | Yes |
ALGORITHM |
JWT algorithm | HS256 |
No |
ACCESS_TOKEN_EXPIRE_MINUTES |
Token expiration time in minutes | 30 |
No |
OPENAI_API_KEY |
OpenAI API key for LangGraph agent | - | Yes (for chatbot) |
LANGSMITH_TRACING |
Enable LangSmith tracing | false |
No |
LANGSMITH_API_KEY |
LangSmith API key for monitoring | - | No |
Generate a secure SECRET_KEY:
openssl rand -hex 32
# or using Python:
python -c "import secrets; print(secrets.token_hex(32))"
Get API Keys:
- OpenAI: https://platform.openai.com/api-keys
- LangSmith: https://smith.langchain.com/
Troubleshooting
"Module not found" errors
Make sure you're in the virtual environment and have installed all dependencies:
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install -r requirements.txt
Database connection errors
- Check that
DATABASE_URLis correctly set in.env - For SQLite, ensure the directory is writable
- For PostgreSQL/MySQL, verify the server is running and credentials are correct
"Could not validate credentials" errors
- Ensure you're sending the token in the
Authorization: Bearer <token>header - Check that the token hasn't expired (default: 30 minutes)
- Verify
SECRET_KEYin.envmatches the one used to generate the token
Alembic migration issues
# Reset migrations (⚠️ development only)
rm -rf alembic/versions/*.py
alembic revision --autogenerate -m "initial migration"
alembic upgrade head
LangGraph agent errors
"OpenAI API key not found"
- Ensure
OPENAI_API_KEYis set in your.envfile - Verify the key is valid and has credits available
"Checkpointer not initialized"
- Make sure the PostgreSQL database is running
- Check the
DB_URIinsrc/db/checkpoint.pyis correct - Verify the database is accessible
"langgraph dev" command not found
- Install LangGraph CLI:
pip install langgraph-cli - Ensure you're in the virtual environment
Agent not responding or timing out
- Check your OpenAI API key has sufficient credits
- Verify internet connection for API calls
- Check LangSmith dashboard for error traces (if enabled)
Project Status
This is a production-ready template that includes:
- ✅ JWT authentication with secure password hashing
- ✅ LangGraph AI agents with state persistence
- ✅ Streaming and non-streaming chatbot endpoints
- ✅ PostgreSQL checkpointing for conversation history
- ✅ LangSmith integration for tracing and monitoring
- ✅ Modular architecture following best practices
- ✅ Complete test suite with 85%+ coverage
- ✅ Database migrations with Alembic
- ✅ Docker support for easy deployment
- ✅ Comprehensive API documentation
- ✅ CORS configuration
- ✅ Input validation with Pydantic
- ✅ Role-based access control (staff, superuser)
Contributing
This is a template project. Feel free to:
- Fork and customize for your needs
- Report issues or suggest improvements
- Use as a starting point for your projects
License
This is a template project - use it as you wish for your own projects.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dinnovos_agent_cli-1.0.1.tar.gz.
File metadata
- Download URL: dinnovos_agent_cli-1.0.1.tar.gz
- Upload date:
- Size: 49.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67ee8ee9958e555c8b20347968da04b9882110e77a85b314cd1f4d4b6a64f0ad
|
|
| MD5 |
291198d1776a878b18cf4630eb50654e
|
|
| BLAKE2b-256 |
4194f2ea454e2ad7869486119c81b5ac6707f2701d4709204822b7c958811078
|
File details
Details for the file dinnovos_agent_cli-1.0.1-py3-none-any.whl.
File metadata
- Download URL: dinnovos_agent_cli-1.0.1-py3-none-any.whl
- Upload date:
- Size: 40.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f7a21a2d4218c2ff46bdbc0f905c9bb944404329e6b1b19a8116503799f5e07
|
|
| MD5 |
8cd7b8f830dedb5c7156bc3c515cacfc
|
|
| BLAKE2b-256 |
fd318070dddd05de2fbd558d05dc5f0b9f1533cebf47be4addbc87623e63c2ee
|