pai-bot

module
v0.0.0-...-7eeefe3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: Apache-2.0

README ΒΆ

P&AI Bot

The AI learning companion that keeps students motivated

Open-source Β· Self-hostable Β· Model-agnostic Β· Chat-first

Quick Start Β· Features Β· Architecture Β· Deployment Β· Contributing

License Go Report Card Go Version Platforms


What is P&AI?

P&AI (Practice & AI) is a proactive AI learning agent that teaches students through chat. It doesn't wait for students to ask β€” it initiates study sessions, tracks mastery, schedules reviews, and keeps students motivated with battles, streaks, leaderboards, and purpose-driven progress.

Built on Pandai's years of proven engagement mechanics that have made learning fun for millions of students across Southeast Asia.

Content is commodity. Motivation is the moat.

What makes P&AI different?

Feature ChatGPT / Claude Khan Academy P&AI
Answers questions βœ… βœ… βœ…
Follows a curriculum ❌ βœ… βœ…
Structured step-by-step solving ❌ Partial βœ…
Adapts explanation to mastery level ❌ ❌ βœ…
Cites curriculum source in responses ❌ ❌ βœ…
Tracks mastery per topic ❌ βœ… βœ…
Generates exam-style practice questions ❌ ❌ βœ…
Proactive β€” initiates sessions ❌ ❌ βœ…
Spaced repetition scheduling ❌ ❌ βœ…
Battles, streaks, leaderboards ❌ ❌ βœ…
Model-agnostic (swap AI providers) ❌ ❌ βœ…
Self-hostable ❌ ❌ βœ…
Works on $50 phones via Telegram ❌ ❌ βœ…
Open source ❌ ❌ βœ…

Quick Start

Get P&AI running in under 5 minutes.

Prerequisites

  • Docker and Docker Compose (v2+)
  • A Telegram bot token (get one from @BotFather)
  • At least one AI provider API key (OpenAI, Anthropic, or use free self-hosted Ollama)

1. Clone and configure

git clone --recurse-submodules https://github.com/p-n-ai/pai-bot.git
cd pai-bot
git submodule update --init --recursive
cp .env.example .env

Edit .env with your credentials:

# Required
LEARN_TELEGRAM_BOT_TOKEN=your-telegram-bot-token

# AI Providers (at least one required)
LEARN_AI_DEFAULT_PROVIDER=openrouter
LEARN_AI_OPENROUTER_API_KEY=sk-or-v1-...
LEARN_AI_OPENROUTER_MODEL=qwen/qwen3-max

# Or use free self-hosted AI (no API key needed)
LEARN_AI_DEFAULT_PROVIDER=ollama
LEARN_AI_OLLAMA_ENABLED=true
LEARN_AI_OLLAMA_MODEL=qwen3

2. Start everything

docker compose up -d

This starts: PostgreSQL, Dragonfly (cache), NATS (messaging), the Go server, and the admin panel.

If you want demo rows in PostgreSQL for local testing, run:

just seed

If the app is running in Docker, seed through the app container instead:

just seed-docker

When the backend is running in Docker, make sure .env uses Compose service names such as postgres, dragonfly, and nats instead of localhost. The app service already reads .env, so school admins can choose AI provider and default model purely with Docker env vars. For Ollama, Compose overrides LEARN_AI_OLLAMA_URL inside the app container to http://ollama:11434.

3. Pull a free AI model (optional)

Only do this if you are using Ollama as your AI provider. This downloads the model weights into the Ollama container so the app has something local to run.

Warning: this can be a large download and may take time depending on the model and network speed.

docker compose exec ollama ollama pull qwen3

After that, set LEARN_AI_OLLAMA_ENABLED=true and optionally LEARN_AI_OLLAMA_MODEL=qwen3 in .env.

4. Chat with your bot

Open Telegram, find your bot, and send /start. That's it β€” you're learning.

5. Access the admin panel

Open http://localhost:3000 to access the admin panel. Current scaffolding keeps the shell publicly reachable in local development, but the planned production model is invite-based account activation followed by email + password login for teacher, parent, and admin roles.

6. Browse the API docs

Open http://localhost:8080/docs for the Scalar-powered API reference. The raw OpenAPI document is served at http://localhost:8080/openapi.json and is generated directly from explicit Go request/response schemas.


Features

πŸŽ“ For Students

  • AI Tutor on Telegram β€” Learn any topic through natural chat conversation. The AI uses Socratic method, scaffolding, and growth mindset pedagogy.
  • Step-by-Step Problem Solving β€” Every math question is answered with a structured approach: Understand β†’ Plan β†’ Solve β†’ Verify β†’ Connect. Teaches students how to think, not just the answer.
  • Adaptive Explanations β€” The AI adjusts explanation complexity based on your mastery level. Beginners get simpler language and more examples; proficient students get concise explanations with harder challenges.
  • Curriculum-Cited Responses β€” Every explanation references the exact curriculum source (e.g., "KSSM Form 1 > Algebra > Linear Equations"), so students can find it in their textbook.
  • Proactive Study Sessions β€” The agent initiates conversations when it's time to review. Spaced repetition ensures long-term retention.
  • Progress Tracking β€” See mastery per topic, XP earned, streak length, and progress toward personal goals.
  • Quizzes & Assessments β€” Take quizzes in chat with deterministic grading for OSS-backed free-text answers, hints, and detailed feedback.
  • Exam-Style Practice β€” Current quiz content comes from OSS KSSM assessment sets reviewed against Algebra topics. Dynamic AI-generated UASA/SPM-style mimicry is planned, not yet live.
  • Peer Challenges β€” Battle classmates on the same set of questions. Learn together, compete for fun.
  • Goals & Streaks β€” Set a learning goal ("Master algebra by April") and track daily streaks.

πŸ‘©β€πŸ« For Teachers

  • Class Dashboard β€” Mastery heatmap showing every student's progress across every topic at a glance.
  • Student Detail View β€” Deep dive into any student: mastery radar, activity timeline, struggle areas, conversation summaries.
  • Nudge Students β€” One-click to have the AI send a personalized study prompt to a specific student.
  • Assign Topics β€” Direct the AI to teach a specific topic to a student or entire class. (Planned)
  • Weekly Leaderboards β€” Motivate the class with weekly rankings by mastery gain.

πŸ‘ͺ For Parents

  • Child Progress View β€” Simple dashboard showing weekly activity, topics studied, streak, and XP.
  • Weekly Reports β€” Automated weekly summary: what your child worked on, what they did well, and how you can help.

🏫 For Schools & Governments

  • Self-Hostable β€” Run on your own infrastructure. Full data sovereignty. No student data leaves your network.
  • Multi-Tenant β€” One deployment serves multiple schools, each with isolated data.
  • Token Budget Management β€” Allocate AI credits per school, per class, or per student. Automatic fallback to free self-hosted models when budget runs low.
  • Data Export β€” Export all student data as CSV/JSON at any time. Your data, your control.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Chat Channels                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚ Telegram β”‚ β”‚ WhatsApp β”‚ β”‚ WebSocketβ”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜             β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                     β–Ό                               β”‚
β”‚              Chat Gateway                           β”‚
β”‚                     β”‚                               β”‚
β”‚                     β–Ό                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚           Agent Engine                   β”‚       β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚       β”‚
β”‚  β”‚  β”‚ Conversation β”‚  β”‚ Proactive        β”‚  β”‚       β”‚
β”‚  β”‚  β”‚ State Machineβ”‚  β”‚ Scheduler (NATS) β”‚  β”‚       β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚       β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚       β”‚
β”‚  β”‚  β”‚ Progress    β”‚  β”‚ Pedagogical      β”‚   β”‚       β”‚
β”‚  β”‚  β”‚ Tracker     β”‚  β”‚ Prompts          β”‚   β”‚       β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                         β”‚                           β”‚
β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚            β–Ό            β–Ό              β–Ό            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  AI Gateway   β”‚ β”‚Curriculumβ”‚ β”‚  PostgreSQL   β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚ β”‚ Service  β”‚ β”‚  + Dragonfly  β”‚   β”‚
β”‚  β”‚  β”‚OpenAI   β”‚  β”‚ β”‚  (OSS)   β”‚ β”‚               β”‚   β”‚
β”‚  β”‚  β”‚Anthropicβ”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”‚  β”‚Ollama   β”‚  β”‚                                  β”‚
β”‚  β”‚  β”‚Custom   β”‚  β”‚                                  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                                  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β”‚                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚  Admin Panel (Next.js + TanStack Query)  β”‚       β”‚
β”‚  β”‚  Teacher Dashboard Β· Parent View Β· Admin β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tech Stack

Component Technology Why
Backend Go 1.22+ (stdlib) Goroutines handle millions of concurrent connections. Single binary, ~15MB.
Database PostgreSQL 17 Standard, portable. Every cloud has managed Postgres.
Cache Dragonfly Redis-compatible, multi-threaded, 80% less memory.
Messaging NATS + JetStream Proactive nudge scheduling, background jobs, event-driven communication.
AI Providers OpenAI, Anthropic, Ollama, OpenRouter Provider-agnostic gateway. Swap models without code changes.
Chat Telegram Bot API, WhatsApp Cloud API, WebSocket Works on $50 phones, 2G connections, zero data cost in many countries.
Admin Panel Next.js 16, TypeScript, TanStack Query, shadcn/ui Teacher dashboards, parent views, school admin.
Curriculum Open School Syllabus Structured YAML curriculum consumed by the agent.
Deployment Docker Compose or Helm Single server ($20/mo) to national deployment (millions of students).

Current Admin Auth

  • Teachers, parents, school admins, and platform admins sign in through /login; visiting / routes signed-in users to their workspace and everyone else to the login flow.
  • Ongoing login uses email + password; if the same email belongs to multiple schools, the UI asks the user to pick the correct school before finishing sign-in.
  • The Go backend owns admin auth with one server session cookie (pai_session); bearer JWT parsing remains only as a compatibility lane.
  • Students continue to access P&AI primarily through Telegram; a student web login is not part of the current baseline.

Project Structure

pai-bot/
β”œβ”€β”€ cmd/
β”‚   β”œβ”€β”€ server/main.go               # Application entrypoint
β”‚   β”œβ”€β”€ seed/main.go                 # Demo data seeder
β”‚   β”œβ”€β”€ terminal-chat/main.go        # Terminal chat for testing
β”‚   └── terminal-nudge/main.go       # Terminal nudge for testing
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ ai/                          # AI Gateway
β”‚   β”‚   β”œβ”€β”€ gateway.go               # Provider interface + types
β”‚   β”‚   β”œβ”€β”€ router.go                # Model routing + fallback chain + circuit breaker
β”‚   β”‚   β”œβ”€β”€ budget.go                # Token budget tracking (in-memory)
β”‚   β”‚   β”œβ”€β”€ provider_openai.go       # OpenAI + DeepSeek (compatible API)
β”‚   β”‚   β”œβ”€β”€ provider_anthropic.go    # Anthropic Claude
β”‚   β”‚   β”œβ”€β”€ provider_google.go       # Google Gemini
β”‚   β”‚   β”œβ”€β”€ provider_ollama.go       # Self-hosted (Llama, Qwen, etc.)
β”‚   β”‚   └── provider_openrouter.go   # 100+ models via OpenRouter
β”‚   β”œβ”€β”€ agent/                       # Agent Engine
β”‚   β”‚   β”œβ”€β”€ engine.go                # Conversation state machine
β”‚   β”‚   β”œβ”€β”€ scheduler.go             # Proactive nudge scheduler
β”‚   β”‚   β”œβ”€β”€ quiz.go                  # Quiz engine + assessment
β”‚   β”‚   β”œβ”€β”€ challenge.go             # Peer battle system
β”‚   β”‚   β”œβ”€β”€ challenge_runtime.go     # Challenge gameplay + settlement
β”‚   β”‚   └── goals.go                 # Goal tracking
β”‚   β”œβ”€β”€ chat/                        # Chat Gateway
β”‚   β”‚   β”œβ”€β”€ gateway.go               # Unified message routing
β”‚   β”‚   β”œβ”€β”€ telegram.go              # Telegram Bot API adapter
β”‚   β”‚   └── websocket.go             # WebSocket adapter
β”‚   β”œβ”€β”€ curriculum/                   # Curriculum Service
β”‚   β”‚   β”œβ”€β”€ loader.go                # Reads YAML from OSS repository
β”‚   β”‚   β”œβ”€β”€ types.go                 # Go structs matching OSS schema
β”‚   β”‚   └── prerequisites.go         # Prerequisite graph
β”‚   β”œβ”€β”€ progress/                    # Progress Tracker
β”‚   β”‚   β”œβ”€β”€ tracker.go               # Mastery scoring
β”‚   β”‚   β”œβ”€β”€ spaced_rep.go            # SM-2 algorithm
β”‚   β”‚   β”œβ”€β”€ streaks.go               # Streak tracking
β”‚   β”‚   └── xp.go                    # XP system
β”‚   β”œβ”€β”€ auth/                        # Authentication
β”‚   β”‚   β”œβ”€β”€ jwt.go                   # Token generation + validation
β”‚   β”‚   β”œβ”€β”€ middleware.go            # Role-based access control
β”‚   β”‚   β”œβ”€β”€ google_oidc.go           # Google OIDC sign-in
β”‚   β”‚   └── service.go              # Login, invites, sessions
β”‚   β”œβ”€β”€ adminapi/                    # Admin REST API
β”‚   β”œβ”€β”€ retrieval/                   # BM25 knowledge retrieval
β”‚   β”œβ”€β”€ tenant/                      # Multi-tenancy bootstrap
β”‚   β”œβ”€β”€ i18n/                        # Internationalization (BM/EN/ZH)
β”‚   └── platform/                    # Shared infrastructure
β”‚       β”œβ”€β”€ config/                  # Environment configuration
β”‚       β”œβ”€β”€ database/                # PostgreSQL connection (pgx)
β”‚       β”œβ”€β”€ cache/                   # Dragonfly client (go-redis)
β”‚       β”œβ”€β”€ mailer/                  # SMTP email delivery
β”‚       └── seed/                    # Demo data seeding
β”œβ”€β”€ admin/                           # Legacy Next.js admin panel
β”œβ”€β”€ admin-spa/                       # Vite/TanStack admin SPA
β”‚   └── src/
β”‚       β”œβ”€β”€ routes/                  # TanStack Router routes
β”‚       └── components/              # Admin UI components (shadcn/ui)
β”œβ”€β”€ migrations/                      # SQL migration files (goose)
β”œβ”€β”€ deploy/
β”‚   β”œβ”€β”€ docker/
β”‚   β”‚   β”œβ”€β”€ Dockerfile               # Multi-stage Go build
β”‚   β”‚   └── Dockerfile.admin         # Multi-stage Next.js build
β”‚   β”œβ”€β”€ caddy/                       # Reverse proxy config
β”‚   └── nginx/                       # Alternative reverse proxy
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ setup.sh                     # First-time setup wizard
β”‚   β”œβ”€β”€ deploy-remote.sh             # Production deployment
β”‚   └── analytics.sh                 # Quick metrics from CLI
β”œβ”€β”€ docker-compose.yml               # Local development
β”œβ”€β”€ docker-compose.prod.yml          # Production single-server
β”œβ”€β”€ justfile                         # Preferred task runner
β”œβ”€β”€ .env.example                     # All configuration documented
└── .github/workflows/               # CI pipeline

AI Providers

P&AI is not locked to any AI model. Configure one or more providers:

Provider Models Cost Setup
OpenAI GPT-5.4, GPT-5.4 mini Paid API Set LEARN_AI_OPENAI_API_KEY and optionally LEARN_AI_OPENAI_MODEL
Anthropic Claude Sonnet 4.6, Claude Haiku 4.5 Paid API Set LEARN_AI_ANTHROPIC_API_KEY and optionally LEARN_AI_ANTHROPIC_MODEL
DeepSeek DeepSeek-V3.2 (deepseek-chat), DeepSeek-R1 (deepseek-reasoner) Paid API (very cheap) Set LEARN_AI_DEEPSEEK_API_KEY and optionally LEARN_AI_DEEPSEEK_MODEL
Google Gemini Gemini 3 Flash Preview, Gemini 3 Pro Preview Paid API Set LEARN_AI_GOOGLE_API_KEY and optionally LEARN_AI_GOOGLE_MODEL
Ollama Qwen3, Qwen3 14B, Qwen3 30B Free (self-hosted) Set LEARN_AI_OLLAMA_ENABLED=true and optionally LEARN_AI_OLLAMA_MODEL
OpenRouter Qwen3 Max, Qwen3 Coder Next, 100+ others Varies Set LEARN_AI_OPENROUTER_API_KEY and optionally LEARN_AI_OPENROUTER_MODEL

DeepSeek uses the OpenAI-compatible API format β€” no extra code, just a different API key and base URL. Its official deepseek-chat alias already tracks the current DeepSeek-V3.2 non-thinking model. Gemini 3 models are the latest family, but note that the current Flash/Pro API IDs are preview models. Preview Gemini IDs can have different or tighter rate limits, so for steadier production behavior it is usually safer to set LEARN_AI_GOOGLE_MODEL to a non-preview model name such as gemini-2.5-flash. Qwen, Kimi, and other models are accessible via OpenRouter or self-hosted via Ollama.

To prefer one provider first, set LEARN_AI_DEFAULT_PROVIDER to one of: openai, anthropic, deepseek, google, ollama, openrouter.

The AI Gateway automatically routes by task type:

  • Teaching (complex explanations) β†’ Best available model (Claude Sonnet, GPT-4o, Gemini Pro)
  • Grading (quick JSON responses) β†’ Cheapest model (DeepSeek V3, GPT-4o-mini, Gemini Flash)
  • Question generation (dynamic quiz/exam-style) β†’ Cheapest model (DeepSeek V3, GPT-4o-mini)
  • Nudges (short messages) β†’ Any available model
  • Fallback β†’ Self-hosted Ollama (always free)

When paid API budgets run low, the system automatically degrades to cheaper models, then to self-hosted. No student is ever cut off from learning.


Supported Curricula

P&AI reads structured curriculum data from the Open School Syllabus (OSS) repository.

Currently supported:

Curriculum Subjects Status
Malaysia KSSM Form 1 Matematik (Algebra) Live
Malaysia KSSM Form 2 Matematik (Algebra) Live
Malaysia KSSM Form 3 Matematik (Algebra) Live
Cambridge IGCSE 0580 Mathematics Planned
More coming β€” contributions welcome!

Adding a new curriculum doesn't require code changes β€” just add YAML files to the OSS repository and P&AI picks them up automatically. See the OSS contribution guide.

Updating OSS Submodule Pointer

To sync to the latest oss commit from its default branch:

git submodule update --remote oss

Note: the submodule wiring is currently a bootstrap stub for upcoming curriculum sync work, not a finalized end-user feature.


Deployment

Option 1: Single Server (Docker Compose)

For a single school or small deployment. Runs on any VPS with 2GB+ RAM.

git clone https://github.com/p-n-ai/pai-bot.git
cd pai-bot
./scripts/setup.sh     # Interactive setup wizard
docker compose up -d   # Start everything

Cost: ~$20/month on any VPS provider. Supports 100-500 students.

Option 2: Kubernetes (Helm)

For districts, states, or national deployments. A Helm chart is available at deploy/helm/pai/.

helm install pai deploy/helm/pai \
  --set secrets.telegramBotToken=YOUR_TOKEN \
  --set secrets.ai.openaiApiKey=YOUR_KEY \
  --set secrets.authSecret=$(openssl rand -hex 16) \
  --set ingress.enabled=true \
  --set ingress.host=learn.yourschool.edu.my

See docs/ops/deployment.md for full configuration, local testing with k3d, and external database setup.

Scales: Horizontally to millions of students. Each school gets a namespace with isolated data.

Option 3: Cloud-Agnostic

P&AI is designed to run on any cloud without lock-in:

Component AWS GCP Azure Self-Hosted
Compute EKS GKE AKS Any K8s
Database RDS PostgreSQL Cloud SQL Azure DB PostgreSQL
Cache (self-hosted Dragonfly) (self-hosted) (self-hosted) Dragonfly/Redis
Messaging (self-hosted NATS) (self-hosted) (self-hosted) NATS
Storage S3 GCS Blob MinIO

Configuration Reference

Configuration is environment-driven. Core app variables use LEARN_; auth variables use PAI_AUTH_ only. See .env.example for the complete list.

Variable Required Default Description
LEARN_TELEGRAM_BOT_TOKEN Yes β€” Telegram bot token from @BotFather
LEARN_DATABASE_URL No postgres://pai:pai@localhost:5432/pai PostgreSQL connection string
LEARN_CACHE_URL No redis://localhost:6379 Dragonfly/Redis connection
LEARN_NATS_URL No nats://localhost:4222 NATS messaging server
LEARN_AI_DEFAULT_PROVIDER No β€” Preferred provider to try first (openai, anthropic, deepseek, google, ollama, openrouter)
LEARN_AI_OPENAI_API_KEY No* β€” OpenAI API key
LEARN_AI_OPENAI_MODEL No β€” Default OpenAI model when request model is not set
LEARN_AI_ANTHROPIC_API_KEY No* β€” Anthropic API key
LEARN_AI_ANTHROPIC_MODEL No β€” Default Anthropic model when request model is not set
LEARN_AI_DEEPSEEK_API_KEY No* β€” DeepSeek API key (OpenAI-compatible)
LEARN_AI_DEEPSEEK_MODEL No β€” Default DeepSeek model when request model is not set
LEARN_AI_GOOGLE_API_KEY No* β€” Google Gemini API key
LEARN_AI_GOOGLE_MODEL No β€” Default Google model when request model is not set
LEARN_AI_OPENROUTER_API_KEY No* β€” OpenRouter API key (100+ models)
LEARN_AI_OPENROUTER_MODEL No β€” Default OpenRouter model when request model is not set
LEARN_AI_OLLAMA_ENABLED No* false Enable self-hosted Ollama
LEARN_AI_OLLAMA_URL No http://localhost:11434 Ollama server URL
LEARN_AI_OLLAMA_MODEL No β€” Default Ollama model when request model is not set
LEARN_AI_PERSONALIZED_NUDGES_ENABLED No true Let AI personalize proactive nudge messages; falls back to template text on failure
PAI_AUTH_SECRET No change-me-in-production Root auth secret; currently used for JWT signing
LEARN_SERVER_PORT No 8080 HTTP server port
LEARN_TENANT_MODE No single single or multi tenant mode

*At least one AI provider must be configured.

First-Boot Tenant Flow

The first setup behavior depends on LEARN_TENANT_MODE:

  • single mode:
    • On server startup, P&AI ensures tenant slug default exists.
    • If it is missing (for example, on a fresh DB), startup will auto-create/upsert it.
    • Tenant-bound runtime services use this single tenant context.
  • multi mode:
    • Startup does not auto-create tenants.
    • Tenant lifecycle is managed explicitly (seed/admin/invite workflows).

Recommended first setup sequence:

  1. Run migrations.
  2. Set LEARN_TENANT_MODE in .env.
  3. Start the server.

Development

Prerequisites

  • Go 1.22+
  • Node.js 20+ (for admin panel)
  • Docker and Docker Compose

Local Development

Note: just recipes are supported on macOS/Linux for now. On Windows, prefer Docker/WSL2 instead of just go / just next.

just go / just next require LEARN_DATABASE_URL to be present in .env; the local bootstrap path no longer falls back to an implicit default DSN or shell override.

# Start infrastructure (Postgres, Dragonfly, NATS, Ollama)
docker compose up -d postgres dragonfly nats ollama

# Run database migrations
just migrate

# Check the current migration version
just migrate-version

# Seed demo data (optional)
just seed

# Or, if the app itself is running in Docker
just seed-docker

# Start the Go server (turnkey deps + local Postgres/Dragonfly; auto-seeds only for the default local dev DB target)
just go

# Start the admin panel + Agentation MCP, and try to boot the Go server if needed
# If backend boot fails, Next.js still starts; check /tmp/pai-go.log for backend errors
# Ctrl-C also stops backend + Agentation started by this command
just next

# Start Google auth emulator + backend + admin + Agentation through one wrapper script
# Good target for Codex app "play" / run-button flows
./scripts/run-dev.sh

# Stop docker services plus local backend/frontend/Agentation listeners
just stop

# Stop only the local run-dev.sh processes
./scripts/stop-dev.sh

Running Tests

go test ./...     # Run all Go tests
go test -tags=integration ./...   # Run integration tests
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@"${GOLANGCI_LINT_VERSION:-v2.4.0}" run ./...
cd admin && pnpm test      # Admin unit + component tests
cd admin && pnpm test:e2e  # Admin Playwright smoke tests
just admin-e2e             # Same Playwright run via just
just test-all              # Convenience gate: lint + Go tests + admin unit/component tests

Playwright first-run setup (install deps + Chromium) is documented in docs/ops/setup.md. Backend-dependent E2E tests are tagged @backend and are skipped by default unless E2E_BACKEND_ENABLED=true. Authenticated routes also require E2E_AUTH_ENABLED=true plus E2E_ADMIN_EMAIL and E2E_ADMIN_PASSWORD. These E2E_* variables are documented in .env.example.

OpenAI live conversation integration suite:

  • Fixture source: internal/agent/testdata/openai_live_conversations.yaml (30 scripted conversations, 2-10 turns each)
  • Test harness: internal/agent/engine_openai_integration_test.go (//go:build integration)
  • Required env for live run: LEARN_AI_OPENAI_API_KEY
  • Optional env:
    • LEARN_AI_LIVE_TIMEOUT_SECONDS (default 45)
    • LEARN_AI_LIVE_MAX_CASES (default 30)
  • CI behavior: the live OpenAI suite is explicitly skipped in CI (CI/GITHUB_ACTIONS detection) to avoid external paid API calls in pipeline runs.

Terminal chat workflow:

just chat-terminal
# or:
docker compose run --rm --entrypoint /pai-terminal-chat app --user-id demo-user --lang en
# for an ephemeral local-only session:
docker compose run --rm --entrypoint /pai-terminal-chat app --memory

The terminal chat uses the same agent.Engine and AI router as the app. By default it uses PostgreSQL-backed conversation state for production parity; pass --memory for an ephemeral local-only session.

Terminal nudge workflow:

just nudge-terminal USER_ID=demo-user
# or:
docker compose run --rm --entrypoint /pai-terminal-nudge app --user-id demo-user

The terminal nudge command triggers the real scheduler path for one user and prints any generated nudge message to stdout.

Useful Commands

just setup        # First-time setup
just install-deps # Install Go modules + frontend packages
just install-local-runtime  # Install missing Postgres client tools via Homebrew when available
just start        # Start all services via Docker Compose
just stop         # Stop all services
just logs         # Tail application logs
just migrate      # Run database migrations
just migrate-status   # Show applied/pending goose migrations
just migrate-version  # Show current goose migration version
just migrate-down # Roll back the most recent migration
just migration-create add_parent_invites  # Create a new timestamped SQL migration
just seed         # Seed demo tenant/users/messages/progress/events
just seed-docker  # Seed through the running app container
just analytics    # Print quick metrics from the database
just analytics-xlsx   # Export a styled Excel workbook to output/spreadsheet/
just analytics-example  # Generate a sample Excel workbook without a database
just ollama-pull  # Download a free AI model for Ollama
just chat-terminal  # Open a local terminal chat session
just nudge-terminal USER_ID=<user-id>  # Trigger a due-review nudge for one user

Excel export notes:

  • scripts/analytics.sh --xlsx output/spreadsheet/pai-analytics.xlsx keeps the terminal report and also writes a formatted workbook.
  • scripts/analytics.sh --example-xlsx output/spreadsheet/pai-analytics-example.xlsx creates a sample workbook for layout review without touching the database.
  • The analytics script loads .env automatically when present. When PAI_DB_URL is unset, it falls back to LEARN_DATABASE_URL from the app environment before using Docker Compose PostgreSQL.
  • The workbook builder now runs through go run ./cmd/analyticsxlsx, so there is no separate Python runtime or spreadsheet dependency to install.

Migration notes:

  • The repo now uses goose with single-file timestamped SQL migrations and goose_db_version tracking.
  • just migrate runs goose up -allow-missing so older timestamped migrations can still be applied after newer ones in out-of-order branch merges.
  • Existing databases from the pre-goose migration flow should be recreated in local dev or explicitly baselined before switching tools. Do not run both migration systems against the same database long-term.

Rating Analytics Contract

  • Rating callbacks use internal assistant message IDs in callback data: rating:{messages.id}:{score}.
  • Submitted ratings are logged in events as answer_rating_submitted with:
    • data.rating (1-5)
    • data.rated_message_id (assistant messages.id being rated)
    • data.source, data.channel, data.delayed_submit
  • Deduplication is enforced per rated assistant message (rated_message_id) to prevent duplicate submissions for the same prompt.

Contributing

We welcome contributions! P&AI is built by a community that believes every student deserves a patient, always-available learning companion.

Ways to contribute

  • Code β€” Pick up a good first issue or propose a feature.
  • Curriculum β€” Add topics, teaching notes, or assessments to OSS.
  • Translation β€” Help translate the bot's messages and admin panel.
  • Testing β€” Try P&AI with real students and report what works and what doesn't.
  • Documentation β€” Improve guides, fix typos, add examples.

Development workflow

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests (go test ./... and go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@"${GOLANGCI_LINT_VERSION:-v2.4.0}" run ./...)
  5. Commit (git commit -m 'Add amazing feature')
  6. Push to your branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

See docs/ops/setup.md for development environment setup.


Documentation

Document Description
Setup Guide Prerequisites, quick start, environment variables, common issues
Configuration Environment variable defaults and validation rules
Architecture Modular monolith design, domain packages, HTTP routing, infrastructure
AI Providers Provider configuration, fallback chain, structured output, budget enforcement
Curriculum YAML schema, teaching notes, assessments, adding new curricula
Deployment Docker Compose production, monitoring, backups
Admin Panel Dashboard features, roles, API specification
Admin Routes Admin frontend route and backend API map
Telegram Runtime Telegram Bot API polling, commands, media, and nudge behavior
Embed Chat Embeddable widget runtime and security boundaries
WhatsApp Runtime WhatsApp backend modes, env vars, and setup routes
OpenAPI and Scalar API docs surface and update rules
Local Tools Local helper binaries, scripts, and emulation tools
Technical Plan Detailed architecture, database schema, security model

Repository Description
p-n-ai/oss Open School Syllabus β€” structured curriculum data for any learning platform. See docs/curriculum-oss.md for how pai-bot consumes it.
p-n-ai/oss-bot GitHub bot + CLI tools for contributing to Open School Syllabus

License

P&AI Bot is licensed under the Apache License 2.0.

You are free to use, modify, and distribute this software. Self-host it for your school, fork it for your country, build a business on it. The only requirement is that you include the license notice.

Our promise: The core learning platform will always be free and open source. We will never sell student data or show ads.


Acknowledgments

P&AI is built on the shoulders of Pandai β€” years of making learning fun for millions of students through gamification, battles, leaderboards, and purpose-driven progress. The secret sauce has always been motivation, not content.


Every student deserves a patient, always-available learning companion.
A Pandai initiative. Built with ❀️ by educators and AI, for everyone.

Directories ΒΆ

Path Synopsis
cmd
analyticsxlsx command
seed command
server command
terminal-chat command
terminal-nudge command
internal
agent
Package agent implements the Agent Engine: conversation state machine, proactive scheduler, pedagogical prompts, quiz engine, and peer challenges.
Package agent implements the Agent Engine: conversation state machine, proactive scheduler, pedagogical prompts, quiz engine, and peer challenges.
ai
Package ai provides a provider-agnostic AI gateway with task-based routing.
Package ai provides a provider-agnostic AI gateway with task-based routing.
auth
Package auth implements JWT authentication and RBAC middleware.
Package auth implements JWT authentication and RBAC middleware.
chat
Package chat provides a unified interface for messaging channels (Telegram, WhatsApp, WebSocket).
Package chat provides a unified interface for messaging channels (Telegram, WhatsApp, WebSocket).
curriculum
Package curriculum loads structured curriculum YAML from the OSS repository.
Package curriculum loads structured curriculum YAML from the OSS repository.
platform/cache
Package cache provides a Dragonfly/Redis client wrapper.
Package cache provides a Dragonfly/Redis client wrapper.
platform/config
Package config loads application configuration from environment variables.
Package config loads application configuration from environment variables.
platform/database
Package database provides PostgreSQL connection management via pgx.
Package database provides PostgreSQL connection management via pgx.
platform/featureflags
Package featureflags owns deploy-time product and internal rollout gates.
Package featureflags owns deploy-time product and internal rollout gates.
progress
Package progress implements mastery scoring, SM-2 spaced repetition, streaks, and XP tracking.
Package progress implements mastery scoring, SM-2 spaced repetition, streaks, and XP tracking.
retrieval
Package retrieval provides a generic retrieval platform for the bot.
Package retrieval provides a generic retrieval platform for the bot.
tenant
Package tenant implements multi-tenancy isolation.
Package tenant implements multi-tenancy isolation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL