An AI-Powered Social Gym for Improvisational Comedy Practice
Note: This project uses Application-Level OAuth 2.0 for authentication with Google Sign-In and email whitelist access control.
Improv Olympics is a multi-agent AI application that enables users to practice improvisational comedy skills through interactive text-based or live audio sessions with specialized AI agents. Built on Google Cloud Platform with Application-Level OAuth 2.0 authentication and per-user rate limiting to support a pilot launch for 10-50 early adopters.
- Overview
- Architecture
- Key Features
- Quick Start
- Project Structure
- Documentation
- Deployment
- Development
- Testing
- Contributing
- License
Improv Olympics provides an interactive learning environment where users practice improvisational comedy through AI-powered sessions. Five specialized agents orchestrate the experience using Google's Agent Development Kit (ADK):
- Stage Manager Agent - Orchestrates the multi-agent experience across all sub-agents
- Partner Agent - Phase-aware scene partner that adapts behavior based on user skill level
- Room Agent - Simulates audience reactions and collective vibe using sentiment analysis
- Coach Agent - Delivers actionable feedback using improv principles database
- MC Agent - (Future) Introduces games and guides session flow
- Backend: FastAPI (Python)
- AI Models: Google Gemini 2.0 Flash Exp via VertexAI
- Agent Framework: Google Agent Developer Toolkit (ADK)
DatabaseSessionServicefor session persistence (SQLite)VertexAiRagMemoryServicefor cross-session learningCloudTraceCallbackfor native observabilityInMemoryRunnersingleton pattern for efficient execution
- Database: Google Cloud Firestore (rate limits), SQLite (ADK sessions)
- Hosting: Google Cloud Run (serverless containers)
- Authentication: Application-Level OAuth 2.0 with Google Sign-In (authlib, itsdangerous)
- Infrastructure: Terraform
- CI/CD: Cloud Build
- Monitoring: Cloud Logging, Cloud Monitoring, Cloud Trace
┌─────────────┐
│ User │
│ Browser │
└──────┬──────┘
│ HTTPS
▼
┌──────────────────┐
│ Cloud Load │
│ Balancer │◄─── Google-managed SSL
└────────┬─────────┘
│
▼
┌─────────────────────┐
│ Cloud Run │
│ (FastAPI App) │
│ ┌───────────────┐ │
│ │ OAuth Session │ │
│ │ Middleware │ │◄─── Application-Level OAuth 2.0
│ ├───────────────┤ │ (session cookies)
│ │ Rate Limiter │ │
│ ├───────────────┤ │
│ │ Session Mgr │ │
│ ├───────────────┤ │
│ │ ADK Agents │ │
│ └───────────────┘ │
└────────┬────────────┘
│
├──────────► Firestore (sessions, rate limits)
│
└──────────► VertexAI (Gemini models)
User Input
│
▼
┌──────────────────┐
│ Stage Manager │ (Gemini 2.0 Flash Exp)
│ (ADK LlmAgent) │ [Orchestrates 3 sub-agents]
└────────┬─────────┘
│
├────► Partner Agent (Phase-aware improv partner)
│ - Phase 1: Supportive "Yes, and..."
│ - Phase 2: Fallible, realistic friction
│
├────► Room Agent (Audience sentiment & vibe)
│ - Sentiment analysis tools
│ - Demographic simulation
│
└────► Coach Agent (Expert feedback)
- Improv principles database
- Constructive coaching
All agents backed by:
- ADK DatabaseSessionService (session persistence)
- ADK MemoryService (cross-session learning)
- ADK CloudTraceCallback (observability)
- Singleton InMemoryRunner (efficient execution)
The application implements two different orchestration architectures based on user tier:
HTTP-based request/response model with multi-agent orchestration:
Architecture:
- Single Singleton Runner: One shared
InMemoryRunnerinstance across all text sessions - Stage Manager Orchestration: Root agent coordinates 4 sub-agents per turn
- Synchronous Turn Execution: HTTP POST to
/session/{id}/turntriggers full agent workflow - Simple Agent Flow: MC → Partner → Room → Coach (all on every turn)
- Separate Room Agent: Dedicated Room Agent provides audience text reactions and mood visualization
Audience Reactions:
- Room Agent emits text reactions that appear in the chat (e.g., audience suggestions, reactions)
- Background color changes reflect audience sentiment (coral for laughter, warm amber for excitement)
- Distinct separation between Partner Agent dialogue and audience feedback
Characteristics:
- ✅ Lower complexity - proven HTTP patterns
- ✅ Easier to debug and monitor
- ✅ Lower cost per session
- ✅ All agents participate on every turn
- ✅ Clear separation of audience vs scene partner
⚠️ Higher latency (2-4 seconds per turn)⚠️ No real-time interaction
Code Location: app/services/turn_orchestrator.py
WebSocket-based streaming with unified MC agent (simplified in IQS-63):
Architecture:
- Per-Session Runner: Each audio session gets its own
Runnerinstance for isolation - Single MC Agent: One unified MC agent handles both hosting AND scene work per session
- Live API Integration: Uses ADK's
run_live()for real-time bidirectional audio streaming - Push-to-Talk: Manual activity signals control user speech (no automatic VAD)
- Simple Turn Counting:
AgentTurnManagertracks turn count and phase transitions - Voice Synthesis: Real-time text-to-speech with MC voice configuration
- MC-Consolidated Audience Vibes: MC naturally weaves audience reactions into speech
Audience Reactions (Consolidated into MC):
- MC verbally incorporates audience reactions: "The crowd is loving this!", "That got a big laugh!"
- Audio orchestrator detects these phrases in MC transcriptions and triggers mood visualization
- Same visual mood feedback (background color changes) as text mode, but through MC's natural speech
- No separate Room Agent needed - simplifies architecture while maintaining user experience
| MC Phrase Type | Sentiment | Engagement | Visual Effect |
|---|---|---|---|
| Laughter | 0.9 | 0.95 | Coral flash |
| Excitement | 0.8 | 0.9 | Warm Amber |
| Tension | 0.6 | 0.85 | Subtle shift |
| Engagement | 0.7 | 0.75 | Soft change |
Key Design Decisions (IQS-63):
- Unified MC Agent: MC handles game hosting, scene partner work, and suggestions - no agent switching
- Session Isolation: Each session gets its own MC agent instance to prevent cross-talk
- Simplified State: Only track turn count and phase - no agent handoffs or coordination
- Single Audio Stream: One voice (MC) for consistent user experience
- MC-Driven Mood: Audience vibe extracted from MC speech rather than separate agent
Characteristics:
- 🎤 Real-time voice interaction with single MC voice
- ✅ Simple architecture - one agent per session
- ✅ No agent handoffs or coordination complexity
- ✅ Lower latency (~1 second response time)
- ✅ Reduced API costs (~67% reduction from previous multi-agent design)
- ✅ Same visual mood feedback as text mode
- 💰 Premium-only feature (tier-gated)
Code Locations:
- Main:
app/audio/audio_orchestrator.py - WebSocket Handler:
app/audio/websocket_handler.py - Turn Management:
app/audio/turn_manager.py - Voice Config:
app/audio/voice_config.py
| Aspect | Text Mode (Regular) | Audio Mode (Premium) |
|---|---|---|
| Transport | HTTP POST | WebSocket |
| Runner | 1 singleton shared | 1 per session |
| Agents | Stage Manager + 4 sub-agents | Single MC agent |
| Latency | 2-4 seconds | ~1 second |
| Interaction | Turn-based | Real-time streaming |
| Audio | None | PCM16 bidirectional streaming |
| Agent Coordination | Stage Manager orchestrates | None (single agent) |
| Audience Reactions | Separate Room Agent emits text | MC weaves reactions into speech |
| Mood Visualization | Room Agent triggers color changes | MC phrases trigger color changes |
| Memory Overhead | Low | Moderate (per-session agent) |
| Cost | ~$0.20/session | ~$0.60/session |
| Complexity | Moderate | Low-Moderate |
| Phase Transitions | Yes | Yes (same logic) |
Text Mode (Default):
- Initial user onboarding
- Cost-sensitive deployments
- Mobile/low-bandwidth scenarios
- Testing and development
- All user tiers (free, regular, premium)
Audio Mode (Premium Feature):
- Premium users seeking immersive voice experience
- Natural conversation practice
- Real-time improv sessions
- Users with stable internet connections
- Application-Level OAuth 2.0: Google Sign-In with secure httponly cookies (no IAP required)
- Per-User Rate Limiting: 10 sessions/day, 3 concurrent sessions
- ADK Session Persistence:
DatabaseSessionServicewith SQLite backend - Cross-Session Memory:
VertexAiRagMemoryServicefor personalized learning - Native Observability: ADK
CloudTraceCallbackauto-instrumentation - Efficient Agent Execution: Singleton
InMemoryRunnerpattern - Health Checks: Load balancer integration with readiness probes
- Structured Logging: Cloud Logging-compatible JSON logs
- Auto-Scaling: Serverless Cloud Run with automatic scaling
- Security: Workload Identity for service-to-service auth (no API keys)
- OAuth Gating: Prevents anonymous abuse of LLM services
- Rate Limiting: Per-user session limits prevent runaway costs
- Model Optimization: Strategic use of Gemini Flash vs Pro
- Budget Target: <$200/month for pilot (10-50 users)
- Secure Session Management: Signed, httponly session cookies with 24-hour expiration
- Transactional Updates: Race-condition-safe Firestore operations
- Retry Logic: Exponential backoff for VertexAI calls
- Graceful Degradation: Clear error messages for quota/timeout issues
- Google Cloud Platform account with billing enabled
- Domain name (e.g., ai4joy.org)
- gcloud CLI installed
- Terraform >= 1.5
- Python >= 3.11
# 1. Clone the repository
git clone https://github.com/yourusername/ai4joy.git
cd ai4joy
# 2. Set environment variables
export PROJECT_ID="your-gcp-project-id"
export BILLING_ACCOUNT_ID="your-billing-account-id"
# 3. Run setup script
./scripts/setup.sh
# 4. Create OAuth 2.0 credentials and secrets (manual step)
# Visit: https://console.cloud.google.com/apis/credentials
# Create OAuth client ID, add credentials to Secret Manager
# See docs/OAUTH_GUIDE.md for detailed instructions
# 5. Configure Terraform variables
cd infrastructure/terraform
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your settings
# 6. Deploy infrastructure
terraform init
terraform apply
# 7. Configure DNS at your domain registrar
# Use nameservers from: terraform output dns_nameservers
# 8. Build and deploy application (after DNS propagates)
cd ../..
./scripts/deploy.sh# 1. Create virtual environment
python3 -m venv venv
source venv/bin/activate
# 2. Install dependencies
pip install -r requirements.txt
# 3. Set environment variables
cp .env.example .env
# Edit .env with your local configuration
# 4. Run Firestore emulator (optional)
gcloud emulators firestore start
# 5. Run application
cd app
uvicorn main:app --reload --port 8080
# 6. Test authentication flow
# Visit http://localhost:8080/auth/login to test OAuth
curl http://localhost:8080/health # No auth required for healthai4joy/
├── app/ # FastAPI application
│ ├── main.py # Application entry point
│ ├── config.py # Configuration management
│ ├── middleware/ # OAuth session middleware
│ │ └── oauth_auth.py # OAuthSessionMiddleware
│ ├── models/ # Pydantic data models
│ ├── routers/ # API endpoints
│ │ ├── auth.py # OAuth endpoints (/auth/login, /callback, /logout)
│ │ └── sessions.py # Session management
│ ├── services/ # Business logic
│ │ ├── rate_limiter.py # Per-user rate limiting
│ │ ├── session_manager.py # Session persistence
│ │ └── adk_agent.py # ADK agent integration
│ └── utils/ # Utilities (logging, etc.)
│
├── infrastructure/
│ └── terraform/ # Terraform IaC
│ ├── main.tf # Infrastructure definition
│ ├── variables.tf # Input variables
│ └── outputs.tf # Output values
│
├── tests/ # Test suites
│ ├── test_oauth.py # Application-level OAuth tests
│ ├── test_rate_limiting.py # Rate limit tests
│ └── test_infrastructure.py # Infrastructure validation
│
├── scripts/ # Operational scripts
│ ├── setup.sh # Initial GCP setup
│ ├── deploy.sh # Application deployment
│ ├── rollback.sh # Rollback to previous revision
│ ├── seed_firestore_tool_data.py # Seed Firestore with tool data
│ ├── manage_users.py # User tier management
│ ├── reset_limits.py # Reset user rate limits
│ ├── logs.sh # View application logs
│ ├── smoke_test.py # Post-deployment validation
│ ├── test_local_app.sh # Local testing script
│ └── test_turn.py # Turn execution testing
│
├── docs/ # Documentation
│ ├── API_DOCUMENTATION.md
│ ├── DEPLOYMENT.md
│ ├── design_overview.md
│ ├── FIRESTORE_SCHEMA.md
│ └── OAUTH_GUIDE.md
│
├── .claude/ # Claude Code configuration
│ ├── agents/ # Specialized agents
│ └── commands/ # Custom slash commands
│
├── Dockerfile # Container definition
├── cloudbuild.yaml # CI/CD pipeline
├── requirements.txt # Python dependencies
└── README.md # This file
- Application README - Backend application, API endpoints, local development setup
- Deployment Guide - Complete deployment procedures and infrastructure setup
- OAuth Guide - OAuth 2.0 setup and user access management
- API Documentation - Complete API reference
- Firestore Schema - Database schema documentation
- Design Overview - Original vision and design philosophy
- Terraform README - Infrastructure as code configuration
- Testing Summary - Test strategy and results
- Manual Test Procedures - Manual testing steps
- Tests README - Testing guide and execution
The application uses Google Cloud Firestore for persistent storage across three primary domains:
1. sessions - Active Game Sessions
- Purpose: Stores active and completed improv game sessions with full conversation history
- Document ID: Auto-generated UUID (e.g.,
a1b2c3d4-e5f6-7890-abcd-ef1234567890) - Key Fields:
user_id,user_email- OAuth user identificationstatus-active,completed,abandonedcurrent_phase-PHASE_1_SUPPORT,PHASE_2_FALLIBLEturn_count- Number of completed turnsgame_type- Selected improv gamelocation- Scene locationconversation_history- Full turn-by-turn conversation with timestampsgame_state- Current phase, suggestion counts, performer tracking
- Usage: Session lifecycle management, conversation persistence, phase transitions
- Indexes:
user_id + created_at,status + created_at,user_id + status
2. user_limits - Rate Limiting & Cost Tracking
- Purpose: Per-user rate limiting and cost management
- Document ID: OAuth user ID (e.g.,
google-oauth2|1234567890) - Key Fields:
user_id,email- User identificationsessions_today- Daily session counter (resets midnight UTC)last_reset- Last daily reset timestampactive_sessions- Current concurrent session countactive_session_ids- List of active session IDstotal_sessions- All-time session countertotal_cost_estimate,daily_cost_today- Cost tracking in USDrate_limit_overrides- Custom limits for admins/testersflags-is_admin,is_tester,unlimited_sessions
- Usage: Rate limit enforcement (10/day, 3 concurrent), cost monitoring
- Indexes:
email,sessions_today + last_reset,daily_cost_today
3. users - User Profiles & Tier Management
- Purpose: User tier management (free, regular, premium) and access control
- Document ID: User email (e.g.,
user@example.com) - Key Fields:
email- Unique identifiertier-free,regular,premiumcreated_at,updated_at- Audit timestampscreated_by- Admin who created/migrated useraudio_enabled- Premium feature flag
- Usage: Tier-based feature gating (audio mode for premium only)
- Script:
scripts/manage_users.pyfor user management
These collections store static reference data seeded via scripts/seed_firestore_tool_data.py:
4. improv_games - Game Database
- Purpose: Available improv game formats with rules and constraints
- Fields:
id,name,description,rules,constraints,difficulty - Usage: MC Agent selects games for sessions
5. improv_principles - Coaching Database
- Purpose: Core improv principles for Coach Agent feedback
- Fields:
id,principle,description,examples,anti_patterns - Usage: Coach Agent provides principle-based feedback
6. audience_archetypes - Demographic Generator
- Purpose: Audience persona templates for Room Agent
- Fields:
id,archetype,traits,reactions,catchphrases - Usage: Room Agent simulates diverse audience reactions
7. sentiment_keywords - Sentiment Analysis
- Purpose: Keyword lists for sentiment analysis
- Fields:
id,keyword,sentiment(positive/negative/neutral),weight - Usage: Room Agent sentiment gauge for scene vibe
8. admin_config - Global Settings (Optional)
- Purpose: Application-wide configuration and circuit breakers
- Document ID:
rate_limits - Fields:
default_daily_session_limit,default_concurrent_session_limitmax_cost_per_user_per_dayemergency_circuit_breaker- Cost protection thresholdfeature_flags-rate_limiting_enabled,cost_tracking_enabled
- Usage: Global rate limit defaults, emergency controls
User Session Creation
↓
1. Check `user_limits` for rate limits
2. Create document in `sessions`
3. Increment counters in `user_limits`
↓
Turn Execution (Text Mode)
↓
4. Read `sessions` for conversation history
5. Query `improv_games`, `improv_principles` (tools)
6. Update `sessions` with new turn data
↓
Audio Session (Premium)
↓
7. Check `users` tier for audio access
8. Per-session agents query tool collections
9. Real-time updates to `sessions`
↓
Session Cleanup
↓
10. Update `sessions` status to completed
11. Decrement `user_limits.active_sessions`
12. Track cost in `user_limits`
# After infrastructure deployment, seed tool data collections
python scripts/seed_firestore_tool_data.py
# Manage user tiers
python scripts/manage_users.py add user@example.com premium
python scripts/manage_users.py list
# Reset rate limits (operations)
python scripts/reset_limits.py user_idSee FIRESTORE_SCHEMA.md for complete schema documentation including field types, security rules, and backup procedures.
The application is deployed to Google Cloud Run with the following components:
- Cloud Load Balancer - HTTPS termination and routing
- Cloud Run - Serverless container hosting with OAuth middleware
- Cloud Firestore - Session and rate limit storage
- VertexAI - Gemini model access
- Cloud DNS - Domain management
- Cloud Armor - Security policies
- Secret Manager - OAuth credentials and session secrets
The cloudbuild.yaml defines a fully automated pipeline:
- Run automated tests
- Build Docker container
- Scan for vulnerabilities
- Deploy to Cloud Run
- Run smoke tests
- Gradual rollout (25% → 50% → 100%)
- Automatic rollback on failure
# Build container
docker build -t gcr.io/${PROJECT_ID}/improv-olympics:latest .
# Push to Container Registry
docker push gcr.io/${PROJECT_ID}/improv-olympics:latest
# Deploy to Cloud Run
gcloud run deploy improv-olympics \
--image gcr.io/${PROJECT_ID}/improv-olympics:latest \
--platform managed \
--region us-central1 \
--allow-unauthenticated \ # OAuth handled by application middleware
--set-secrets OAUTH_CLIENT_ID=oauth-client-id:latest,OAUTH_CLIENT_SECRET=oauth-client-secret:latest# Install dependencies
pip install -r requirements.txt
# Install development tools
pip install pytest pytest-asyncio black flake8 mypy
# Format code
black app/
# Lint code
flake8 app/
# Type check
mypy app/Required environment variables (see .env.example):
GCP_PROJECT_ID- Your GCP project IDGCP_REGION- Deployment region (default: us-central1)FIRESTORE_DATABASE- Firestore database nameMODEL_NAME- Default Gemini model (gemini-1.5-flash)RATE_LIMIT_DAILY- Daily session limit per user (default: 10)RATE_LIMIT_CONCURRENT- Concurrent session limit (default: 3)OAUTH_CLIENT_ID- Google OAuth 2.0 client ID (from Secret Manager)OAUTH_CLIENT_SECRET- Google OAuth 2.0 client secret (from Secret Manager)SESSION_SECRET_KEY- Secret key for signing session cookies (from Secret Manager)ALLOWED_USERS- Comma-separated list of allowed user emails
Key endpoints:
GET /health- Health check (no auth required)GET /ready- Readiness check (validates dependencies)GET /auth/login- Initiate OAuth login flowGET /auth/callback- OAuth callback endpointGET /auth/logout- Clear session and logoutGET /auth/user- Get current user info (protected)POST /api/v1/session/start- Create new session (protected)POST /api/v1/session/{id}/message- Send message to agent (protected)GET /api/v1/session/{id}- Retrieve session state (protected)POST /api/v1/session/{id}/close- Close session (protected)
See app/README.md for complete API documentation.
# Run all tests
pytest tests/
# Run specific test suite
pytest tests/test_oauth.py
# Run with coverage
pytest --cov=app tests/- Unit Tests - Individual component testing
- Integration Tests - OAuth flow, rate limiting, Firestore
- Infrastructure Tests - Terraform validation, resource checks
- Manual Tests - End-to-end OAuth flow, production verification
# Test OAuth login flow
open http://localhost:8080/auth/login
# After authenticating, test protected endpoint with session cookie
curl http://localhost:8080/api/v1/session/start \
-H "Cookie: session=<your-session-cookie>" \
-H "Content-Type: application/json" \
-d '{"location": "Mars Colony"}'
# Get current user info
curl http://localhost:8080/auth/user \
-H "Cookie: session=<your-session-cookie>"The scripts/ directory contains operational utilities for deployment and maintenance. See DEPLOYMENT.md for complete documentation.
# Setup & Initialization
./scripts/setup.sh # One-time GCP setup
python scripts/seed_firestore_tool_data.py # Seed Firestore with tool data
# Deployment
./scripts/deploy.sh # Deploy application
./scripts/rollback.sh # Rollback deployment
# User Management
python scripts/manage_users.py add user@example.com premium
python scripts/manage_users.py list
python scripts/manage_users.py remove user@example.com
# Operations
python scripts/reset_limits.py user_id # Reset rate limits
./scripts/logs.sh tail # View logs
python scripts/smoke_test.py --url https://ai4joy.org # Post-deployment testsSee Deployment Scripts Documentation for detailed usage.
Authentication & Infrastructure (IQS-45)
- Application-Level OAuth 2.0 authentication with Google Sign-In
- Secure session management with httponly cookies and Secret Manager
- Per-user rate limiting (10 sessions/day, 3 concurrent)
- Health check endpoints
- Structured JSON logging
- Complete Terraform infrastructure
- Automated testing suite
Multi-Agent System (IQS-46 to IQS-48)
- 5 specialized ADK agents (Stage Manager, Partner, Room, Coach, MC)
- Phase-aware Partner Agent behavior
- Multi-agent orchestration via Stage Manager
- Sentiment analysis and audience simulation
- Improv coaching with principles database
ADK-First Architecture (IQS-49 to IQS-54)
- ADK
DatabaseSessionServicefor session persistence - ADK
VertexAiRagMemoryServicefor cross-session learning - ADK
CloudTraceCallbacknative observability - Singleton
InMemoryRunnerpattern for efficiency - ADK evaluation framework for agent quality testing
- All agents using
google.adk.agents.Agent - Comprehensive documentation updates
Phase 1: MVP Launch (Completed - IQS-45)
- OAuth authentication and rate limiting
- Infrastructure automation
- Single-agent skeleton deployment
Phase 2: Multi-Agent Implementation (Completed - IQS-46 to IQS-48)
- Stage Manager (multi-agent orchestrator)
- Partner Agent (phase-aware scene partner)
- Room Agent (audience simulation with sentiment tools)
- Coach Agent (feedback with improv principles)
- MC Agent (game introduction and context)
Phase 3: ADK-First Architecture (Completed - IQS-49 to IQS-54)
- ADK
DatabaseSessionServicefor session persistence - ADK
MemoryServicefor cross-session learning - ADK
CloudTraceCallbackfor native observability - Singleton
InMemoryRunnerpattern - ADK evaluation framework for agent quality testing
Phase 4: Production Optimization (Future)
- Streaming responses for real-time feedback
- Context compaction for long sessions
- Performance optimization and caching
- Advanced coaching features
- Mid-scene coaching options
This is currently a private project for pilot testing. Contribution guidelines will be published when the project enters public beta.
For issues or questions:
- Documentation: See the docs/ directory
- Issues: Create a GitHub issue (when repository is public)
- Contact: support@ai4joy.org
Copyright 2025 JP Antona. All rights reserved.
Project Status: 🟢 Production Ready (ADK-First Architecture Complete) Last Updated: 2025-11-30 Version: 2.0.0 (ADK-First)