ALMS AI-first backend starter
Project description
ALMS
The AI-First Backend for Scalable, Intelligent Applications.
Quick Start with CLI
Create a new ALMS project in seconds:
# Install the CLI
pip install alms-cli
# Create a new project
alms init my-project
# Or run without installing
uvx --from alms-cli alms init my-project
The reference framework package is published on PyPI as axtra-alms because the alms distribution name is unavailable. Internal imports and generated module names remain src.*; only the installable distribution name changed.
pip install axtra-alms
The CLI features:
- Beautiful terminal UI with interactive prompts
- Feature selection (Database, Redis, AI Agents, Observability, Docker, CI/CD)
- Complete project scaffolding ready to run
Bundled Agent Skills
ALMS includes a repo-packaged agent skill for LLM coding assistants:
.agents/skills/alms-dev
Use alms-dev when asking an AI coding agent to add endpoints, usecases, actions, repositories, providers, settings, middleware, tests, or docs in this repo. The skill teaches the ALMS layer boundaries and keeps generated code aligned with the project structure.
For LangGraph-specific agent workflow work, use the separate public skill:
npx skills add KJ-AIML/alms-langgraph-agent-skill
Use both skills together when a change touches normal ALMS backend layers and production LangGraph workflows. The intended flow is:
API Endpoint -> UseCase -> Action -> Agent or LangGraph Workflow
Introduction
ALMS is a production-ready boilerplate designed for building robust, AI-powered backends. Built with an "AI-First" philosophy, it combines the performance of FastAPI with ALMS (Agentic Layer for Microservices) - a pragmatic layered architecture that treats LLM interactions as first-class citizens.
Whether you're building autonomous agents, RAG pipelines, or intelligent APIs, this starter kit provides the scalability and clean code structure you need to move fast without over-engineering.
Key Features
- ๐ค AI-Native Architecture: Dedicated
src/agentslayer for managing LLM logic, tools, and complex agentic workflows - ๐๏ธ ALMS Architecture: Agentic Layer for MicroServices - A pragmatic layered architecture optimized for AI applications
- ๐ Provider Pattern: Clean separation of external services (OpenAI, Redis, VectorDBs) via
src/providers - ๐ง Business Logic Separation: Clear distinction between
usecases(orchestration) andactions(execution) - ๐พ Database Abstraction: Repository pattern with Alembic migrations and async PostgreSQL support
- ๐ Security-First: Built-in middleware for security headers, CORS, and request validation
- ๐ Standardized Responses: Consistent API response format with error handling
- โก Async-Ready: Full async/await support with FastAPI and asyncpg
- ๐งช Testing Ready: pytest setup with fixtures and organized test structure
- ๐ Modern Documentation: Scalar API docs for beautiful interactive documentation
- ๐ Built-in Observability: OpenTelemetry tracing + Prometheus metrics (AI, DB, Cache monitoring)
ALMS Architecture
Agentic Layer for MicroServices is a layered architecture designed specifically for AI applications. Unlike complex Hexagonal architecture, ALMS prioritizes simplicity and rapid development while maintaining clean separation of concerns.
Why ALMS?
| Feature | ALMS | Hexagonal | Traditional MVC |
|---|---|---|---|
| Complexity | Low | High | Medium |
| AI-First | โ Native | โ Add-on | โ Add-on |
| Learning Curve | Gentle | Steep | Moderate |
| Microservice Ready | โ Yes | โ ๏ธ Overhead | โ No |
| Production Speed | Fast | Slow | Medium |
Architecture Layers
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ API Layer (src/api/) โ
โ HTTP handling, routing, middleware, validation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข endpoints/v1/ - Versioned API endpoints โ
โ โข middlewares/ - Security, logging, error handling โ
โ โข router/ - Router aggregation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Execution Layer (src/execution/) โ
โ Business logic, use cases, action orchestration โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข usecases/ - Orchestrate business flow โ
โ โข actions/ - Execute discrete operations โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Agent Layer (src/agents/) โ
โ AI logic, prompts, tools, workflows (when needed) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข agent_manager/ - Agent definitions โ
โ โข prompts/ - LLM prompt templates โ
โ โข tools/ - Agent tools โ
โ โข workflows/ - LangGraph workflows โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Infrastructure Layers (src/*) โ
โ Providers, Database, Core utilities, Configurations โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข providers/ - External service integrations โ
โ โข database/ - Repositories, migrations โ
โ โข core/ - Exceptions, base classes โ
โ โข config/ - Settings, logging โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layer Communication Rules
# โ
Correct: Flow through layers
API Endpoint โ Usecase โ Action โ Provider
# โ Wrong: Never skip layers
API Endpoint โ Provider # Don't bypass execution layer
Usecase โ Database # Use repository pattern
Project Structure
alms/
โโโ src/
โ โโโ api/ # API Layer
โ โ โโโ endpoints/v1/ # Versioned endpoints
โ โ โ โโโ dependencies.py # DI for v1
โ โ โ โโโ health.py # Health check endpoint
โ โ โ โโโ metrics.py # Prometheus metrics endpoint
โ โ โ โโโ sample_agent.py # Agent endpoint example
โ โ โ โโโ sample_di.py # DI example
โ โ โ โโโ schemas/ # Pydantic schemas
โ โ โ โโโ base.py # AppResponse wrapper
โ โ โ โโโ sample.py # Request/response schemas
โ โ โโโ middlewares/ # Global middlewares
โ โ โ โโโ error_handler.py # Exception handling
โ โ โ โโโ logging.py # Request logging
โ โ โ โโโ observability.py # Metrics & tracing middleware
โ โ โ โโโ security.py # Security headers
โ โ โโโ router/ # Router aggregation
โ โ โ โโโ routers.py # Main API router
โ โ โโโ main.py # FastAPI app factory
โ โโโ execution/ # Execution Layer
โ โ โโโ actions/ # Discrete operations
โ โ โ โโโ sample_action.py
โ โ โโโ usecases/ # Business flow orchestration
โ โ โโโ sample_usecase.py
โ โโโ agents/ # Agent Layer
โ โ โโโ agent_manager/
โ โ โ โโโ agent.py # Agent definitions
โ โ โโโ prompts/
โ โ โ โโโ prompt_manager.py # Markdown prompt loader
โ โ โ โโโ agents/
โ โ โ โโโ agent_sample.md
โ โ โโโ schemas/ # Structured agent output schemas
โ โ โโโ tools/ # Agent tools (empty)
โ โ โโโ workflows/ # LangGraph workflows
โ โ โโโ sample/
โ โ โโโ state.py
โ โ โโโ nodes.py
โ โ โโโ build.py
โ โโโ providers/ # Infrastructure Providers
โ โ โโโ ai/
โ โ โโโ base.py # AIModelProvider abstract base
โ โ โโโ factory.py # get_ai_provider() factory
โ โ โโโ langchain_model_loader.py
โ โโโ observability/ # Observability Layer
โ โ โโโ __init__.py # Module exports
โ โ โโโ tracing.py # OpenTelemetry tracing
โ โ โโโ metrics.py # Prometheus metrics
โ โโโ database/ # Database Layer
โ โ โโโ connection.py # DB connection setup
โ โ โโโ migrations/ # Alembic migrations
โ โ โโโ repositories/
โ โ โโโ base.py # BaseRepository pattern
โ โโโ core/ # Shared Core
โ โ โโโ exceptions.py # Custom exceptions
โ โโโ config/ # Configuration
โ โ โโโ settings.py # Pydantic Settings
โ โ โโโ logs_config.py # Logging setup
โ โโโ models/ # Domain models (empty)
โ โโโ utils/ # Utilities
โ โโโ tests/ # Tests
โ โโโ conftest.py # pytest fixtures
โ โโโ v1/ # Versioned tests
โ โโโ test_health.py
โ โโโ test_agent.py
โโโ alembic/ # Database migrations
โ โโโ env.py
โ โโโ README
โโโ rules/
โ โโโ project_rules.md # ALMS guidelines
โโโ .env.example # Environment template
โโโ pyproject.toml # Dependencies (uv)
โโโ README.md # This file
Tech Stack
| Category | Technology | Purpose |
|---|---|---|
| Framework | FastAPI | High-performance API framework |
| AI/LLM | LangChain + LangGraph | Agent orchestration |
| Database | PostgreSQL + SQLAlchemy | Data persistence |
| Async DB | asyncpg | Async PostgreSQL driver |
| Migrations | Alembic | Database schema migrations |
| Caching | Redis | Caching & message broker |
| Validation | Pydantic v2 | Data validation & settings |
| Documentation | Scalar | Modern API documentation |
| Observability | OpenTelemetry + Prometheus | Distributed tracing & metrics |
| Testing | pytest | Testing framework |
| Linting | Ruff | Fast Python linter |
| Package Manager | uv | Modern Python package manager |
Quick Start
Prerequisites
- Python 3.13+
- PostgreSQL (optional, for database features)
- Redis (optional, for caching)
- uv installed
1. Clone & Setup
git clone https://github.com/KJ-AIML/alms.git
cd alms
# Copy environment file
cp .env.example .env
# Edit .env with your credentials
# Required only when AI_ENABLED=True: OPENAI_API_KEY
# Optional: DATABASE_URL, REDIS_URL, OTLP_ENDPOINT
2. Install Dependencies
# Using uv (recommended)
uv sync
# Or using pip
pip install -e .
3. Run Database Migrations (if using PostgreSQL)
# Create initial migration
alembic revision --autogenerate -m "Initial migration"
# Apply migrations
alembic upgrade head
4. Start the Application
# Development mode with hot-reload
uv run -m src.api.main
# The API will be available at:
# - API: http://localhost:3000
# - Docs: http://localhost:3000/docs (Scalar)
Development Commands
Application
# Run development server
uv run -m src.api.main
# Run with specific host/port
uv run -m src.api.main --host 0.0.0.0 --port 8080
Testing
# Run all tests
uv run pytest src/tests
# Run with verbose output
uv run pytest src/tests -v
# Run specific test file
uv run pytest src/tests/v1/test_agent.py -v
# Run with coverage
uv run pytest src/tests --cov=src
Database
# Create new migration
alembic revision --autogenerate -m "Description of changes"
# Apply all migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1
# Show current version
alembic current
# View migration history
alembic history --verbose
Dependencies
# Add production dependency
uv add <package>
# Add development dependency
uv add --dev <package>
# Sync with lock file
uv sync
# Update lock file
uv lock
# Show dependency tree
uv tree
Code Quality
# Run linter
ruff check src/
# Fix auto-fixable issues
ruff check --fix src/
# Format code
ruff format src/
API Standards
Response Format
All API responses use the standardized AppResponse wrapper:
Success Response:
{
"success": true,
"data": {
"message": "Operation completed",
"result": {...}
},
"error": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Error Response:
{
"success": false,
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input provided",
"details": {
"field": "email",
"reason": "Invalid email format"
}
},
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Exception Handling
Use custom exceptions from src/core/exceptions.py:
from src.core.exceptions import NotFoundException, ValidationException
# Resource not found
raise NotFoundException(
message="User not found",
error_code="USER_NOT_FOUND",
details={"user_id": user_id}
)
# Validation error
raise ValidationException(
message="Invalid email format",
error_code="INVALID_EMAIL",
details={"field": "email", "value": email}
)
Repository Pattern
Database access is abstracted through the Repository pattern:
from src.database.repositories.base import BaseRepository
from src.models.user import User
from typing import Optional
class UserRepository(BaseRepository[User]):
def __init__(self):
super().__init__(User)
async def get_by_email(self, email: str) -> Optional[User]:
# Implementation using SQLAlchemy
result = await self.session.execute(
select(User).where(User.email == email)
)
return result.scalar_one_or_none()
async def get_active_users(self, skip: int = 0, limit: int = 100):
result = await self.session.execute(
select(User)
.where(User.is_active == True)
.offset(skip)
.limit(limit)
)
return result.scalars().all()
Configuration
Configuration is managed via Pydantic Settings with environment variables:
# .env file
# Feature flags โ enable only what your project needs
AI_ENABLED=False # Set True when using AI agents or LangGraph workflows
DATABASE_ENABLED=True # Set False to disable DB dependency and readiness check
REDIS_ENABLED=False # Set True when Redis is in use
MODEL_PROVIDER=openai # AI provider selection (Google/Anthropic support is deferred)
# AI keys โ required only when AI_ENABLED=True
OPENAI_API_KEY=sk-...
OPENAI_MODEL_BASIC=gpt-4o-mini
OPENAI_MODEL_REASONING=gpt-4o
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=mydb
DATABASE_USER=postgres
DATABASE_PASSWORD=secret
REDIS_HOST=localhost
REDIS_PORT=6379
# Observability (Optional)
OTLP_ENDPOINT=http://localhost:4317
METRICS_ENABLED=true
TRACING_ENABLED=true
DEBUG=true
LOG_LEVEL=info
SERVER_PORT=3000
Production Configuration
When DEBUG=False, ALMS calls settings.validate_production_settings() at lifespan startup and refuses to start if unsafe defaults are present:
SECRET_KEYmust not be the default placeholder valueALLOWED_HOSTSmust not contain*OPENAI_API_KEYmust be set whenAI_ENABLED=TrueandMODEL_PROVIDER=openai
Set these in your production environment:
DEBUG=False
SECRET_KEY=<generated-secure-key>
ALLOWED_HOSTS=["your-domain.com"]
Access settings anywhere:
from src.config.settings import settings
# Use settings
api_key = settings.OPENAI_API_KEY
db_url = settings.DATABASE_URL
Optional Extras
ALMS uses optional dependency extras so you only install what you need:
# Install with AI/LLM support
uv sync --extra ai
# Install with database support
uv sync --extra db
# Install with observability support
uv sync --extra observability
# Install with all features
uv sync --extra full
Available extras:
| Extra | Purpose |
|---|---|
ai |
LangChain, LangGraph, OpenAI |
db |
SQLAlchemy, asyncpg, Alembic |
cache |
Redis |
observability |
OpenTelemetry, Prometheus |
docs |
Scalar API docs |
full |
All of the above |
Project Metadata ([tool.alms])
ALMS projects declare their active profile and capabilities in pyproject.toml:
[tool.alms]
profile = "full"
capabilities = ["runtime_auth", "tests", "llm", "langgraph", "database", "redis", "observability", "scalar_docs", "docker", "ci"]
The ALMS CLI reads this metadata to generate projects with only the enabled capabilities. The companion skill also reads [tool.alms] to constrain code generation.
Generated Project Routes
When you generate a project with the ALMS CLI, the route structure is:
/api/v1/health/live # Liveness check
/api/v1/health/ready # Readiness check (includes DB if enabled)
/api/v1/health # Alias for ready
/api/v1/metrics # Prometheus metrics (if observability enabled)
/api/v1/agent/sample # Sample agent endpoint (if llm enabled)
/api/v1/di/sample # Sample DI endpoint (if llm enabled)
The three-level router pattern is:
v1_router = APIRouter() # No prefix
v1_router.include_router(health.router, prefix="/health")
v1_router.include_router(metrics.router, prefix="/metrics")
api_router = APIRouter()
api_router.include_router(v1_router, prefix="/v1")
app.include_router(api_router, prefix=settings.API_PREFIX) # /api
Observability
ALMS includes built-in observability with OpenTelemetry and Prometheus:
Features
- Distributed Tracing: Track requests across all layers with OpenTelemetry
- Metrics Collection: Prometheus-compatible metrics for monitoring
- AI Monitoring: Track LLM token usage, latency, and costs
- Database Metrics: Query performance and connection pool monitoring
- Cache Analytics: Hit/miss ratios and operation latency
Available Metrics
Access metrics at: http://localhost:3000/api/v1/metrics
| Metric | Description |
|---|---|
http_requests_total |
HTTP requests by method, endpoint, status |
db_queries_total |
Database queries by operation |
cache_hits_total & cache_misses_total |
Cache performance |
ai_tokens_total |
LLM token usage |
ai_request_duration_seconds |
AI API latency |
agent_executions_total |
Agent executions by type |
Configuration
# OpenTelemetry tracing
OTLP_ENDPOINT=http://localhost:4317 # Optional: Send traces to collector
TRACING_ENABLED=true # Enable/disable tracing
# Prometheus metrics
METRICS_ENABLED=true # Enable/disable metrics
Using Custom Metrics
from src.observability.metrics import metrics
from src.observability.tracing import tracer
# Record custom metric
metrics.counter("my_event_total", {"type": "example"})
# Create custom span
with tracer.start_as_current_span("my_operation") as span:
span.set_attribute("custom.attribute", value)
result = do_work()
Creating a New Agent
New agent features should keep HTTP, orchestration, execution, and AI behavior in separate layers:
Endpoint -> UseCase -> Action -> Agent or Workflow
- Define the prompt in
src/agents/prompts/agents/:
<!-- src/agents/prompts/agents/agent_my_agent.md -->
You are a helpful assistant for this feature.
- Register the prompt in
src/agents/prompts/prompt_manager.py:
class PromptManager:
def __init__(self) -> None:
self._my_agent: str | None = None
@property
def my_agent(self) -> str:
if self._my_agent is None:
self._my_agent = self._load_prompt("agents/agent_my_agent.md")
return self._my_agent
- Define the agent in
src/agents/agent_manager/:
# src/agents/agent_manager/my_agent.py
from src.agents.prompts.prompt_manager import prompt_manager
from src.providers.ai.factory import get_ai_provider
class MyAgent:
def __init__(self):
self._model = None
@property
def model(self):
if self._model is None:
self._model = get_ai_provider().get_chat_model("basic")
return self._model
async def process(self, query: str) -> str:
response = await self.model.ainvoke(
[
("system", prompt_manager.my_agent),
("user", query),
]
)
return response.content
- Create an action in
src/execution/actions/:
# src/execution/actions/process_my_agent_action.py
from src.agents.agent_manager.my_agent import MyAgent
class ProcessMyAgentAction:
def __init__(self, agent: MyAgent | None = None):
self.agent = agent or MyAgent()
async def execute(self, query: str) -> dict:
result = await self.agent.process(query)
return {"response": result}
- Create use case in
src/execution/usecases/:
# src/execution/usecases/process_my_agent_usecase.py
from src.execution.actions.process_my_agent_action import ProcessMyAgentAction
class ProcessMyAgentUseCase:
def __init__(self, action: ProcessMyAgentAction | None = None):
self.action = action or ProcessMyAgentAction()
async def execute(self, query: str) -> dict:
return await self.action.execute(query)
- Create endpoint in
src/api/endpoints/v1/:
# src/api/endpoints/v1/my_endpoint.py
from fastapi import APIRouter
from src.api.endpoints.v1.schemas.base import AppResponse
from src.execution.usecases.process_my_agent_usecase import ProcessMyAgentUseCase
router = APIRouter()
@router.post("/my-agent")
async def my_agent_endpoint(query: str):
usecase = ProcessMyAgentUseCase()
result = await usecase.execute(query)
return AppResponse(success=True, data=result)
- Register router in
src/api/endpoints/v1/routers.py:
from src.api.endpoints.v1 import my_endpoint
v1_router.include_router(my_endpoint.router, prefix="/my-agent")
For multi-step or auditable LangGraph workflows, place the workflow under src/agents/workflows/<feature>/ with state.py, nodes.py, and build.py, then invoke the compiled workflow from an action class.
Scaling to Microservices
ALMS makes it easy to extract layers into microservices:
Monolith Microservices
โโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ API โ โโโโโโโโโโโโโ โ API Gateway โ
โโโโโโโโโโโโค โโโโโโโโโโโโโโโโค
โ Executionโ โโโโโโโโโโโโโ โ Logic Serviceโ
โโโโโโโโโโโโค โโโโโโโโโโโโโโโโค
โ Agent โ โโโโโโโโโโโโโ โ Agent Serviceโ
โโโโโโโโโโโโค โโโโโโโโโโโโโโโโค
โ DB โ โโโโโโโโโโโโโ โ Data Service โ
โโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
Each layer is already isolated - just add HTTP/gRPC clients between them!
Contributing
- Follow ALMS layer rules - never skip layers
- Add tests for all use cases and actions
- Use custom exceptions, not raw HTTPException
- Add type hints to all functions
- Update documentation for new features
- Run
ruff checkbefore committing - Ensure all tests pass:
uv run pytest src/tests
License
Built for the next generation of AI applications
ALMS Architecture - Pragmatic, Scalable, AI-First
Project details
Release history Release notifications | RSS feed
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 axtra_alms-0.3.0.tar.gz.
File metadata
- Download URL: axtra_alms-0.3.0.tar.gz
- Upload date:
- Size: 49.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55e7cc05248f47c6c75b9a029eb65a1515c98a0b1b7fe7a966a4ffd5cd7cf7e6
|
|
| MD5 |
0a174b721b90783a0b2694693ead8a3f
|
|
| BLAKE2b-256 |
9d85e94a091a8950162d4e9f62a5b813ea1f6dde129315d9983566fc2248d4bb
|
File details
Details for the file axtra_alms-0.3.0-py3-none-any.whl.
File metadata
- Download URL: axtra_alms-0.3.0-py3-none-any.whl
- Upload date:
- Size: 54.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df93fe1ed2fba4f80805cc6a10015b87ff8170de052e3582ddf78072233601af
|
|
| MD5 |
23143be74454e552190fb54f8493bfc8
|
|
| BLAKE2b-256 |
389410675c67fca5ad20874a26995369d6812fe894af1cce1416c00636add0d2
|