Demo Gauntlet is an AI-powered simulation environment designed to help Solution Consultants and Sales Engineers practice their demo skills. It ingests a sales deck, researches the prospect/industry, and generates dynamic "Challenger Personas" (e.g., Skeptical CTO, ROI-focused CFO) to grill the user with tough questions.
- Deck Ingestion: Upload PDF or PPTX decks. The system parses text and slides.
- AI Research Agent: Automatically researches competitors, industry trends, and compliance risks based on the deck content.
- Challenger Personas: Simulates realistic stakeholders (CTO, CFO, CMO) with distinct personalities and concerns.
- Real-time Evaluation: Scores answers on the fly using an LLM-based evaluation engine with server-side ideal answer lookup.
- Session Reporting: Generates a detailed report card with strengths, weaknesses, and a readiness score.
- Security: JWT-authenticated API, server-side scoring, upload size limits, per-session guest isolation.
- Backend: Python, FastAPI, ChromaDB (Vector Store), Arq + Redis (background processing).
- Frontend: React, TypeScript, Vite, TailwindCSS.
- AI: Anthropic Claude (primary), OpenAI (optional fallback).
- Search: Brave Search (optional).
In production the backend is split into two scale-to-zero services on Google Cloud Run, with all shared state on networked, serverless backends:
- Web (
demo-gauntlet-backend, Cloud Run service,min-instances=0) — handles uploads, enqueues processing, serves results. - Worker (
demo-gauntlet-worker, Cloud Run Job,arq … --burst) — processes each deck (parse → OCR → embed → tag), then exits. Triggered by the web service on upload, with a Cloud Scheduler safety-net every 2h. - Job queue — Upstash Redis (serverless, TLS).
- File storage — Google Cloud Storage (
BLOB_STORAGE_TYPE=gcs). - Sessions / DB — Neon serverless Postgres (
DATABASE_URL). - Frontend — Vercel (
demo-gauntlet-ui.vercel.app).
Local development keeps everything on one machine via docker-compose (local
Redis, local disk, SQLite); the serverless backends above are production-only.
See CLAUDE.md for deploy commands and the full env-var/secret list.
- Python 3.10+
- Node.js 18+
- Redis (for background deck processing)
- Anthropic API Key (
ANTHROPIC_API_KEY) - OCR Dependencies (for slide parsing):
poppler(macOS:brew install poppler, Ubuntu:sudo apt-get install poppler-utils)tesseract(macOS:brew install tesseract, Ubuntu:sudo apt-get install tesseract-ocr)
git clone https://github.com/rjspence3/demo-gauntlet.git
cd demoGauntlet# Create virtual environment and install dependencies
make install
# Configure environment
cp .env.example .env
# Edit .env and set at minimum:
# ANTHROPIC_API_KEY — required for all LLM calls
# SECRET_KEY — required; any random string (e.g. openssl rand -hex 32)cd frontend
npm install
cd ..To enable the one-click demo login (auto-submits a guest session with a preset code):
# In .env (backend):
BETA_INVITE_CODE=your-invite-code
# In frontend/.env (or set as build env var):
VITE_DEMO_INVITE_CODE=your-invite-codeWhen VITE_DEMO_INVITE_CODE is set, the app automatically calls /auth/login with that code on page load. If the variable is not set, users must enter the code manually.
# Terminal 1: Backend
make run-backend
# Terminal 2: Frontend
make run-frontendAccess the application at http://localhost:5173.
- Backend API:
http://localhost:8001
- Linting:
make lint - Type Checking:
make typecheck - Testing:
make test
- Authentication: All API endpoints that generate LLM calls or mutate data require a valid JWT. Tokens are issued by
/auth/loginand must be passed asAuthorization: Bearer <token>. - Secret Key:
SECRET_KEYis used to sign JWTs. If the default value is detected at startup, the application logs a loudWARNING. In production (ENV_MODE=production) it refuses to start. Set this to any strong random value before exposing the service externally. - Upload Limits: File uploads are capped at 50 MB (HTTP 413 if exceeded).
- Server-Side Scoring: Ideal answers are looked up server-side only; the client never controls the grading key.
- CORS: By default, the API only accepts requests from
http://localhost:5173. UpdateALLOWED_ORIGINSin.envfor production. - Data: Locally, uploaded decks are stored in
data/decks. In production they go to a private Google Cloud Storage bucket (BLOB_STORAGE_TYPE=gcs), accessed via the service account — no public access.
MIT