3 min read · 554 words
Application Entry — main.py
33 lines that assemble the whole service: create tables, migrate, mount two routers, expose health checks.
Purpose
backend/app/main.py is the ASGI entry point (uvicorn main:app). It performs the platform's entire startup sequence at import time, then defines the two unauthenticated liveness endpoints.
The file, annotated
python
from fastapi import FastAPI
from database import Base, engine, run_startup_migrations
import models # (1)!
from routers import agents, documents
Base.metadata.create_all(bind=engine) # (2)!
run_startup_migrations() # (3)!
app = FastAPI(
title=" AgentOps AI",
description="Backend API for AgentOps AI project",
version="0.1.0"
)
app.include_router(agents.router) # (4)!
app.include_router(documents.router)
@app.get("/")
async def root():
return {"message": "AgentOps AI backend is running"}
@app.get("/health")
async def health_check():
return {"status": "ok", "service": "agentops-ai-backend"}- Importing
modelsregisters every model class onBase.metadata— without this import,create_allwould create nothing. - Creates all 9 tables in
agentops.dbif absent. Idempotent; it never alters existing tables. - Ad-hoc SQLite migration: adds
model_name,estimated_tokens,estimated_costtotool_callson older databases. See Migrations. - Both routers use
prefix="/agents"— the documents router nests its routes under/agents/{agent_id}/documents....
Responsibilities
- Build the SQLite schema (
create_all) and apply startup migrations before the app serves traffic. - Mount the
agentsanddocumentsrouters. - Provide
GET /andGET /healthfor liveness probes.
Dependencies
| Imports | Used for |
|---|---|
database.Base, database.engine, run_startup_migrations | schema + migrations |
models | side-effect registration of all tables |
routers.agents, routers.documents | the API surface |
Data flow
Startup only: import → create_all → migrations → app ready. After startup, main.py is not on any request path except / and /health.
Rendering diagram…
Public API
| Endpoint | Response |
|---|---|
GET / | {"message": "AgentOps AI backend is running"} |
GET /health | {"status": "ok", "service": "agentops-ai-backend"} |
Both are safe, side-effect-free, and require no configuration — they work even without an OpenAI key, making them the right targets for readiness probes.
Edge cases & error handling
- Missing
modelsimport would silently produce an empty database — the import exists precisely to prevent this. - Schema drift:
create_allnever adds columns to existing tables; that is whatrun_startup_migrations()is for. Forgetting a migration entry surfaces later asOperationalError: no such column— see Troubleshooting. - Startup work runs at import time, not in a lifespan handler; a failure (e.g., unwritable directory for
agentops.db) aborts boot with a traceback — which is the desirable behavior.
Security notes
/ and /health are unauthenticated by design and reveal only the service name. Everything else inherits the platform's security posture (no auth).
Future improvements
- Move startup work into a FastAPI lifespan context for testability.
- Add
CORSMiddlewarewhen browser-direct access is needed. - Read
title/versionfrom package metadata instead of literals (note the stray leading space in" AgentOps AI").