from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import httpx import logging import sys import traceback import os logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", handlers=[logging.StreamHandler(sys.stdout)]) logger = logging.getLogger(__name__) app = FastAPI() app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"]) class MessageRequest(BaseModel): message: str LANGGRAPH_URL = os.getenv("LANGGRAPH_URL", "http://langgraph-service:8090") @app.post("/chat") async def chat(request: MessageRequest): """ Routes all queries through LangGraph Supervisor. No hardcoded keywords - LangGraph intelligently routes to: - Librarian: For knowledge base queries (RAG) - Opencode: For coding tasks - Brain: For general LLM queries """ logger.info(f"Gateway: Routing query to LangGraph: {request.message}") try: async with httpx.AsyncClient(timeout=httpx.Timeout(60.0, connect=10.0)) as client: response = await client.post( f"{LANGGRAPH_URL}/query", json={"query": request.message} ) if response.status_code == 200: result = response.json() agent_used = result.get("agent_used", "unknown") logger.info(f"Gateway: Response from {agent_used} agent") return {"response": result["response"]} else: logger.error(f"Gateway: LangGraph error {response.status_code}") return {"response": "Error: Orchestration service unavailable"} except Exception as e: logger.error(f"Gateway: Error routing through LangGraph: {traceback.format_exc()}") return {"response": "Error: Unable to process your request at this time."} @app.get("/health") async def health(): return {"status": "healthy", "service": "chat-gateway"} @app.get("/agents") async def list_agents(): """List available agents from LangGraph.""" try: async with httpx.AsyncClient(timeout=httpx.Timeout(10.0)) as client: response = await client.get(f"{LANGGRAPH_URL}/agents") if response.status_code == 200: return response.json() except Exception as e: logger.error(f"Error fetching agents: {e}") return {"agents": [], "error": "Could not retrieve agent list"}