Demo walkthrough coming soon.
CalibAI Backend is the server side of CalibAI β an AI assistant with seven specialized agents. It is split into five independently containerized Node.js services behind a thin API gateway , so each domain (auth, chat, agent, billing) can be built, deployed, and scaled on its own.
The heart of the system is the agent service : a LangGraph StateGraph that routes each request through an LLM intent classifier to one of eight agents β chat, coding, web search, image, PDF, PPT, PDF-RAG, and image analysis β with model selection per agent across Groq, OpenRouter, and Google Gemini.
Companion repo: CalibAI-Frontend β React 19 + Vite + Redux Toolkit chat console.
flowchart LR
Client["Browser (CalibAI Frontend)"]
subgraph GW["Gateway :8000"]
P["express-http-proxy"]
M["protect middleware<br/>cookie β Redis session"]
end
Client -- "cookie: session=<uuid>" --> GW
GW -- "/api/auth/**" --> AUTH["auth :8001"]
GW -- "/api/chat/** + x-user-id" --> CHAT["chat :8002"]
GW -- "/api/agent/** + x-user-id" --> AGENT["agent :8003"]
GW -- "/api/billing/** + x-user-id" --> BILL["billing :8004"]
AUTH --> MONGO[(MongoDB Atlas)]
CHAT --> MONGO
BILL --> MONGO
AUTH <--> REDIS[(Redis<br/>sessions Β· memory Β· rate limits)]
AGENT <--> REDIS
AGENT -- "persist / credits" --> AUTH
AGENT -- "persist messages" --> CHAT
BILL -- "plan upgrade" --> AUTH
subgraph AI["LangGraph orchestrator"]
R["LLM router"] --> A1["chat"]
R --> A2["coding"]
R --> A3["search"] -.-> A1
R --> A4["image"]
R --> A5["pdf"]
R --> A6["ppt"]
R --> A7["pdfRag"]
R --> A8["imageAnalyzer"]
end
AGENT --> AI
AI --> LLM["Groq Β· OpenRouter Β· Gemini Β· Tavily"]
AI --> VEC[(Qdrant)]
AI --> B2[(Backblaze B2 / S3)]
BILL --> RZP["Razorpay"]
Loading
Service
Port
Responsibility
gateway
8000
CORS, cookie parsing, protect auth, reverse proxy, x-user-id injection
auth
8001
Firebase token verification, user upsert, Redis sessions, plan + credit ledger
chat
8002
Conversation/message CRUD, artifact persistence, soft delete
agent
8003
LangGraph orchestration, 8 agents, rate limits, file handling, storage
billing
8004
Razorpay orders, signature verification, plan upgrades
Shared code lives in shared/redis and is copied into every Docker image.
π€ Multi-Agent Orchestration (LangGraph)
Conditional StateGraph β __start__ β router then a conditional edge dispatching to one of 8 agents, plus a special search β chat edge that injects web results as grounding context.
LLM intent router β classifies prompts, output sanitized against a whitelist with a safe chat fallback.
Fast paths before the LLM β explicit agent selection wins, application/pdf β pdfRag, image/* β imageAnalyzer.
Model-per-agent fan-out β Groq openai/gpt-oss-120b for chat, OpenRouter minimax-m3 for coding, Groq qwen3.8-27b for routing/search/RAG, Gemini flash-lite for vision.
Agent
What it does
chat
General assistant with Redis-backed conversation memory and optional web context
coding
Intent classifier (GENERATION / REVIEW / EXPLANATION / DEBUGGING / OPTIMIZATION / CONVERSION / DOCUMENTATION) β multi-file JSON artifacts for live preview
search
Tavily web search (5 results + images) β forwarded to chat for grounded answering
image
LLM prompt engineering β Pollinations.ai generation β B2 upload β 24h presigned URL
pdf
LLM outline (JSON) β PDFKit A4 render β B2 β 24h URL
ppt
LLM outline (JSON) β pptxgenjs 6-slide deck with randomized themes β B2 β 24h URL
pdfRag
pdf-parse β RecursiveCharacterTextSplitter (1000/100) β Qdrant + Gemini embeddings β score-thresholded top-3 β grounded answer
imageAnalyzer
Multimodal Gemini vision β OCR, chart/table explanation, image Q&A
Firebase Admin verifyIdToken() β find-or-create user β crypto.randomUUID() session stored in Redis (7-day TTL) with a reverse index for live patching.
Session delivered as an httpOnly, secure, sameSite: none cookie β no self-issued JWT, no passwords on our side.
Gateway protect middleware resolves the cookie β session blob β injects x-user-id into proxied requests.
π΄ Redis β Three Roles in One Store
Session store with reverse index (user-session-<userId>) so payments can rewrite a live session without re-login.
Conversation memory cache β hydrated from Mongo on first use (24h TTL), rolling 20-turn window appended after every response.
Rate limiter β fixed-window INCR rate:<userId>:<agent> + EXPIRE 60; per-agent ceilings (chat 20, image 10, coding/pdf/ppt/search 5, pdfRag/imageAnalyzer 3) returning structured 429 payloads with human-readable retryAfter.
Per-agent costs: chat 1 Β· search 3 Β· coding 12 Β· pdf 6 Β· ppt 8 Β· image 5 Β· pdfRag 10 Β· imageAnalyzer 10.
Enforced as checkAgentLimit β checkCredits β LLM call β deductCredits.
Every AI response returns remainingCredits so the UI updates immediately.
POST /billing/create β order for Free βΉ0/100 Β· Starter βΉ199/500 Β· Pro βΉ399/1000 (30-day validity) β Payment recorded as created.
POST /billing/verify β HMAC-SHA256 signature check β paid β auth /update-plan β live Redis session rewritten.
Multer disk uploads filtered to application/pdf + image/*, 20 MB limit, temp files unlinked in finally.
Dual S3-compatible layer β Backblaze B2 in active use, AWS S3 configured as fallback.
Generated PDFs/PPTs/images are built as in-memory Buffers and pushed straight to B2 with 24-hour presigned URLs .
π Data Model (MongoDB / Mongoose 9)
User β firebaseUid (unique), plan, credits/totalCredits, planExpiresAt
Conversation β title, userId, deletedAt soft delete
Message β role, content, images[], artifacts[{id, type, title, files[]}] , deletedAt
Payment β orderId, paymentId, amount, credits, plan, status (created|paid|failed)
Layer
Choice
Runtime
Node.js 20 (native --watch, --env-file)
Framework
Express 5.2.1 (ESM, plain JavaScript)
Gateway
express-http-proxy, cors, cookie-parser, morgan
Database
MongoDB Atlas + Mongoose 9
Cache / state
Redis via ioredis
AI
LangChain, LangGraph, Groq, OpenRouter, Google Gemini
Search
Tavily
Vector DB
Qdrant
Auth
firebase-admin
Payments
Razorpay
Documents
pdf-parse, PDFKit, pptxgenjs
Storage
AWS S3 + Backblaze B2 (presigner)
Uploads
Multer
CI/CD
GitHub Actions β GHCR β Render deploy hooks
Containers
Docker (node:20-alpine), docker-compose (Redis)
Node.js 20+ and npm
Docker (for Redis) β or a local Redis on 6379
MongoDB Atlas connection string
Firebase service account (client email + private key)
API keys: Groq , OpenRouter , Google AI , Tavily , Qdrant , Razorpay , Backblaze B2 (AWS optional)
git clone https://github.com/Regestrac/CalibAI-Backend.git
cd CalibAI-Backend
# install deps for every package (root, gateway, shared usage, and all services)
npm install --prefix gateway
npm install --prefix services/auth
npm install --prefix services/chat
npm install --prefix services/agent
npm install --prefix services/billing
docker compose up -d redis # redis on localhost:6379
Copy each service's .env.example to .env and fill it in:
cp gateway/.env.example gateway/.env
cp services/auth/.env.example services/auth/.env
cp services/chat/.env.example services/chat/.env
cp services/agent/.env.example services/agent/.env
cp services/billing/.env.example services/billing/.env
gateway/.env
Variable
Description
PORT
8000
AUTH_SERVICE
e.g. http://localhost:8001
CHAT_SERVICE
e.g. http://localhost:8002
AGENT_SERVICE
e.g. http://localhost:8003
BILLING_SERVICE
e.g. http://localhost:8004
FRONTEND_URL
e.g. http://localhost:5173 (CORS origin)
REDIS_URL
e.g. redis://localhost:6379
services/auth/.env
Variable
Description
PORT
8001
MONGO_DB_URI
MongoDB Atlas connection string
REDIS_URL
Redis connection string
FIREBASE_CLIENT_EMAIL
Service account email
FIREBASE_PRIVATE_KEY
Service account key (\n-escaped)
FIREBASE_PROJECT_ID
Firebase project id
services/chat/.env
Variable
Description
PORT
8002
MONGO_DB_URI
MongoDB Atlas connection string
services/agent/.env
Variable
Description
PORT
8003
MONGO_DB_URI
MongoDB Atlas connection string
GROQ_API_KEY
Groq LLM access
TAVILY_API_KEY
Web search
OPENROUTER_API_KEY
Coding agent model
GOOGLE_API_KEY
Gemini embeddings + vision
CHAT_SERVICE
e.g. http://localhost:8002
AUTH_SERVICE
e.g. http://localhost:8001
REDIS_URL
Redis connection string
AWS_BUCKET_NAME / AWS_REGION / AWS_ACCESS_KEY_ID / AWS_ACCESS_KEY
S3 fallback storage
B2_BUCKET_NAME / B2_ENDPOINT / B2_REGION / B2_KEY_ID / B2_APPLICATION_KEY
Backblaze B2 storage
QDRANT_API_KEY / QDRANT_URL
Vector DB for PDF RAG
services/billing/.env
Variable
Description
PORT
8004
MONGO_DB_URI
MongoDB Atlas connection string
RAZORPAY_KEY_ID
Razorpay key id
RAZORPAY_KEY_SECRET
Razorpay secret (used for HMAC verification)
AUTH_SERVICE
e.g. http://localhost:8001
In five separate terminals (each uses Node's native watcher):
npm run dev --prefix gateway # :8000
npm run dev --prefix services/auth # :8001
npm run dev --prefix services/chat # :8002
npm run dev --prefix services/agent # :8003
npm run dev --prefix services/billing # :8004
Then start the frontend with VITE_SERVER_URL=http://localhost:8000.
curl http://localhost:8000/
# {"success":true,"message":"Gateway request success."}
Method
Path
Auth
Description
*
/api/auth/**
public
Proxied to auth service
*
/api/chat/**
protect
Proxied with x-user-id
*
/api/agent/**
protect
Proxied with x-user-id
*
/api/billing/**
protect
Proxied with x-user-id
GET
/api/me
protect
Current session payload
Method
Path
Description
POST
/login
Verify Firebase token β create Redis session β set cookie
POST
/logout
Destroy session + clear cookie
POST
/update-plan
internal β apply plan upgrade + credits
POST
/check-credits
internal β pre-flight credit check
POST
/deduct-credits
internal β deduct cost, refresh session
Method
Path
Description
GET
/create-conversation
Create a conversation
GET
/get-conversations
List conversations (updatedAt desc)
POST
/update-conversation
Rename {id, title}
POST
/save-message
Persist a message incl. images + artifacts
GET
/get-messages/:conversationId
Message history
DELETE
/delete-conversation/:id
Soft delete conversation + messages
Method
Path
Description
POST
/chat
Run LangGraph β multipart/form-data {prompt, conversationId, agent, file} β {message, images, artifacts, remainingCredits}
Method
Path
Description
POST
/create
Create Razorpay order + Payment record
POST
/verify
HMAC-SHA256 verify β mark paid β upgrade plan
backend/
βββ docker-compose.yml # Redis
βββ .github/workflows/build-push.yml
βββ gateway/ # :8000 β proxy, CORS, protect middleware
β βββ index.js
β βββ middleware/auth.middleware.js
β βββ utils/proxyWithHeader.js
βββ shared/
β βββ redis/redis.js # shared ioredis client (baked into every image)
βββ services/
βββ auth/ # :8001
β βββ config/{db,firebase}.js
β βββ controllers/auth.controller.js
β βββ models/user.model.js
β βββ routes/auth.route.js
βββ chat/ # :8002
β βββ controllers/chat.controller.js
β βββ models/{conversation,message}.model.js
β βββ routes/chat.routes.js
βββ billing/ # :8004
β βββ config/{plans,razorpay}.js
β βββ controllers/billing.controller.js
β βββ models/payment.model.js
β βββ routes/billing.routes.js
βββ agent/ # :8003 β the AI core
βββ agents/{chat,coding,search,image,imageAnalyzer,pdf,ppt,pdfRag}.agent.js
βββ config/{llmModels,agentLimit,memory,vectorDB,multer,s3,b2,...}.js
βββ graph/{graph,router,state}.js
βββ controllers/agent.controller.js
βββ routes/agent.route.js
βββ utils/{checkCredits,deductCredits,generatePdf,generatePpt,...}.js
npm run lint --prefix ../frontend # frontend ESLint config
Backend services are verified end-to-end through health endpoints (GET / on each port) and the live gateway. Automated test suites are on the roadmap.
.github/workflows/build-push.yml runs on push to master:
dorny/paths-filter detects which services changed (gateway/**, services/<name>/**, shared/**, root lockfile).
Only the changed services build β Buildx β login to GHCR β tags latest + sha-<short> β build-push with GHA layer cache .
A Render deploy hook is POSTed per service to trigger a redeploy.
Each service ships a Dockerfile (node:20-alpine, layered npm install, EXPOSE 8000β8004). docker-compose.yml runs Redis only; MongoDB is Atlas.
Fork the repository
Create a feature branch β git checkout -b feature/amazing-thing
Commit your changes β git commit -m "Add amazing thing"
Push and open a Pull Request
This project is licensed under the MIT License β see the LICENSE file for details.
Built with Node.js, Express, LangGraph, and Redis Β· Part of the CalibAI project