Qurio / backend-python /src /services /agent_os_app.py
veeiiinnnnn's picture
new
592cb1d
"""
AgentOS app bootstrap using Agno SDK.
"""
from __future__ import annotations
import logging
import os
from types import SimpleNamespace
from agno.os import AgentOS
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
# Configure logging to see debug messages
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("httpcore").setLevel(logging.WARNING)
from ..config import get_settings
from ..routes import (
agent_for_auto,
deep_research,
mcp_tools,
related_questions,
research_plan,
space_agent,
title_and_space,
title_space_agent,
)
from ..routes import (
daily_tip as daily_tip_route,
)
from ..routes import (
db as db_route,
)
from ..routes import (
emoji as emoji_route,
)
from ..routes import (
memory as memory_route,
)
from ..routes import (
stream_chat as stream_chat_route,
)
from ..routes import (
title as title_route,
)
from ..routes import (
email as email_route,
)
from ..routes import (
scrapbook as scrapbook_route,
)
from ..routes import (
env as env_route,
)
from ..routes import (
skills as skills_route,
)
from .agent_registry import build_agent
from .email_monitor import start_email_monitor, stop_email_monitor
_agent_os: AgentOS | None = None
def _build_base_app() -> FastAPI:
settings = get_settings()
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Optional auto polling; disabled by default to avoid background pulls.
if os.getenv("EMAIL_AUTO_POLL_ENABLED", "0") == "1":
start_email_monitor()
yield
# Stop scheduler on shutdown if it was started.
stop_email_monitor()
app = FastAPI(
title="Qurio Backend (AgentOS)",
description="Agno AgentOS app with Qurio routes",
version="0.2.0",
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.middleware("http")
async def _cors_fallback(request, call_next):
try:
response = await call_next(request)
except Exception as exc:
response = JSONResponse(status_code=500, content={"detail": str(exc)})
origin = request.headers.get("origin")
if origin and (origin in settings.allowed_origins):
response.headers.setdefault("Access-Control-Allow-Origin", origin)
response.headers.setdefault("Vary", "Origin")
response.headers.setdefault("Access-Control-Allow-Credentials", "true")
response.headers.setdefault("Access-Control-Allow-Headers", "*")
response.headers.setdefault("Access-Control-Allow-Methods", "*")
return response
app.include_router(stream_chat_route.router, prefix="/api")
app.include_router(daily_tip_route.router, prefix="/api")
app.include_router(title_route.router, prefix="/api")
app.include_router(emoji_route.router, prefix="/api")
app.include_router(title_and_space.router, prefix="/api")
app.include_router(title_space_agent.router, prefix="/api")
app.include_router(space_agent.router, prefix="/api")
app.include_router(agent_for_auto.router, prefix="/api")
app.include_router(related_questions.router, prefix="/api")
app.include_router(research_plan.router, prefix="/api")
app.include_router(deep_research.router, prefix="/api")
app.include_router(memory_route.router, prefix="/api")
app.include_router(mcp_tools.router, prefix="/api/mcp-tools")
app.include_router(db_route.router, prefix="/api")
app.include_router(email_route.router, prefix="/api")
app.include_router(scrapbook_route.router, prefix="/api")
app.include_router(env_route.router, prefix="/api")
app.include_router(skills_route.router, prefix="/api")
return app
def get_agent_os() -> AgentOS:
global _agent_os
if _agent_os is not None:
return _agent_os
base_app = _build_base_app()
# init_memory_db() # Removed legacy DB init
default_request = SimpleNamespace(
provider="openai",
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
model=os.getenv("OPENAI_MODEL"),
tavily_api_key=os.getenv("TAVILY_API_KEY") or os.getenv("PUBLIC_TAVILY_API_KEY"),
temperature=None,
top_p=None,
top_k=None,
frequency_penalty=None,
presence_penalty=None,
thinking=None,
tool_ids=None,
tools=None,
user_tools=None,
tool_choice=None,
enable_long_term_memory=os.getenv("ENABLE_LONG_TERM_MEMORY", "0") == "1",
database_provider=os.getenv("DATABASE_PROVIDER") or "default",
)
default_agent = build_agent(default_request)
_agent_os = AgentOS(
name="Qurio AgentOS",
description="Qurio backend powered by Agno AgentOS",
agents=[default_agent],
base_app=base_app,
on_route_conflict="preserve_base_app",
cors_allowed_origins=get_settings().allowed_origins,
)
return _agent_os