Skip to content

Latest commit

Β 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 E-commerce Operations Brain

An AI-powered multi-agent system that operates like a smart operations manager for your online store β€” diagnosing issues, recommending actions, and learning from the past.

Python LangGraph EPAM DIAL React License: MIT Status


πŸ“– Table of Contents


🌐 Overview

The E-commerce Operations Brain is a multi-agent AI system designed to simulate an intelligent operations team for an online store. Instead of querying a single dashboard, a business user can ask natural-language questions and receive:

  • πŸ” Root cause analysis across multiple business domains
  • πŸ“‹ Actionable recommendations with reasoning
  • βœ… Safe execution β€” actions only happen after human approval
  • 🧠 Memory-backed insights β€” learns from past incidents

This system is built with agentic AI principles: specialized agents collaborate, share findings, and synthesize a final decision β€” just like a real ops team.


❗ Problem Statement

E-commerce businesses generate signals across dozens of systems: sales data, inventory levels, marketing dashboards, customer support tickets, and more. When something goes wrong β€” like a revenue drop β€” no single system tells the full story.

The operational question is always cross-domain:

"Was yesterday's sales drop caused by inventory going out of stock, a campaign failing, or a surge in customer complaints?"

Traditional BI dashboards require a human analyst to manually correlate these signals. This project replaces that manual effort with an autonomous, reasoning AI system that:

  1. Understands the business question in natural language
  2. Investigates each relevant domain independently
  3. Correlates findings to identify root causes
  4. Recommends and executes corrective actions with human oversight

πŸ—οΈ System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              REACT + EPAM UUI LOVESHIP FRONTEND                 β”‚
β”‚        Chat Console β”‚ HITL Panel β”‚ Dashboard β”‚ Incidents        β”‚
β”‚               nginx (port 3000) β†’ proxies /api/*                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚  Natural Language Query
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    FASTAPI BACKEND                              β”‚
β”‚    POST /api/query/submit  β”‚  GET /api/query/{job_id}           β”‚
β”‚    POST /api/actions       β”‚  GET /api/incidents                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    ORCHESTRATOR NODE                            β”‚
β”‚   β€’ Classifies intent (diagnosis/action/memory/report/chitchat) β”‚
β”‚   β€’ Selects active agents via AGENT_REGISTRY                    β”‚
β”‚   β€’ Loads session context from Redis                            β”‚
β”‚   β€’ Pre-fetches similar past incidents from ChromaDB (RAG)      β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚          β”‚          β”‚          β”‚          β”‚
       β–Ό          β–Ό          β–Ό          β–Ό          β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  parallel via asyncio
  β”‚  Sales  β”‚ β”‚Inventory β”‚ β”‚ Mktg & β”‚ β”‚Support β”‚
  β”‚  Agent  β”‚ β”‚  Agent   β”‚ β”‚Campaignβ”‚ β”‚& CX    β”‚
  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ Agent  β”‚ β”‚ Agent  β”‚
       β”‚           β”‚       β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό  (all join into analyst_outputs)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MOCK TOOL APIS  (GET /tools/sales|inventory|marketing|support) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    SYNTHESIS NODE                               β”‚
β”‚   Merges analyst outputs + RAG past incidents β†’ root causes     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    REFLECTION NODE                              β”‚
β”‚   Self-audits conclusions for gaps and low-confidence signals   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
   β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ Action proposed?            β”‚
   β–Ό yes                         β–Ό no
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ HITL Gateβ”‚               β”‚Final Responseβ”‚
β”‚ (pause)  β”‚               β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                      β”‚
     β”‚ approved                   β”‚
     β–Ό                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚Action        β”‚        β”‚           MEMORY WRITER                 β”‚
β”‚Executor      │───────►│  PostgreSQL (incident log)              β”‚
β”‚POST /tools/  β”‚        β”‚  ChromaDB (vector embed for future RAG) β”‚
β”‚actions/...   β”‚        β”‚  Redis (session history TTL 30 min)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ€– Agent Roles & Responsibilities

Agent Responsibility Invoked for
Orchestrator Classifies intent, selects active agents, loads Redis session, fetches RAG context Every query
Sales Agent Calls GET /tools/sales, analyses revenue trends, order volume, regional performance diagnosis, action, memory, report
Inventory Agent Calls GET /tools/inventory, detects stockouts and low-stock impact diagnosis, action, memory, report
Marketing Agent Calls GET /tools/marketing, surfaces campaign pauses and promo issues diagnosis, action, memory, report
Support Agent Calls GET /tools/support, correlates complaint volume with business events diagnosis, action, memory, report
Synthesis Node Merges all analyst outputs + RAG past incidents into ranked root causes Every query (post-agents)
Reflection Node Self-audits synthesis for weak or incomplete conclusions Every query (post-synthesis)
HITL Node Emits ActionProposal, checkpoints state to Redis, pauses for human approval action queries
Action Executor Calls POST /tools/actions/{type} only after hitl_approved == True Approved actions only
Memory Writer Single write path: PostgreSQL + ChromaDB + Redis session Every resolved query

✨ Key Features

  • πŸ” Multi-Agent Orchestration β€” Specialist agents work in parallel, findings get synthesized
  • 🌐 Cross-Domain Root Cause Analysis β€” Correlates signals across sales, inventory, marketing, and CX
  • 🧠 Dual Memory System β€” Short-term session context + long-term incident memory
  • πŸ›‘ Human-in-the-Loop (HITL) β€” All destructive or impactful actions require explicit approval
  • πŸͺž Self-Reflection Layer β€” Orchestrator checks for weak conclusions before finalizing
  • πŸ“ Structured Outputs β€” Every response is machine-readable and downstream-ready
  • πŸ”­ Observability β€” Every agent decision and tool call is logged with reasoning traces
  • πŸ§ͺ Evaluation Suite β€” Automated tests for agent behavior on business scenarios

πŸ› οΈ Tech Stack

Layer Technology Notes
LLM EPAM DIAL (GPT-4o via AzureChatOpenAI) OpenAI-compatible API β€” configured via DIAL_API_KEY
Agent Framework LangGraph 0.2 Single adaptive graph; one graph, not multiple
Backend FastAPI 0.115 + uvicorn Mock tool APIs + async job endpoints
Memory β€” Short-Term Redis (TTL 30 min) Session context + in-flight graph state checkpoint
Memory β€” Long-Term PostgreSQL + asyncpg + SQLAlchemy Incident log (query β†’ root causes β†’ actions β†’ outcome)
Memory β€” Vector ChromaDB 0.5 (embedded, no server) Semantic search for RAG over past incidents
Observability LangSmith Trace spans around graph execution, configured at app startup
UI React 18 + EPAM UUI Loveship + Vite Chat console, operations dashboard, HITL panel, incident history β€” served via nginx
Async Python asyncio Parallel analyst execution + non-blocking query jobs
Testing Pytest + pytest-asyncio Unit + integration + 5 core scenario tests

πŸ“ Project Structure

ecomm-ops-brain/
β”‚
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ main.py                      # FastAPI entry point + CORS middleware
β”‚   β”œβ”€β”€ config.py                    # Settings (env vars) + get_llm() + AGENT_REGISTRY
β”‚   β”‚
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ query.py                 # POST /api/query/submit, GET /api/query/{job_id}, DELETE
β”‚   β”‚   β”œβ”€β”€ actions.py               # POST /api/actions (HITL resume)
β”‚   β”‚   β”œβ”€β”€ incidents.py             # GET /api/incidents
β”‚   β”‚   └── dashboard.py             # GET /api/dashboard (operations dashboard payload)
β”‚   β”‚
β”‚   β”œβ”€β”€ graph/
β”‚   β”‚   β”œβ”€β”€ state.py                 # AgentState TypedDict
β”‚   β”‚   β”œβ”€β”€ graph.py                 # LangGraph graph compilation
β”‚   β”‚   β”œβ”€β”€ builder.py               # Node + edge wiring
β”‚   β”‚   β”œβ”€β”€ agents_runner.py         # Parallel analyst execution via asyncio.gather
β”‚   β”‚   β”œβ”€β”€ routing.py               # Conditional edge logic
β”‚   β”‚   └── nodes/
β”‚   β”‚       β”œβ”€β”€ orchestrator.py      # Intent classification + RAG fetch
β”‚   β”‚       β”œβ”€β”€ synthesis.py         # Cross-domain root-cause synthesis
β”‚   β”‚       β”œβ”€β”€ reflection.py        # Self-check for weak conclusions
β”‚   β”‚       β”œβ”€β”€ hitl.py              # HITL pause gate + Redis checkpoint
β”‚   β”‚       └── action_executor.py   # Executes approved actions
β”‚   β”‚
β”‚   β”œβ”€β”€ agents/                      # Analyst agents (called by agents_runner.py)
β”‚   β”‚   β”œβ”€β”€ base_agent.py
β”‚   β”‚   β”œβ”€β”€ sales_agent.py
β”‚   β”‚   β”œβ”€β”€ inventory_agent.py
β”‚   β”‚   β”œβ”€β”€ marketing_agent.py
β”‚   β”‚   └── support_agent.py
β”‚   β”‚
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ query_service.py         # Graph invocation + runtime stage signalling
β”‚   β”‚   β”œβ”€β”€ action_service.py        # HITL resume + action execution + runtime stage updates
β”‚   β”‚   β”œβ”€β”€ dashboard_service.py     # Dashboard stats, backend health, and data-source labels
β”‚   β”‚   └── incident_service.py      # Incident read + ChromaDB semantic search
β”‚   β”‚
β”‚   β”œβ”€β”€ tools/                       # Mock FastAPI routes
β”‚   β”‚   β”œβ”€β”€ sales.py                 # GET /tools/sales
β”‚   β”‚   β”œβ”€β”€ inventory.py             # GET /tools/inventory
β”‚   β”‚   β”œβ”€β”€ marketing.py             # GET /tools/marketing
β”‚   β”‚   β”œβ”€β”€ support.py               # GET /tools/support
β”‚   β”‚   └── actions.py               # POST /tools/actions/{action_type}
β”‚   β”‚
β”‚   β”œβ”€β”€ memory/
β”‚   β”‚   β”œβ”€β”€ redis_client.py          # Session state + runtime stage diagnostics
β”‚   β”‚   β”œβ”€β”€ postgres_client.py       # Incident CRUD
β”‚   β”‚   β”œβ”€β”€ chroma_client.py         # Vector embed + cosine similarity search
β”‚   β”‚   └── memory_writer.py         # Single write path for all three stores
β”‚   β”‚
β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   β”œβ”€β”€ query.py                 # QueryResult, IncidentContext
β”‚   β”‚   β”œβ”€β”€ agents.py                # AnalystOutput per domain
β”‚   β”‚   β”œβ”€β”€ actions.py               # ActionProposal, ActionResult
β”‚   β”‚   └── incidents.py             # Incident, IncidentSummary
β”‚   β”‚
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ error_handler.py         # Global FastAPI exception handlers
β”‚   β”‚   β”œβ”€β”€ dependencies.py          # DI: shared httpx/redis client instances
β”‚   β”‚   β”œβ”€β”€ llm_utils.py             # invoke_with_retry() β€” tenacity wrapper for all LLM calls
β”‚   β”‚   └── rate_limiter.py          # slowapi Limiter singleton (avoids circular import)
β”‚   β”‚
β”‚   └── observability/
β”‚       └── tracer.py                # configure_tracing() for LangSmith environment bootstrap
β”‚
β”œβ”€β”€ frontend/                        # React + EPAM UUI Loveship frontend
β”‚   β”œβ”€β”€ Dockerfile                   # Multi-stage: node:20 builds, nginx:alpine serves
β”‚   β”œβ”€β”€ nginx.conf                   # /api/* proxied to backend container
β”‚   β”œβ”€β”€ package.json                 # @epam/loveship, react-router-dom, vite
β”‚   β”œβ”€β”€ vite.config.ts
β”‚   └── src/
β”‚       β”œβ”€β”€ main.tsx                 # React entry + loveship CSS import
β”‚       β”œβ”€β”€ App.tsx                  # BrowserRouter + layout
β”‚       β”œβ”€β”€ index.css                # Loveship dark theme CSS variables
β”‚       β”œβ”€β”€ api/client.ts            # All fetch calls (submit, poll, cancel, action, dashboard)
β”‚       β”œβ”€β”€ types/index.ts           # TypeScript types matching backend schemas
β”‚       β”œβ”€β”€ components/
β”‚       β”‚   β”œβ”€β”€ Sidebar.tsx          # Dark nav sidebar (Chat / Dashboard / Incidents)
β”‚       β”‚   β”œβ”€β”€ ChatPage.tsx         # Chat UI with polling, badges, expanders
β”‚       β”‚   β”œβ”€β”€ HITLPanel.tsx        # Per-action-type editable approval panel
β”‚       β”‚   β”œβ”€β”€ DashboardPage.tsx    # Metrics grid, agent cards, bar chart, event feed
β”‚       β”‚   └── IncidentsPage.tsx    # Searchable incident history with expandable cards
β”‚       └── pages/                   # Barrel re-exports for React Router
β”‚
β”œβ”€β”€ data/
β”‚   └── incidents.json               # 2000 seeded incidents
β”‚
β”œβ”€β”€ scripts/
β”‚   └── seed_incidents.py            # Seeds PostgreSQL + ChromaDB (idempotent)
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ unit/
β”‚   β”‚   β”œβ”€β”€ test_agents.py
β”‚   β”‚   β”œβ”€β”€ test_nodes.py
β”‚   β”‚   β”œβ”€β”€ test_schemas.py
β”‚   β”‚   └── test_memory.py
β”‚   └── integration/
β”‚       β”œβ”€β”€ test_api.py
β”‚       β”œβ”€β”€ test_graph.py
β”‚       └── test_scenarios.py        # 5 core demo scenarios
β”‚
β”œβ”€β”€ alembic/                         # Database migrations
β”œβ”€β”€ .env.example
β”œβ”€β”€ requirements.txt
└── CLAUDE.md                        # AI coding context and conventions

πŸš€ Getting Started

Prerequisites

  • Docker Desktop with WSL 2 backend (recommended) β€” runs all services in containers
  • An EPAM DIAL API key (OpenAI-compatible endpoint)
  • (Optional) LangSmith account for tracing

For local development without Docker: Python 3.11+, Node 20+, Redis, PostgreSQL 16


Installation

# 1. Clone the repository
git clone https://git.epam.com/your-username/ecomm-ops-brain.git
cd ecomm-ops-brain

# 2. Create a virtual environment
python -m venv .venv
source .venv/bin/activate        # On Windows: .venv\Scripts\activate

# 3. Install dependencies
pip install -r requirements.txt

Environment Variables

Copy .env.example to .env and fill in your values:

cp .env.example .env
# EPAM DIAL
DIAL_API_KEY=your-dial-api-key-here
DIAL_API_BASE=https://your-dial-endpoint/openai
DIAL_MODEL=gpt-4o

# LangSmith (optional, for observability)
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your-langsmith-api-key-here
LANGCHAIN_PROJECT=ecomm-ops-brain

# Redis (start via WSL: sudo service redis-server start)
REDIS_URL=redis://localhost:6379

# PostgreSQL
POSTGRES_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/ecomm_ops

# ChromaDB (embedded β€” no server needed)
CHROMA_PATH=./chroma_data

# App
LOG_LEVEL=INFO
HITL_TIMEOUT_SECONDS=120

Running the System

🐳 Docker (recommended)

# Clone and configure env
git clone https://git.epam.com/your-username/ecomm-ops-brain.git
cd ecomm-ops-brain
cp .env.example .env   # fill in DIAL_API_KEY and optionally LANGCHAIN_API_KEY

# Build and start all 4 services (postgres, redis, backend, frontend)
docker compose up --build
Service URL
React frontend http://localhost:3000
FastAPI backend http://localhost:8000
Swagger docs http://localhost:8000/docs

docker-entrypoint.sh automatically runs Alembic migrations and seeds 2000 incidents on first start.

πŸ’» Local (without Docker)

# 1. Start Redis + PostgreSQL manually (or via WSL)
sudo service redis-server start
sudo service postgresql start

# 2. Install Python dependencies
pip install -r requirements.txt

# 3. Run migrations and seed
alembic upgrade head
python scripts/seed_incidents.py

# 4. Start backend
uvicorn app.main:app --reload --port 8000

# 5. Start React frontend (separate terminal)
cd frontend
npm install
npm run dev   # http://localhost:3000

Run tests:

pytest tests/ -v

πŸ’¬ Usage Examples

πŸ“Š Dashboard Notes

  • The dashboard (/dashboard) is an operations view β€” business health score, inventory risk table, agent work cards, regional revenue bar chart, and recent activity feed.
  • All data is live from PostgreSQL and Redis β€” no mock data on the dashboard.
  • Revenue cards, regional sales breakdown, and support SLA/CSAT trends are sourced from the sales_daily_metrics and support_daily_metrics PostgreSQL tables.

1. Diagnosing a Business Issue

Input:

"Why did sales drop yesterday?"

System Output (structured):

{
  "summary": "Sales dropped 34% yesterday compared to the prior 7-day average.",
  "root_causes": [
    {
      "domain": "Inventory",
      "finding": "3 top-selling SKUs were out of stock for 14+ hours",
      "confidence": 0.91
    },
    {
      "domain": "Marketing",
      "finding": "Email campaign scheduled for 10am was not sent due to a config error",
      "confidence": 0.87
    }
  ],
  "recommended_actions": [
    "Restock SKUs: SKU-102, SKU-207, SKU-334",
    "Reschedule or resend email campaign",
    "Apply 10% promotional discount to affected products"
  ],
  "memory_context": "Similar drop occurred on 2024-11-03 β€” resolved by restocking + campaign relaunch"
}

2. Taking Corrective Action (HITL)

Input:

"Fix the issue."

System pauses and displays:

⚠️  The following actions require your approval before execution:

  [1] Restock SKU-102, SKU-207, SKU-334 (triggers purchase order)
  [2] Reschedule email campaign for 2pm today
  [3] Apply 10% discount to top 3 affected products for 48 hours

Approve all? [yes/no] or select: [1, 2, 3]

User input: 1 2

System executes approved actions only and logs outcome.


3. Memory-Based Recall

Input:

"What did we do last time this happened?"

Output:

On 2024-11-03, a similar 31% sales drop was caused by stockouts + a failed campaign.
Actions taken:
  βœ… Restocked 4 SKUs β†’ resolved within 6 hours
  βœ… Relaunched campaign β†’ recovered 80% of lost revenue by EOD
  ❌ Discount offer β€” not used, deemed unnecessary

Recommendation: Prioritize restock + campaign relaunch over discount.

🧰 Tool Catalog

All tools are mock FastAPI routes under /tools/ that return realistic seeded data for three core scenarios.

Endpoint Method Domain Description
/tools/sales GET Sales Revenue, order count, AOV, regional breakdown, promo status
/tools/inventory GET Inventory Stock levels, stockout products, low-stock alerts
/tools/marketing GET Marketing Campaign performance, paused campaigns, active promos
/tools/support GET Support Complaint volume, top issue categories, CSAT score
/tools/actions/restock POST Action Restocks products to 100 units (HITL)
/tools/actions/resume_campaign POST Action Resumes a paused campaign (HITL)
/tools/actions/apply_discount POST Action Applies promotional discount to SKUs (HITL)
/tools/actions/extend_promo POST Action Extends an active promotion's end date (HITL)
/tools/actions/create_support_ticket POST Action Opens a support escalation ticket (HITL)
/tools/actions/escalate POST Action Escalates an existing issue (HITL)

⚠️ All /tools/actions/ endpoints are guarded by HITL β€” they will never be called without hitl_approved == True.


🧠 Memory System

The system uses a three-layer memory architecture, all written through a single memory_writer.py to avoid scattered writes.

Short-Term Memory (Redis)

  • Keyed by session_id, TTL = 30 minutes
  • Stores the current AgentState snapshot so the graph can be resumed after HITL pause
  • Also tracks runtime stage (orchestrator β†’ agents β†’ synthesis β†’ reflection β†’ hitl β†’ action β†’ done β†’ idle) for internal diagnostics and troubleshooting

Long-Term Memory (PostgreSQL)

  • incidents table: id, timestamp, query, query_type, root_causes, actions_proposed, actions_approved, outcome_notes, conversation_history
  • Written by memory_writer.py at the end of every resolved query
  • Managed with Alembic migrations

Vector Memory (ChromaDB β€” embedded)

  • Each resolved incident is embedded and stored on write
  • Retrieved via cosine similarity search at the start of every query (RAG)
  • Top-3 similar past incidents are injected into the synthesis prompt as context
  • No separate ChromaDB server needed β€” runs embedded in ./chroma_data/

Schema of a stored incident:

{
  "incident_id": "uuid",
  "timestamp": "2026-04-13T10:00:00Z",
  "query": "Why did sales drop yesterday?",
  "query_type": "diagnosis",
  "root_causes": ["3 SKUs out of stock", "campaign paused"],
  "actions_proposed": ["restock", "resume_campaign"],
  "actions_approved": ["restock"],
  "outcome_notes": "Revenue recovered 80% within 24h"
}

πŸ›‘ Human-in-the-Loop (HITL)

Any action that modifies business state is gated behind a mandatory human approval step enforced in two places in code β€” hitl.py (graph node) and action_executor.py (both assert hitl_approved == True before proceeding).

Flow:

  1. Synthesis determines an action is needed β†’ hitl_node emits ActionProposal and sets hitl_approved = None
  2. Graph checkpoints full AgentState to Redis and returns control to the UI
  3. Streamlit hitl_panel.py renders the approval card β€” operator clicks Approve, Reject, or edits parameters
  4. UI sends POST /api/actions with { session_id, decision, selected_action_index }
  5. action_service.py loads the paused state from Redis, sets hitl_approved, and invokes action_executor_node

Principles:

  • βœ… The system will always propose before executing
  • βœ… Operators can approve, reject, or modify action parameters before confirming
  • βœ… Rejected actions are logged as "declined" in the incident record
  • βœ… HITL timeout: HITL_TIMEOUT_SECONDS (default 120 s) β€” returns 408 if not actioned in time
  • ❌ No action bypasses this gate β€” the guard is enforced in both node and executor code

πŸ”­ Observability & Logging

Graph execution is instrumented end-to-end:

  • LangSmith Integration β€” Application startup calls configure_tracing() and the graph uses LangSmith trace spans around orchestrator, agent runner, synthesis, reflection, HITL, and action execution.
  • Redis Stage Tracking β€” Each node updates its runtime stage (orchestrator β†’ agents β†’ synthesis β†’ reflection β†’ hitl β†’ action β†’ done β†’ idle) so execution state is available for debugging and future admin diagnostics.
  • Dashboard Data Labels β€” The operations dashboard distinguishes persisted operational data from demo sales/support snapshots so the UI does not imply unavailable historical data is live.

To view LangSmith traces: https://smith.langchain.com β†’ Project: ecomm-ops-brain


πŸ§ͺ Evaluation & Testing

tests/
β”œβ”€β”€ unit/
β”‚   β”œβ”€β”€ test_agents.py       # Each analyst agent in isolation (mock tool responses)
β”‚   β”œβ”€β”€ test_nodes.py        # Graph nodes in isolation (mock AgentState)
β”‚   β”œβ”€β”€ test_schemas.py      # Pydantic schema validation + serialisation
β”‚   └── test_memory.py       # Memory clients with mock backends
└── integration/
    β”œβ”€β”€ test_api.py          # FastAPI endpoint tests (TestClient)
    β”œβ”€β”€ test_graph.py        # Full graph execution against mock tool APIs
    └── test_scenarios.py    # 5 core demo scenarios end-to-end

5 core demo scenarios (must all pass before the project is considered complete):

# Question Expected behaviour
1 "Why did sales drop yesterday?" Cross-domain synthesis citing inventory + campaign signals
2 "Fix the problem." ActionProposal emitted, graph pauses for HITL
3 "What did we do last time this happened?" ChromaDB recall surfaces β‰₯1 past incident
4 "Which products are close to stock-out?" Inventory analyst only, structured list response
5 "Summarize yesterday's business health." Full structured report, no action proposed
# Run all tests
pytest tests/ -v

# Run only scenario tests
pytest tests/integration/test_scenarios.py -v

πŸ—ΊοΈ Roadmap

  • Project scaffolding and architecture design
  • Mock tool APIs (sales, inventory, marketing, support, actions)
  • Individual specialist agents (Sales, Inventory, Marketing, Support)
  • Orchestrator with LangGraph state machine + intent classification
  • Parallel agent execution via asyncio
  • Short-term memory via Redis (session context + HITL checkpoint)
  • Long-term memory β€” PostgreSQL incident log + Alembic migrations
  • Vector memory β€” ChromaDB embedded + RAG in synthesis
  • Human-in-the-Loop approval gate (pause β†’ approve/reject β†’ resume)
  • Self-reflection / gap detection layer
  • Structured output schema validation (Pydantic)
  • FastAPI REST interface with async job system (submit/poll/cancel)
  • LangSmith observability integration
  • React + EPAM UUI Loveship frontend β€” chat console, HITL panel, incident history
  • Operations dashboard with health score, agent cards, inventory risk, and activity feed
  • Multi-stage Docker build (node:20 β†’ nginx:alpine) with nginx API proxy
  • Incident seed script (2000 past incidents)
  • Test suite β€” unit + integration + 5 core scenarios

🀝 Contributing

Contributions, issues, and feature requests are welcome!

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Commit your changes: git commit -m 'feat: add your feature'
  4. Push to the branch: git push origin feature/your-feature-name
  5. Open a Pull Request

πŸ“„ License

This project is under the EPAM R&D Python Training.


πŸ‘€ Author

Esha Jawade Built with ❀️ as a deep-learning AI engineering project.
Guided by principles of multi-agent design, responsible AI (HITL), and production-grade observability.

"The best ops team is one that never sleeps, never misses a signal, and always asks before acting."

About

Multi-Agent Ecommerce Operational Brain

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages