Skip to content
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"}
  1. Importing models registers every model class on Base.metadata — without this import, create_all would create nothing.
  2. Creates all 9 tables in agentops.db if absent. Idempotent; it never alters existing tables.
  3. Ad-hoc SQLite migration: adds model_name, estimated_tokens, estimated_cost to tool_calls on older databases. See Migrations.
  4. 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 agents and documents routers.
  • Provide GET / and GET /health for liveness probes.

Dependencies

ImportsUsed for
database.Base, database.engine, run_startup_migrationsschema + migrations
modelsside-effect registration of all tables
routers.agents, routers.documentsthe 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

EndpointResponse
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 models import would silently produce an empty database — the import exists precisely to prevent this.
  • Schema drift: create_all never adds columns to existing tables; that is what run_startup_migrations() is for. Forgetting a migration entry surfaces later as OperationalError: 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 CORSMiddleware when browser-direct access is needed.
  • Read title/version from package metadata instead of literals (note the stray leading space in " AgentOps AI").