AI-powered chat automation platform with an Express API, Next.js frontend, and a LangGraph-based Python agent with MCP tool integrations.
- Automated complex, multi-step user requests, successfully executing end-to-end task flows, by designing an agentic AI workflow engine in LangGraph that implements a Plan → Route → Execute pattern with LLM-driven task decomposition.
- Decreased overall LLM token consumption by 90% by architecting a smart integration registry that dynamically binds only contextually relevant Model Context Protocol (MCP) tools per request instead of loading the entire toolset.
- Increased autonomous task completion rate by over 25% by engineering self-correction mechanisms and reasoning loops that allow the AI agent to dynamically evaluate output and gracefully recover from tool errors.
- Guaranteed the safe execution of AI-driven actions with real-world consequences, resulting in zero unauthorized system mutations, by implementing a state-based Human-in-the-Loop (HITL) system that supports mid-workflow approve, edit, and skip decisions.
- Ensured high availability of the real-time AI workflow engine, maintaining 99.9% system uptime, by provisioning and deploying the production backend infrastructure and PostgreSQL databases on AWS EC2 instances.
Technical Blog: Building an Autonomous AI Agent: A Deep Dive into the Architecture
| Service | Tech | Port |
|---|---|---|
| Web | Next.js 16, React 19, TailwindCSS | 3000 |
| API | Express 5, tRPC, Passport.js, Prisma, JWE | 8000 |
| Agent | FastAPI, LangGraph, LangChain, MCP | 8001 |
| Database | PostgreSQL 16 | 5432 |
| Proxy | Nginx | 8080 |
┌──────────────────────────────────────────────────┐
│ Nginx (:8080) │
│ │
│ / → Web (:3000) │
│ /auth/* → API (:8000) │
│ /trpc/* → API (:8000) │
│ /oauth/* → API (:8000) │
│ /agent/* → Agent (:8001) │
└──────────────────────────────────────────────────┘
Choose your setup method:
- Docker Setup — Recommended for quick start, all services containerized
- Local Development — For active development with hot reload
- Docker & Docker Compose
cp .env.docker .envGenerate a session secret and fill in the required values:
openssl rand -base64 32 # paste this as SESSION_SECRETRequired values in .env:
| Variable | Where to get it |
|---|---|
SESSION_SECRET |
Run openssl rand -base64 32 |
GOOGLE_CLIENT_ID |
Google Cloud Console |
GOOGLE_CLIENT_SECRET |
Google Cloud Console |
GOOGLE_API_KEY |
Google AI Studio |
TAVILY_API_KEY |
Tavily |
- Go to APIs & Services → Credentials
- Create or select an OAuth 2.0 Client ID (Application type: Web application)
- Under Authorized redirect URIs, add:
http://localhost:8080/auth/google/callback - Under Authorized JavaScript origins, add:
http://localhost:8080 - Enable these APIs in API Library:
- Google People API (for login profile)
- Gmail API (if using Gmail integration)
- Google Drive API (if using Drive/Docs/Sheets/Slides)
- Google Calendar API (if using Calendar integration)
- Go to Notion Integrations → New integration
- Set Redirect URI to:
http://localhost:8080/oauth/notion/callback - Add to
.env:NOTION_CLIENT_ID=your-notion-client-id NOTION_CLIENT_SECRET=your-notion-client-secret
docker compose upAccess at http://localhost:8080
- Node.js 20+
- pnpm 9+
- Python 3.11+ with uv
- PostgreSQL 16 (local or cloud)
cp .env.example .envFill in the required values in .env:
| Variable | Where to get it |
|---|---|
DATABASE_URL |
PostgreSQL connection string (local or cloud like Neon, Supabase) |
SESSION_SECRET |
Run openssl rand -base64 32 |
GOOGLE_CLIENT_ID |
Google Cloud Console |
GOOGLE_CLIENT_SECRET |
Google Cloud Console |
GOOGLE_API_KEY |
Google AI Studio |
TAVILY_API_KEY |
Tavily |
Same as Docker Setup, but use these URLs:
- Authorized redirect URIs:
http://localhost:8000/auth/google/callback - Authorized JavaScript origins:
http://localhost:3000
# Install Node.js dependencies
pnpm install
# Install Python dependencies
cd apps/agent && uv sync && cd ../..pnpm --filter @workspace/database db:pushpnpm devThis starts:
- Web at http://localhost:3000
- API at http://localhost:8000
- Agent at http://localhost:8001
| Endpoint | Method | Description |
|---|---|---|
/auth/google |
GET | Redirect to Google OAuth |
/auth/google/callback |
GET | Handle Google OAuth callback |
/auth/logout |
POST | Destroy session & clear cookies |
/auth/me |
GET | Get current user (requires auth) |
/auth/status |
GET | Check authentication status |
| Endpoint | Method | Description |
|---|---|---|
/oauth/gmail |
GET | Redirect to Gmail OAuth |
/oauth/gmail/callback |
GET | Handle Gmail OAuth callback |
/oauth/google-docs |
GET | Redirect to Google Docs OAuth |
/oauth/google-docs/callback |
GET | Handle Google Docs OAuth callback |
/oauth/google-sheets |
GET | Redirect to Google Sheets OAuth |
/oauth/google-sheets/callback |
GET | Handle Google Sheets OAuth callback |
/oauth/google-slides |
GET | Redirect to Google Slides OAuth |
/oauth/google-slides/callback |
GET | Handle Google Slides OAuth callback |
/oauth/google-drive |
GET | Redirect to Google Drive OAuth |
/oauth/google-drive/callback |
GET | Handle Google Drive OAuth callback |
/oauth/google-calendar |
GET | Redirect to Google Calendar OAuth |
/oauth/google-calendar/callback |
GET | Handle Google Calendar OAuth callback |
/oauth/notion |
GET | Redirect to Notion OAuth |
/oauth/notion/callback |
GET | Handle Notion OAuth callback |
/oauth/vercel |
GET | Redirect to Vercel OAuth |
/oauth/vercel/callback |
GET | Handle Vercel OAuth callback |
All tRPC procedures are available at /trpc/[procedure].
See packages/trpc/src/routers/ for available procedures.
| Endpoint | Method | Description |
|---|---|---|
/agent/health |
GET | Health check |
/agent/chat |
POST | Send chat message |
/agent/chat/stream |
POST | Send chat message (SSE stream) |
/agent/chat/status/{thread_id} |
GET | Get chat thread status |
/agent/chat/retry |
POST | Retry failed message |
/agent/chat/resume |
POST | Resume interrupted chat |
/agent/sync-gmail-credentials |
POST | Sync Gmail OAuth credentials |
chat-automation/
├── apps/
│ ├── api/ # Express API server
│ ├── web/ # Next.js frontend
│ └── agent/ # Python AI agent (FastAPI + LangGraph)
├── packages/
│ ├── database/ # Prisma schema & client
│ ├── trpc/ # Shared tRPC routers & adapters
│ ├── ui/ # Shared UI components
│ ├── eslint-config/
│ └── typescript-config/
├── nginx/ # Nginx reverse proxy config
├── docker-compose.yml
├── turbo.json
└── pnpm-workspace.yaml
LangGraph workflow implementing Plan → Route → Execute (Auto/Approval) → Loop pattern with Human-in-the-Loop (HITL) support.
+----------+
| START |
+----+-----+
|
v
+-----------------+
| SMART ROUTER | <-- Classify integrations, check auth
+--------+--------+
|
v
+-----------------+
| PLANNER | <-- LLM creates plan with HITL flags
| (structured out)|
+--------+--------+
|
v
+--------------------+
| ROUTE_EXECUTOR | <-- Routes based on requires_human_approval
+--------+-----------+
|
v
+--------+-------------------------+
| |
| approval=false | approval=true
| |
v v
+----------+ +------------------------+
| EXECUTOR |<---+ | EXECUTOR_WITH_APPROVAL |<---+
| (auto) | | | (state-based HITL) | |
+----+-----+ | +-----------+------------+ |
| | | |
| should_ | | should_ |
| continue | | continue |
v | v |
+--------+ | +--------+ |
| TOOLS |------+ | TOOLS |-------------+
+--------+ route_after_tools +--------+ route_after_tools
| (no more tool calls) |
v v
+-------------------+
| STEP_COMPLETE | <-- Extract artifacts, advance index
+---------+---------+
|
v
+---------------------+
| should_execute_next |
+---------+-----------+
|
+-------+-------+
| |
route_executor end
| |
v v
(loop) +-----+
| END |
+-----+
| Node | Description |
|---|---|
smart_router |
Dynamic integration loading, auth pre-flight |
planner |
LLM creates structured plan with HITL flags |
executor |
Auto-execution (no approval needed) |
executor_with_approval |
State-based Human-in-the-Loop execution |
tools |
MCP tool calling (multi-hop supported) |
step_complete |
Clears executor state, prepares next step |
- Multi-hop tool calling: Executor can call tools multiple times
- HITL (Human-in-the-Loop): LLM decides which steps need approval
- State-based approval: Approval state persists across tool calls
- Smart routing: Dynamic integration loading based on user's connected services
- Checkpointing: MemorySaver for workflow state persistence
MIT


